Files
ClaudeDo/docs/superpowers/specs/2026-06-04-marketing-website-design.md
mika kuns a2c339cd87 docs(web): add ClaudeDo distribution website design spec
Approved design for a Nuxt 3 site at claudedo.kuns.dev: "the page is the
app" concept (3-island layout), build-time release fetch, and a Nitro
release proxy that fronts the self-updater to hide the Gitea URL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 20:07:58 +02:00

9.9 KiB
Raw Blame History

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 barDETAILS 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/<encoded-asset-path>. 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