Files
Hunter B bb4d1e5744 docs(web,readme): taste pass — fix stale refs, tighten design rhythm
Polish fixes (12):
- INSTALL.md: drop duplicate code block; doc CODEWHALE_VERSION canonical
  env var; fix example mirror URLs /DeepSeek-TUI/ → /CodeWhale/; remove
  stale "Once npm publication resumes" conditional
- footer.tsx: fix Gitee mirror URL deepseek-tui → CodeWhale
- globals.css: update seal CSS shadows from old cream rgba(244,241,232)
  to paper white rgba(255,255,255)
- web/README.md: update palette description cream #FAF6EE → white #FFFFFF
- nav.tsx: fix zh-only date strip (第…期) and API label (在线) — now
  "Edition …" / "API · Online" in en mode
- page.tsx: hardcoded v0.8.56 → dynamic facts.version
- README.md: merge duplicate Contributing sections
- README.ja-JP/vi: parenthesize untranslated Chinese thank-you blurbs

Design rhythm (9):
- ThinkingTrace section: py-16→py-20, bg-paper-deep, hairlines for reveal
- Judgment stack: py-16→py-12; middle cell bg-paper-deep for ABA rhythm
- Maintainer loop: py-16→py-14; step numbers grow 01→04
- How it works: py-16→py-12
- Join in closer: py-16→py-20 (dark section breathes)
- Ticker: LIVE label shrunk to annotation weight
2026-06-13 13:55:51 -07:00

4.9 KiB
Raw Permalink Blame History

codewhale-web

Community site for CodeWhale — lives at codewhale.net.

Next.js 15 (App Router) + Tailwind, deployed to Cloudflare Workers via @opennextjs/cloudflare. Curated "Today's Dispatch" content is regenerated every 6 hours by a Cloudflare Cron Trigger that calls deepseek-v4-flash to summarise recent repo activity, and stored in Workers KV.

Local dev

cd web
npm install
cp .env.example .env.local   # fill in the keys you have
npm run dev                  # http://localhost:3000

Required env (only for the curator + private-repo rate limits):

Variable What Required?
DEEPSEEK_API_KEY DeepSeek platform key (sk-...) only for /api/cron?task=curate
GITHUB_TOKEN Fine-grained PAT, public-repo read scope optional (raises rate limit)
GITHUB_REPO Defaults to Hmbown/CodeWhale optional
CRON_SECRET Shared secret for manual cron invocation optional

The site renders fine without any of them — Today's Dispatch falls back to a static editorial; the GitHub feed shows "feed not yet loaded".

Deploy to Cloudflare

You already own codewhale.net on Cloudflare and have a Workers Paid plan. The deploy is two steps:

  1. Provision KV namespaces once:

    npx wrangler kv namespace create CURATED_KV
    npx wrangler kv namespace create NEXT_INC_CACHE_KV
    

    Copy the printed id values into the matching wrangler.jsonc bindings (replace each REPLACE_WITH_KV_ID).

  2. Set secrets and deploy:

    npx wrangler secret put DEEPSEEK_API_KEY
    npx wrangler secret put GITHUB_TOKEN     # optional
    npx wrangler secret put CRON_SECRET      # optional, for manual /api/cron?task=curate hits
    
    npm run deploy                           # builds with OpenNext + uploads
    
  3. Point the domain: in the Cloudflare dashboard, add a Worker route for codewhale.net/* → the deployed Worker (currently named deepseek-tui-web unless the Worker is renamed during deploy).

The first cron run happens within 6 hours; you can also kick it manually:

curl -H "x-cron-secret: $CRON_SECRET" "https://codewhale.net/api/cron?task=curate"

What's where

web/
├── app/
│   ├── layout.tsx              root layout, font loading
│   ├── page.tsx                home — hero, dispatch, stats, how-it-works, join
│   ├── globals.css             design system: paper grain, hairlines, type, seal
│   ├── install/page.tsx        per-OS install with auto-detection
│   ├── docs/page.tsx           modes / tools / approval / config / mcp / providers
│   ├── feed/page.tsx           live mirror of issues + PRs
│   ├── roadmap/page.tsx        shipped / underway / considered / ruled out
│   ├── contribute/page.tsx     how to PR + house rules + dev loop
│   └── api/
│       ├── cron/route.ts          manual cron trigger: GitHub → DeepSeek → KV
│       └── github/feed/route.ts   cached JSON endpoint
├── components/
│   ├── nav.tsx                 sticky header w/ date strip + CJK accents
│   ├── footer.tsx              dense 5-column footer
│   ├── seal.tsx                red Chinese-seal mark used as section anchor
│   ├── ticker.tsx              animated live activity strip
│   ├── stat-grid.tsx           tabular repo stats row
│   ├── feed-card.tsx           one issue/PR card
│   └── install-tabs.tsx        client component, OS auto-detect + copy
├── lib/
│   ├── types.ts                shared types
│   ├── github.ts               REST client + relative-time formatter
│   ├── deepseek.ts             v4-flash chat client + curate() prompt
│   └── kv.ts                   Cloudflare KV access via OpenNext bindings
├── wrangler.jsonc              CF Worker config + cron + KV binding
├── open-next.config.ts         OpenNext adapter config
└── tailwind.config.ts          design tokens

Aesthetic

"Yamen tech": Qing memorial document × WeChat news feed × Bloomberg terminal.

  • Palette: white paper #FFFFFF, cool gray #F4F6FB, ink #0E0E10, indigo #4D6BFE, jade green, cobalt blue.
  • Type: Fraunces (display), IBM Plex Sans (body), JetBrains Mono (UI/code), Noto Serif SC (decorative CJK anchors).
  • Structure: hairline 1px dividers, multi-column grids, big tabular numbers, surgical use of red for "hot" markers, decorative Chinese-seal squares as section anchors.

If you want to retune the palette, edit :root in app/globals.css and the colors block in tailwind.config.ts.