From c7b49b3722bf397e74b363b2b5c2c74972d4173b Mon Sep 17 00:00:00 2001
From: Pratik Bodkhe
Date: Mon, 20 Jul 2026 08:27:33 +0900
Subject: [PATCH] Download surface for the macOS companion
/download resolves the newest DMG from GitHub Releases at request time
(5-minute revalidate) and degrades to an honest coming-soon state while
no release exists, so the page never links a 404 or claims a build that
is not there. 404 is the one silent degradation; every other resolver
failure logs with rate-limit context, and GITHUB_TOKEN is used when set.
/download joins the middleware public paths (it previously bounced
logged-out visitors to /login), the landing page and the in-app
companion install prompt route through it, and it lands in the sitemap
and the public-route smoke check.
---
CHANGELOG.md | 1 +
e2e/smoke.spec.ts | 2 +-
src/app/download/page.tsx | 194 ++++++++++++++++++
src/app/page.tsx | 10 +
src/app/sitemap.ts | 6 +
.../minutia/companion-install-prompt.tsx | 4 +-
src/lib/desktop-download.ts | 73 +++++++
src/middleware.ts | 1 +
8 files changed, 287 insertions(+), 4 deletions(-)
create mode 100644 src/app/download/page.tsx
create mode 100644 src/lib/desktop-download.ts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e4619a..84fecb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
+- Public `/download` page for the Minutia macOS companion. It resolves the latest signed DMG from GitHub Releases at request time (cached hourly) and degrades to a "watch for the release" state until the first build ships, so it never links to a 404. Includes system requirements, an open-source link, and how-it-works steps. The landing page and the in-app companion prompt both point to it.
- Minutia Retro: a free, anonymous, multiplayer retrospective board at `/retro`. Guided 7-phase ritual (Lobby, Reflect, Reveal, Theme, Vote, Discuss, Commit) with realtime presence, a synchronized card-flip Reveal, and a closure bloom. Boards are ephemeral (30-day auto-expiry) and rate-limited.
- Anonymous board operations run through `SECURITY DEFINER` Postgres RPCs (default-deny `retro_*` tables); liveness uses Supabase Realtime broadcast and presence with a snapshot reconcile.
- AI theme-clustering suggestions during the Theme phase (OpenRouter; degrades silently when unconfigured).
diff --git a/e2e/smoke.spec.ts b/e2e/smoke.spec.ts
index c5e82a6..59c4e3b 100644
--- a/e2e/smoke.spec.ts
+++ b/e2e/smoke.spec.ts
@@ -34,7 +34,7 @@ test.describe("Smoke Tests", () => {
});
test("all public routes return valid responses", async ({ request }) => {
- const routes = ["/login"];
+ const routes = ["/login", "/download"];
for (const route of routes) {
const response = await request.get(route);
diff --git a/src/app/download/page.tsx b/src/app/download/page.tsx
new file mode 100644
index 0000000..62075a7
--- /dev/null
+++ b/src/app/download/page.tsx
@@ -0,0 +1,194 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { ArrowRight, Bell, Download, ExternalLink } from "lucide-react";
+import {
+ DESKTOP_RELEASES_URL,
+ DESKTOP_REPO_URL,
+ DESKTOP_REQUIREMENTS,
+ getDesktopRelease,
+ type DesktopRelease,
+} from "@/lib/desktop-download";
+
+export const metadata: Metadata = {
+ title: "Minutia for Mac",
+ description:
+ "Record your meetings from the menu bar. No bot joins the call. Recaps land in Minutia seconds after you hit stop.",
+};
+
+export const revalidate = 300;
+
+const steps = [
+ {
+ title: "Install and sign in",
+ description:
+ "Download the app and sign in with your Minutia account. It lives in the menu bar, out of your way.",
+ },
+ {
+ title: "Record from the menu bar",
+ description:
+ "Start a recording yourself, or let meeting detection prompt you the moment a call begins.",
+ },
+ {
+ title: "Stop and get the recap",
+ description:
+ "Hit stop and the recap opens in Minutia seconds later, complete with action items.",
+ },
+];
+
+function DownloadCta({
+ release,
+ variant,
+}: {
+ release: DesktopRelease;
+ variant: "ink" | "accent";
+}) {
+ const base =
+ "inline-flex items-center gap-2 rounded-md px-6 py-3 text-sm font-medium text-paper transition-colors";
+ const solid =
+ variant === "ink"
+ ? "bg-ink hover:bg-ink-2"
+ : "bg-accent hover:bg-accent-hover";
+
+ if (release.available) {
+ return (
+
+
+ Download for macOS
+
+ );
+ }
+
+ return (
+
+
+ Watch for the release
+
+ );
+}
+
+export default async function DownloadPage() {
+ const release = await getDesktopRelease();
+ const requirements = release.available
+ ? `${release.version} · ${DESKTOP_REQUIREMENTS}`
+ : DESKTOP_REQUIREMENTS;
+
+ return (
+
+ {/* ─── Hero ─── */}
+
+
+ Minutia for Mac
+
+
+ Record your meetings from the menu bar.
+
+
+ No bot joins the call. Minutia captures your mic and system audio
+ right from the menu bar, and the recap lands in your workspace seconds
+ after you hit stop.
+
+
+
+
+
{requirements}
+ {!release.available && (
+
+ Not shipped yet. Watch the repo and GitHub tells you the moment the
+ first signed build lands.
+
+ On a Mac?{" "}
+
+ Get the macOS companion
+
+
+
{/* ─── Features ─── */}
diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts
index e08b400..1f6140a 100644
--- a/src/app/sitemap.ts
+++ b/src/app/sitemap.ts
@@ -10,5 +10,11 @@ export default function sitemap(): MetadataRoute.Sitemap {
changeFrequency: "weekly",
priority: 1,
},
+ {
+ url: `${siteUrl}/download`,
+ lastModified: new Date(),
+ changeFrequency: "weekly",
+ priority: 0.8,
+ },
];
}
diff --git a/src/components/minutia/companion-install-prompt.tsx b/src/components/minutia/companion-install-prompt.tsx
index 06f5e59..6c42fbd 100644
--- a/src/components/minutia/companion-install-prompt.tsx
+++ b/src/components/minutia/companion-install-prompt.tsx
@@ -4,8 +4,6 @@ import * as React from "react";
import { X, Download } from "lucide-react";
const DISMISS_KEY = "minutia.companion-prompt-dismissed";
-const DOWNLOAD_URL =
- "https://github.com/shiprite-dev/minutia-desktop/releases/latest";
// Inline nudge shown near the recorder when the signed-in user has no companion
// app checked in yet (companion_last_seen_at is null) and has not dismissed it.
@@ -37,7 +35,7 @@ export function CompanionInstallPrompt({
For the best experience, download and install the companion app.