diff --git a/docs/superpowers/specs/2026-06-04-marketing-website-design.md b/docs/superpowers/specs/2026-06-04-marketing-website-design.md new file mode 100644 index 0000000..be77b6e --- /dev/null +++ b/docs/superpowers/specs/2026-06-04-marketing-website-design.md @@ -0,0 +1,200 @@ +# ClaudeDo distribution website — design + +**Date:** 2026-06-04 +**Status:** Approved (design), ready for implementation planning +**Repo:** new standalone repo `claudedo-web` (not part of the ClaudeDo app solution) +**Domain:** `claudedo.kuns.dev` (Coolify on the user's VPS) + +## Purpose + +Give friends a public place to download ClaudeDo and learn what it does, without +sending them to the Gitea repo — so the source repo can be made more private. The +site also fronts the app's self-updater so the Gitea URL is never exposed in the +app or on the page. + +## Goals / non-goals + +**Goals** +- Public, no-auth landing page at `claudedo.kuns.dev` that matches the app's visual identity. +- A primary download (installer `.exe`) plus the portable `.zip` and checksums. +- A release proxy that (a) feeds the page the current version and (b) serves the + app's self-updater the same JSON shape Gitea returns, with download URLs rewritten + to route through `claudedo.kuns.dev` — hiding Gitea entirely. + +**Non-goals** +- No docs site / getting-started page (the app ships an installer that handles setup). +- No changelog page (release notes already live on Gitea releases). +- No auth, accounts, analytics, or CMS. +- No CI/PR tooling for this repo beyond what Coolify needs to deploy. + +## Access & distribution decisions + +- **Access:** fully public. No password/login. Relies on the unadvertised URL. +- **Download source:** build-time fetch of the latest Gitea release for the displayed + version; actual download links route through the proxy and resolve the latest asset + at request time (so a stale page still downloads the current build). +- **Self-updater proxy:** in scope for v1 (not deferred). + +## Tech stack + +- **Nuxt 3** (Vue 3) — single framework, single repo, single Coolify deploy. +- **Nitro** server routes for the release proxy + asset streaming. +- **No DB, no auth, no secrets** (the `releases/ClaudeDo` repo is public). +- Fonts: **Inter Tight** (display/body) + **JetBrains Mono** (mono), self-hosted or via + Google Fonts. Design tokens ported from `docs/UI Rewrite/design_handoff_claudedo/Tokens.axaml` + and `styles.css` (moss/sage/peat palette, dark-first, 14px island radius, grain texture). + +## Concept: "the page IS the app" + +The landing page is a faithful, in-browser rendering of the ClaudeDo desktop — the +window chrome + the three islands — rather than a conventional marketing page. This +is the chosen direction (over a cinematic single-window scroll and a worklog feed). + +### Layout — three islands on the app "desktop" + +Desktop background = the app's layered moss gradients + 3px grain overlay. A centered +app `window` (titlebar + body) holds a 3-column island grid: + +1. **Lists island (left)** — repurposed as page nav. + - Header "Lists" + a decorative search box (`Ctrl K` kbd chip). + - "Pages" group: Overview · Features (6) · How it works · Screenshots (3) · Download, + each with a colored swatch dot; active item gets the accent left-bar. + - Footer styled like the app's user footer: avatar, "For friends", `claudedo.kuns.dev`. + +2. **Tasks island (middle)** — features rendered as **task cards**. + - Header: date eyebrow, big title (the hero line "Queue the work. Claude does it."), + a `running · review` badge, eye/gear icon buttons, and a subtitle. + - A decorative "Add a task…" row. + - Six **feature cards** (circle check — done cards filled; title; a status chip + `done`/`running`/`waiting for review`; a star). The features: + 1. Isolated worktrees + 2. The task queue + 3. Review & merge + 4. Live session log + 5. Per-list & per-task config + 6. Self-updating + - A "Ready" group with the final **"↓ Download ClaudeDo"** card. + +3. **Detail island (right)** — faithful to the reworked Task-Detail island. + - **Source of truth for the detail visuals:** `docs/superpowers/specs/2026-06-04-task-detail-redesign-design.md` + (the app's in-progress rework). The website's detail pane must track that design. + - Three-zone stack: + - **Task header** — mono id (`#F01…`), title, trash/gear action icons. + - **DETAILS bar** — `DETAILS` eyebrow + `Edit` / copy / `⋯`, then a **markdown body** + (headings, paragraphs, inline `code`, ordered/unordered lists) describing the feature. + - **WorkConsole** docked at the bottom — traffic-light dots, `· N turns · +x −y`, + tabs **Output / Actions / Session**, and a `Created …` footer. + - Per-feature mapping: + - Feature panels: markdown writeup in DETAILS + a short relevant **Output** log. + - "Review & merge": opens on the **Actions** tab with `Merge target` + `Open Diff` / + `Approve & merge`. + - **Download**: DETAILS shows requirements (`.NET 8 Desktop Runtime`, `Claude CLI`, + `Git`); the **Actions** tab holds the install controls, with `Merge target` + repurposed as a **Build** selector and buttons `↓ Download installer` / + `Portable .zip` / `checksums.txt`. + +4. **Statusbar (bottom)** — `● Online · claudedo.kuns.dev · private build`. + +### Interaction + +- Clicking a task card selects it (accent bar + card highlight) and swaps the active + detail panel; the WorkConsole tabs are clickable within a panel. +- **All panels are server-rendered and present in the DOM**, toggled by class — the + page is fully readable and downloadable **without JavaScript** (progressive + enhancement). Vue handles the selection state on the client. + +### Responsive + +- ≤ ~1100px: drop the Detail island; show Lists + Tasks. +- ≤ ~780px: single column — the Tasks list; tapping a feature pushes to a full-screen + Detail view (mirrors the app's narrow-window behavior) with a back affordance. + +## Server: release proxy (Nitro) + +The app's `ReleaseClient` (`src/ClaudeDo.Releases/ReleaseClient.cs`) calls +`{apiBase}/releases/latest` and reads `tag_name`, `name`, and +`assets[].browser_download_url`; `DownloadAsync` GETs an asset URL directly. + +- **`GET /api/releases/latest`** — fetches `https://git.kuns.dev/api/v1/repos/releases/ClaudeDo/releases/latest`, + returns the **same JSON shape**, but every `assets[].browser_download_url` is rewritten + from the Gitea URL to `https://claudedo.kuns.dev/api/download/`. + Cached briefly (e.g. 5 min) server-side. +- **`GET /api/download/[...path]`** — reconstructs the Gitea asset URL from the path and + **streams** the binary back (no redirect to Gitea, so the URL stays hidden). Sets + appropriate `Content-Type`/`Content-Disposition`. +- **`server/utils/gitea.ts`** — shared base URL (`GITEA_API`, `REPO` from env), fetch + helper, and the URL-rewrite/asset-path round-trip. +- The page's download buttons point at the same `/api/download/...` routes (with a + stable "latest installer" path), so links never go stale between deploys. + +### App-side coordinating change (separate, in the ClaudeDo repo) + +Point `ReleaseClient`'s `apiBase` at `https://claudedo.kuns.dev/api` instead of the +Gitea default (one-line DI change where `ReleaseClient`/`UpdateCheckService` are +constructed). Tracked as a follow-up; not part of the `claudedo-web` repo. The proxy +path (`/api/releases/latest`) is chosen to match the existing +`{apiBase}/releases/latest` call so the parser is untouched. + +## Content / assets + +- **Screenshots (provided):** main 3-column view (hero), diff review modal, worktrees + panel. Stored in `public/screenshots/`. Placeholders sized for them until dropped in. +- Copy: hero "Queue the work. Claude does it."; six feature writeups as above (final + wording during implementation). + +## Error handling + +- **Build-time release fetch fails:** render the page with a last-known/placeholder + version label; download buttons still work because they resolve via the runtime + proxy route. +- **Proxy `/api/releases/latest` upstream failure:** return a 502/`null`-equivalent the + way Gitea would on miss; the app's `UpdateCheckService` already treats null/exception + as `CheckFailed` and degrades gracefully. +- **`/api/download` upstream failure:** surface a 502; the button shows an error state. +- No retries beyond a single upstream attempt for v1 (low traffic, friends-only). + +## Testing + +- **Vitest** unit tests for `server/utils/gitea.ts`: URL rewrite (Gitea → proxy) and the + asset-path round-trip (proxy path → Gitea URL), and release-JSON shape preservation. +- A light component smoke test that the page renders the islands and the download + controls without JS errors. +- No real-network/Gitea calls in tests — mock the upstream fetch. + +## Deployment (Coolify) + +- **Dockerfile**: `node:20-alpine` build → `nuxt build` → run `.output/server/index.mjs`. +- Coolify app bound to `claudedo.kuns.dev` with TLS via its reverse proxy. +- Env: `GITEA_API` (default `https://git.kuns.dev/api/v1`), `REPO` (`releases/ClaudeDo`), + `PUBLIC_BASE_URL` (`https://claudedo.kuns.dev`) for URL rewriting. +- Deploy on push to `main`; re-deploy (or a periodic rebuild) refreshes the displayed + version. No PR/CI tooling beyond Coolify's build. + +## Open risk + +- The reworked Detail island in the app is still in flux. The website's detail pane + must be kept in sync with `2026-06-04-task-detail-redesign-design.md`; expect a + visual-polish pass once that rework lands. + +## Repo layout + +``` +claudedo-web/ +├── nuxt.config.ts +├── app.vue +├── pages/index.vue # the one landing page +├── components/ +│ ├── AppWindow.vue # window chrome + statusbar +│ ├── ListsIsland.vue # page nav +│ ├── TasksIsland.vue # feature cards + download card +│ ├── DetailIsland.vue # three-zone detail (header / DETAILS md / WorkConsole) +│ ├── WorkConsole.vue # tabs: Output / Actions / Session +│ └── content/ # per-feature markdown/blurbs + download panel +├── server/ +│ ├── api/releases/latest.get.ts +│ ├── api/download/[...path].get.ts +│ └── utils/gitea.ts +├── assets/css/tokens.css # palette + type ported from Tokens.axaml/styles.css +├── public/screenshots/ # 3 PNGs +└── Dockerfile +```