Throwaway pitch-PDF builder app
  • TypeScript 98.6%
  • CSS 1.4%
Find a file
hgeldenhuys c683b36d4c fix(model): default to anthropic/claude-sonnet-4.5 — mimo burned its budget on reasoning tokens
xiaomi/mimo-v2.5-pro is a reasoning model. With max_tokens=6000 it produced 5999 reasoning_tokens and zero actual output (just CSS + empty body). Reasoning models compete with their own output for the token budget — wrong fit for HTML composition.

Sonnet 4.5 is non-reasoning, ~50 tok/s, produces clean structured HTML at 5K-token output sizes. Override via OPENROUTER_MODEL env var.
2026-04-30 16:08:30 -04:00
app fix(model): default to anthropic/claude-sonnet-4.5 — mimo burned its budget on reasoning tokens 2026-04-30 16:08:30 -04:00
public scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
.gitignore scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
bun.lock scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
CHANGELOG.md scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
package.json scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
react-router.config.ts scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
README.md scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
tsconfig.json scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00
vite.config.ts scaffold(pitch-builder): initial RR7+Bun BFF — form/preview/print + OpenRouter compose route 2026-04-30 10:52:43 -04:00

pitch-builder

Throwaway Kapable App that turns a brief + a client URL into a 2-page A4 client-pitch PDF.

Stack

RR7 + Bun BFF. Single page with a form on the left and an iframe preview on the right. The "Save as PDF" button calls iframe.contentWindow.print() which opens the browser's native print dialog — choose "Save as PDF" with A4 paper size, no margins. No headless Chrome dependency on the server.

Endpoints

  • GET / — form + preview UI.
  • POST /api/compose — body: { clientName, clientUrl?, audience, brief, mode }. Calls OpenRouter, returns { html, elapsed_ms, usage, model }.
  • GET /health — 200 ok.

Env vars (production)

Var Default Purpose
OPENROUTER_API_KEY Required. OpenRouter API key.
OPENROUTER_MODEL xiaomi/mimo-v2.5-pro Override to use a different model (e.g. anthropic/claude-sonnet-4-5).
PORT 3000 Listens here.
SESSION_SECRET RR7 baseline; not used by app routes today but pipeline expects it.
KAPABLE_API_URL https://api.kapable.dev Reserved for future SDK calls.

Local dev

bun install
OPENROUTER_API_KEY=sk-or-... bun dev

Open http://localhost:3000.

Deploy

Push to main on Forgejo, then trigger Connect App Pipeline:

curl -X POST https://api.kapable.dev/v1/apps/<APP_ID>/environments/production/deploy \
  -H "x-api-key: $ADMIN_KEY"

Or use /deploy-frontend skill.