Changelog
Every commit, pulled live from git every 5 minutes.
Friday, May 15
- featdf74226launch promo (14-day free trial on every paid plan) + a11y polish (skip-link, focus rings, aria-labels)
- fix · visual576639fbrighter ambient anime backdrop site-wide; footer Product list now includes Discover/Templates/Changelog; Company column → Community (GitHub + Founders Fund)
- fix · layout602bc70dedupe Discover in nav + auth-aware header (avatar/Dashboard/Sign out when signed in)
Marketing surface ready for Show HN / Product Hunt / Twitter: api: - /stats/public → live counts (apps, builders, ai_calls/wk, builder revenue/wk) cached 60s. Powers landing-page social-proof pill. - /changelog → git log via GH API, parsed into {kind, scope, title, body, sha} cached 5m. Skips merge commits, conventional-commit aware. web: - New /changelog page (edge SSR, 5m revalidate). Groups commits by day, color- coded badges per kind (feat/fix/infra/perf/chore/docs/refactor). - New /api/og?title=…&subtitle=…&kind=… → 1200x630 SVG with our grad…api/src/do/build-room.ts — new BuildRoom Durable Object: - One instance per app_id; holds the WebSocket fan-out for everyone currently editing that app - On connect, sends 'welcome' with current peer list, broadcasts 'join' - Relays 'cursor', 'select', 'typing', 'preview', 'reaction' messages (validated kinds only) to all other clients with from=sender_id - 'ping' → 'pong' for keepalive - Cleans up on close/error api wrangler.toml — DO binding BUILD_ROOM (class_name=BuildRoom) + migration v1-buildroom adds the new class. api routes/builder.ts — GET /builder/room/:app_id (auth + ownership c…
19-row table directly above Founders Fund. Each row: feature, our state (emerald, bold), their state (white/40 muted). Footer notes the 'compared from public docs as of {month}' caveat + a PR-it link to the open repo. The headline: 'Other AI app builders give you a chat box. Stakgod gives you a chat box AND a real BaaS stack baked into every app you ship.' Co-Authored-By: Claude Opus 4.7 <[email protected]>D1 007 (auto-applied via the new admin token): - ALTER apps ADD COLUMN fork_price_cents (default 0 = free) - New fork_purchases table: source/buyer ledger, stripe_session_id unique, amount + application_fee tracking; indexes for both buyer + source. api builder.ts: - /fork now branches on fork_price_cents: * 0 → free fork as before * >0 → returns 402 with Stripe Checkout URL routed via the seller's Connect account; Stakgod takes 20% application_fee_amount * /fork called again with ?session_id=cs_… → verifies payment, writes fork_purchases row, then creates the cloned app.…apps-worker: - handleQueue: POST /__api__/queue/enqueue, GET /__api__/queue, DELETE /:id - Storage layout: appq:{ISO-run_at}:{slug}:{id} → JSON job. ISO prefix means KV's lex-sorted list returns due jobs in chronological order — tick handler scans appq:, takes anything with run_at <= now, runs + deletes. - scheduled() now drains BOTH the recurring cron table (runDueTasks) AND the one-shot queue (processQueue), batched up to 50 jobs/tick. - Action kinds: * webhook → POST url with body, custom method/headers * push → broadcast to all subscribers (or only the original enqueuer …api builder.ts: - ChatBody.images?: ImageAttachment[] (mime + base64) - Validates: max 5 images per turn, allowed mimes png/jpeg/webp/gif - Final user turn becomes Anthropic multipart content blocks: image source base64 + text. Anthropic vision models do the rest. - Persisted-text in D1 gets a '[📎 N images attached]' suffix so chat history shows what the user dropped (without bloating the row with raw bytes). - System prompt gains a VISION INPUT section: 'image without text → match this design; image + text → text wins for intent, image is reference'. build/page.tsx: - 📎 button + hidde…
api routes/users.ts: - New GET /users/leaderboard?by=views|revenue&limit=10 - Aggregates each builder's public apps: * views: live KV scan of appviews:{slug}:total * revenue: SUM(builder_payouts.amount_gross_cents) for the user - Returns { handle, name, avatar_url, apps, total_views, revenue_cents } - Cached 5 min via cache-control header Discover page gets a new ⚒️ 'Top builders' strip below the apps leaderboard — top 5 cards w/ rank + avatar + name + app count + views, each linking to /u/{handle}. Co-Authored-By: Claude Opus 4.7 <[email protected]>D1 006: ALTER users ADD handle (UNIQUE), bio, twitter, website + partial unique index on handle WHERE NOT NULL. API: - routes/users.ts: * GET /users/me — current builder's profile * POST /users/me — update handle/bio/twitter/website (validates handle: lowercase, 3-32 chars, reserved-word check, uniqueness) * GET /users/:handle — PUBLIC: returns profile + their public apps with hydrated KV view counts + total stats - mounted under /users Web: - New /u/[han…apps-worker: - ?embed=1 on the URL: drops X-Frame-Options so the app frames cleanly on third-party sites (Notion, Substack, blog posts), and swaps the full bottom-right Remix badge for a tiny single-pill 'STAKGOD' corner mark. - SDK gains: * sg.share({title, text, url?}) → tries navigator.share (mobile native sheet), falls back to clipboard.writeText with a UTM-tagged deep link. Returns { shared, via: 'native'|'clipboard'|'cancelled'|'unsupported', url }. * sg.embed({width?, height?}) → returns a ready-to-paste <iframe> snippet pointed at the app's own URL with ?embed=1. Sy…apps-worker: - Top-level HTML page-loads now increment view counters in KV (best-effort via ctx.waitUntil so they never block the page). Two keys per app: appviews:{slug}:total + appviews:{slug}:d:{YYYY-MM-DD} (90d TTL). api-worker (now binds APP_DATA + APP_HOSTS so it can read the same KV): - routes/analytics.ts: GET /apps/:id/analytics returns views (total/today + 14-day daily array), db_keys, push.subscribers + push.sent_month, ai calls/cost month + today, email.sent_month, payments.{gross,fee,txns} - routes/discover.ts: * /discover hydrates view_count from KV at query time (colum…sg.ai.image: - apps-worker now binds [ai] AI; /__api__/ai/image runs @cf/black-forest-labs/flux-1-schnell with caller-supplied prompt + steps (1..8, default 4). Returns { base64, data_url, mime, model, steps }. - Same builder-quota path as sg.ai.chat (1 ai_message event/call, $0.003 cost). - Replaces the previous 501 stub; removed the placeholder usage_event insert. Visual editor v2 quick actions: - Floating element-edit prompt now shows 4 one-tap action buttons above the custom-instruction input: 🗑 Delete · 📋 Duplicate · ⬆️ Move up · ⬇️ Move down - Each fires submitElementEdit() with …iOS (apps/codegen-ios/): - project.yml.tmpl: targets now include both Sources and Resources directories - render.sh: curls icon from ${APP_URL}/icon.png into Resources/Assets.xcassets/AppIcon.appiconset/icon-1024.png and emits a Contents.json using the iOS 14+ single-size manifest (covers all device sizes from one 1024). Strips alpha via sips so Apple doesn't reject. Falls back to a flame square if the download fails. Android (apps/codegen-android/): - render.sh: same icon URL, but downscales to mdpi/hdpi/xhdpi/xxhdpi/xxxhdpi via ImageMagick (resize + center-crop). Falls back to the …apps-worker now exports scheduled() in addition to fetch(); wrangler.toml adds [triggers] crons = ['* * * * *'] (every minute, 1440 invocations/day). KV-stored task list: appcron:{slug}:{id} → CronTask. On each minute tick, runDueTasks() lists all due rows, runs them, recomputes next_run, writes back. No DO needed for v0 — flat KV scan, capped at 1000 tasks/tick. Schedule grammar (v0): @hourly | @daily | @weekly | 'HH:MM' (daily UTC) | 'every Nm' (1..1440) Action kinds (v0): { kind:'push', title, body?, url? } → sends to ALL app subscribers { kind:'webhook', url, body_json?, heade…Zero-dep CF Workers implementation in apps-worker/src/lib/webpush.ts: - VAPID JWT signed with ES256 (P-256) using Web Crypto - aes128gcm payload encryption: ECDH P-256 → HKDF → AES-128-GCM - Properly handles WebPush record framing (salt/rs/idlen/keyid header) - Drops subscriptions on 404/410 (push service expiry) apps-worker /__api__/notify/*: - GET /key → server's VAPID public key (base64url) - GET /sw.js → minimal service worker (push + click handlers) - POST /subscribe → store PushSubscription scoped to (slug, ownerId) - POST /unsubscribe → remove (specific end…
apps-worker /__api__/ai/stream: - Proxies Anthropic SSE → tighter SSE only emitting {delta:...} text chunks + a final {done, tokens_in, tokens_out, model} event - Same model router + builder-quota gating + usage_events accounting as sg.ai.chat (one event per completed call) SDK: sg.ai.stream({ system, messages, model, onDelta }) — onDelta(chunk, sofar) fires for every text fragment; resolves to { text, tokens_in, tokens_out, model } when the upstream stream closes. Supports AbortSignal for cancellation. System prompt teaches both sg.ai.chat (one-shot) and sg.ai.stream (typewriter UX) with …#1 AI app icons: - api wrangler.toml: [ai] binding=AI (Workers AI Flux access) - types.ts: Env.AI: Ai - new routes/icons.ts: * POST /apps/:id/icon/generate — auth'd; runs @cf/black-forest-labs/flux-1-schnell with a tight 'no text, premium centered icon' prompt and stores 1024x1024 PNG at apps/{slug}/icon.png (publicly served via apps-worker) * generateIconIfMissing(env, app) — internal helper - builder.ts: c.executionCtx.waitUntil(generateIconIfMissing(...)) fires on first successful deploy of each app. Best-effort; failures don't block. - Dashboard AppCard + /discover cards now …New 🎯 Select toggle in the right-pane toolbar. When ON: - Iframe srcDoc is wrapped with an inject script that hover-outlines elements in flame-orange dashed, click-selects in solid, and posts back a stable CSS selector + outerHTML snippet via window.parent.postMessage - Form submits + link clicks are intercepted (no nav inside select mode) - Selectors include id when available, then up to two classes, then :nth-of-type, walked up max 5 ancestors Parent receives the message and shows a floating glass prompt over the preview: 'Editing <selector>' + a 'Make it red, remove this, add a butto…
sg.geo (no auth, no setup, no rate limit): - /__api__/geo relays Cloudflare's edge geo data: country, region, city, postal, timezone, lat/lon, continent. City-level granularity from IP. sg.notify (client-only Notification API wrapper): - sg.notify.ask() — request permission ('granted'|'denied'|'default'|'unsupported') - sg.notify.show(title, options) — request perm if needed then show - Real server-side web push (VAPID + service worker + payload encryption) is a follow-up; this gives apps the foreground UX immediately. System prompt teaches both with tight examples (currency selection from…apps-worker /__api__/email/send: - Sender: '${from_name|slug} <[email protected]>' (uses our verified stakgod.com domain so no per-app DNS setup) - reply_to defaults to the BUILDER's account email so replies route correctly - HTML and/or text body, up to 200 KB, max 20 recipients per send - Auto-appends 'Sent via Stakgod · Remix this app' footer (viral surface) - Daily caps charged to builder: free 10, hobby 100, pro 1k, studio 10k - Counted in usage_events as kind='email_send' ($0.0004/email cost-line) SDK gains sg.email.send(o). System prompt teaches usage with worked example. Co-Authore…apps-worker /__api__/uploads: - POST multipart-or-raw → R2 put + KV metadata, returns {url, key, mime, size} - GET list signed-in user's uploads (or per-IP-hash if anonymous) - DELETE ?key=... Stored at apps/{slug}/uploads/{ownerId}/{rand}.{ext} so existing static-asset serving makes them publicly fetchable. ownerId is sg.auth user.id when signed in, fnv-1a hash of cf-connecting-ip otherwise (lets anonymous visitors manage their own uploads without revealing their IP). Limits: 10 MB per file. Allowlist: png/jpg/webp/gif/svg, mp3/wav/m4a/ogg/weba, mp4/mov/webm, pdf/zip/json/csv/md/txt. SVGs…apps-worker now exposes /__api__/payments/{checkout,session} alongside db, auth, ai. Charges go through the BUILDER's Stripe Connect account; Stakgod takes a 10% application_fee_amount on top (matches the existing Connect revenue model). Generated apps just write: const { url } = await sg.payments.checkout({ items: [{ name: 'Pro plan', amount_cents: 1900 }], success_url: 'https://apps.stakgod.com/{slug}/?sg_checkout=success', }); location.href = url; After redirect, sg.payments.session(id) verifies paid status + amount. Guards: - Per-call cap: 10 line items, $20k max total, $0.50…apps-worker grows from a static-server + sg.db host into a real mini backend: sg.auth (per-app users via magic link): - /__api__/auth/{me,magic,verify,signout} - KV-backed users + sessions, namespaced per slug so users at app-A and app-B are distinct identities (privacy default) - Magic links go through Resend from [email protected] (existing integration) - 30-day cookies scoped to sg_user_{slug} sg.ai.chat (Claude in user apps): - /__api__/ai/chat → Anthropic API (model 'haiku'|'sonnet'|'opus') - Charged to the BUILDER's monthly_messages quota (resolved via apps.user_id); same hard wall a…Stops the daily 'All jobs have failed' email noise. Deploys happen from local via wrangler with the user's ~/.cloudflare/api-token. The workflow file stays in place, gated to workflow_dispatch only — click 'Run workflow' in the Actions UI when CI deploys are needed. To re-enable push-triggered auto-deploy: uncomment the push trigger AND set CLOUDFLARE_API_TOKEN as a repo secret with D1 + Workers + Pages perms. Co-Authored-By: Claude Opus 4.7 <[email protected]>
D1 005: apps gains is_public + view_count + tagline + index. API: - GET /discover — paginated (24/page) + ?q= search by name; returns slug, name, tagline/description, live URL (custom or default), updated_at, views - POST /apps/:id/visibility — toggles is_public and updates tagline /discover page: - Hero copy + search input - 3-column responsive grid of glass cards - Each card: live iframe preview (pointer-events-none so card stays clickable), name, tagline, date, Open ↗ + Remix → buttons - Remix uses existing /build?fork=slug auto-clone flow - Load-more pagination Dashboard AppCard: - New…
Thursday, May 14
Android template (apps/codegen-android/template): - WebView wrapper using AppCompat + SwipeRefreshLayout (no Compose for fast builds) - AGP 8.7.2 + Kotlin 2.0.21, minSdk 24 / compileSdk 35 - network_security_config locks down cleartext traffic - render.sh sed-substitutes APP_NAME / APP_TYPE / PACKAGE_NAME / APP_URL, generates solid-color launcher icons at all 5 mipmap densities GitHub Actions (android-build.yml): - Fetches creds via HMAC token (already had this for ios) - First build: generates fresh upload keystore (RSA 2048 / 10000d), POSTs to /builds/:id/keystore (R2-stored, password en…
Builders can attach any domain they own to an app. apps-worker: - New APP_HOSTS KV namespace bound. Routing now derives slug from Host header (custom-domain mode) when host != apps.stakgod.com, falling back to KV lookup. apps.stakgod.com keeps path-based routing. API (route apps.stakgod.com/api/apps/:id/domain): - POST attaches a domain (Hobby+; refuses reserved + taken hosts), writes KV mapping, updates apps.custom_domain, returns CNAME instructions - DELETE detaches (clears KV + DB) - GET /verify curls the domain to confirm DNS+SSL is live Dashboard: - AppCard component with collapsib…
Claude can now emit additional JS/CSS/SVG/JSON files alongside index.html in the same chat turn. extractFiles() pulls them out, sanitizes the path (a-z0-9._/-, no '..'), maps content-type by extension, and R2-writes them at apps/{slug}/{path} so apps-worker serves them with the right MIME. Up to 20 extra files per turn. System prompt teaches the syntax with example. Index.html still wins as the page; extras are referenced via relative paths (<script src='app.js'>, <link href='styles.css'>, etc). Co-Authored-By: Claude Opus 4.7 <[email protected]>apps-worker now appends a fixed-position glass badge to <body> alongside the sg.db SDK injection. Badge has utm-tagged 'STAKGOD' wordmark + 'Remix' link that deep-links to /build?fork={slug}. Build page handles ?fork=slug by calling /builder/fork then redirecting to ?app={newId}, so one click on Remix instantly clones the app into the visitor's account and drops them in the chat. Viral surface for every app a builder ships. Co-Authored-By: Claude Opus 4.7 <[email protected]>Brand alignment with stakgod.com domain: - Logo split now STAK (gold) + GOD (white) in header + footer - All user-facing 'Stackgod' → 'Stakgod' across pages, system prompt, email sender, Stripe checkout descriptions - Worker/bucket/repo names stay as 'stackgod-' (infra immutable) Versions UI in /build right-pane: - '↩ Versions (N)' pill toggle in toolbar - Drawer shows list reverse-chrono with timestamps - Revert calls POST /builder/revert, refreshes preview, drops a chat note - Auto-refreshes versions list on every successful chat completion Co-Authored-By: Claude Opus 4.7 <noreply@anthropi…
Pitch: '$99 = 1 founder shipped'. Tips fund Apple Developer enrollment for Stackgod builders who can't afford the fee. Stackgod takes 0%; public ledger. Server: - D1 004: tips + grants tables - routes/tips.ts: POST /tips/checkout (Stripe Checkout, donate mode, $2-$1000), GET /tips/stats (raised, supporters, founders_funded, pct, recent, grants) - billing webhook now branches on metadata.kind='founders_fund_tip' to insert into tips ledger; subscription path unchanged (intentional fallthrough) Web: - /support page: bold pitch, animated progress bar, quick $25/$99/$250 buttons + custom amou…
REAL BACKEND for generated apps: - New KV namespace stackgod-app-data, bound on stackgod-apps worker - Auto-injects window.sg.db SDK into every served HTML (get/put/list/del) - Backed by KV at /{slug}/__api__/db, namespaced 'app:{slug}:{key}' - 64KB/key, 5000 keys/app soft cap, 256-char key limit - System prompt teaches Claude to choose sg.db (persistent/multi-user) vs localStorage (transient/per-user) and gives a worked example VERSIONING: - builder.ts snapshots every successful generate to apps/{slug}/versions/{ts}.html - GET /builder/versions returns reverse-chrono list (last 50) - POST /…API: - /builder/chat now loads full message history from D1 + current deployed HTML and passes both to Claude. System prompt teaches it to PATCH IN PLACE, re-emitting the whole file each turn. Max 8k output tokens. - New GET /builder/messages?app_id=X returns full history + deployed_url - max_history=20 messages, max 80k chars of current HTML for context Web: - /build loads history + current HTML when ?app=X in URL (back-button restore) - Live preview iframe updates throttled (200ms) as Claude streams the HTML - New Preview/Code pill toggle in the right pane - Live link to deployed_url - C…
- body::before fixed-position dimmed+blurred hero artwork (opacity 0.55, blur 2px) sits behind every page. Landing's bold .hero-bg layers on top. - body::after adds soft flame/blue radial-gradient screen-blend glow - Header bumped to backdrop-blur-xl + backdrop-saturate-150 + bg-ink/50 - Footer gets matching glass treatment Same atmospheric feel on /pricing, /showcase, /docs, /login, /dashboard. Co-Authored-By: Claude Opus 4.7 <[email protected]>
- public/hero.jpg — atmospheric anime art (cyan/magenta nebula founder portrait) - globals.css: .card now backdrop-blur-2xl + saturate-150 with inner-light gradient, shadow inset stack for true frosted glass feel; .hero-bg pseudo-elements layer the image with radial vignette + screen-blend gold/flame glow - page.tsx: hero section is full 90vh with image background, larger headline (8xl), drop-shadowed text for legibility over artwork, animated 'live' dot, bigger CTAs Stack chips also pick up backdrop-blur for cohesion. Co-Authored-By: Claude Opus 4.7 <[email protected]>
- New stackgod-apps Worker (apps/apps-worker): serves R2 assets at apps.stakgod.com/* - New R2 bucket stackgod-apps + APPS binding on both workers - builder.ts: extracts HTML from chat stream, auto-deploys to R2 on completion, marks app status=live, returns deployed_url in SSE done event - New POST /builder/deploy for manual save/external integrations - iOS shell template + builds.ts now point at apps.stakgod.com/{slug}/ - apps.ts returns the new url on app create - System prompt updated to require fenced ```html block for cleaner extraction Co-Authored-By: Claude Opus 4.7 <noreply@anthropic…Server: - D1 003: builds table (id, app_id, kind, status, gh_run_url, ...) - lib/build-token.ts: HMAC short-lived tokens for CI auth - routes/builds.ts: GET /builds, GET /builds/:id/credentials (HMAC-gated), POST /builds/:id/status (CI callback) - queue/build-consumer.ts: handle BUILD_QUEUE → insert builds row, mint token, dispatch GH workflow_dispatch - Worker now exports {fetch, queue}; consumer wired in wrangler.toml - mobile.ts uses per-user creds, computes bundle from stored prefix + slug GitHub Actions: - ios-build.yml: fetches creds via HMAC token, renders SwiftUI shell, xcodegen …- D1 migration 002: developer_credentials table (encrypted at rest) - crypto.ts: AES-256-GCM helper using ENCRYPTION_KEY worker secret - /connect/{status,apple,google} routes (POST stores encrypted, DELETE clears) - /mobile/{ios,android}/ship now reads per-user creds, returns 412 if missing - New pages: /dashboard/connect-apple, /dashboard/connect-google - /dashboard now surfaces both as cards - /docs explains 4.2.6 + cost ('$99/yr to Apple, $25 one-time to Google') - plans.ts: ios_ship/android_ship/marketplace flags Co-Authored-By: Claude Opus 4.7 <[email protected]>apps/api/src/lib/jwt.ts — generic OIDC verifier: - Fetches JWKS from issuer, caches in KV for 1h - Verifies RS256 signature via WebCrypto (RSASSA-PKCS1-v1_5) - Validates iss + aud + exp (with 30s clock skew) apps/api/src/routes/oauth.ts — both callbacks now use the verifier: - Google: jwks https://www.googleapis.com/oauth2/v3/certs - Apple: jwks https://appleid.apple.com/auth/keys Production-hardened. No more trust-the-transport assumption. Co-Authored-By: Claude Opus 4.7 <[email protected]>
- Google: OAuth web client created, secrets set on Worker - Apple: Service ID com.sumhead.stakgod.signin, web auth domain stakgod.com, return URL https://api.stakgod.com/auth/apple/callback, key KNN648PBXK, team GY47UX52TR. All 4 secrets set on Worker. - /auth/providers reports {google:true, apple:true} - /login shows both buttons + magic link .p8 backed up locally to ~/.apple-secrets/ (chmod 600, never committed) Co-Authored-By: Claude Opus 4.7 <[email protected]>- /auth/google/{start,callback} — OAuth code flow, mints session cookie - /auth/apple/{start,callback} — Sign in with Apple form_post + name capture - /auth/providers — reports which OAuth providers have credentials configured - /login — Apple/Google buttons auto-hide when unconfigured (no dead buttons rule) - /docs — quickstart, plan limits table, contact - /mobile/ios/ship + /mobile/android/ship — queue producer (consumer + GH Actions next) Both Worker + Pages deployed and verified. Co-Authored-By: Claude Opus 4.7 <[email protected]>- stakgod.com → 200 (Pages) - api.stakgod.com → 200 (Worker) - D1 schema applied, auth middleware verified - Magic-link blocked only by Resend domain verification Co-Authored-By: Claude Opus 4.7 <[email protected]>
- Pages preview: https://stackgod-web.pages.dev (200 OK) - stakgod.com + www.stakgod.com attached, awaiting DNS - nodejs_compat enabled - Stripped TS-only generic .json<T>() so Next 15 build passes Co-Authored-By: Claude Opus 4.7 <[email protected]>
- D1 stackgod (91355169-4ad4-4825-a468-9c830f9dae27) - KV SESSIONS (749eec723bcc4db1892ede8c1a4b401b) - R2 stackgod-artifacts - Queue stackgod-builds (producer only until build handler ships) - STRIPE_WEBHOOK_SECRET set as worker secret - Worker live on api.stakgod.com Co-Authored-By: Claude Opus 4.7 <[email protected]>
Created on Stripe acct_1S40wDQu1YpWmfU0 (SUMHEAD), all livemode=true: - Hobby $19/mo (price_1TX0MMQu1YpWmfU0SsoaTL8F) / $190/yr (price_1TX0MPQu1YpWmfU0ba05E6me) - Pro $49/mo (price_1TX0MSQu1YpWmfU04UUr0Ffb) / $490/yr (price_1TX0MVQu1YpWmfU0mM5ma35D) - Studio $149/mo (price_1TX0MeQu1YpWmfU0Em6VEuBH) / $1490/yr (price_1TX0MhQu1YpWmfU0XzppgklY) Annual = 2 months free. Pricing page now has Monthly/Annual toggle. Checkout endpoint accepts {plan, cycle}. Co-Authored-By: Claude Opus 4.7 <[email protected]>Speak it. Ship it. Own it. Hercules-class clone built on CF Pages + Workers + D1 + R2. - Marketing: landing, /showcase (interactive feature gallery), /pricing - Auth: magic link via Resend (live), Apple/Google ready - Builder chat: streaming Claude with model router (Haiku/Sonnet/Opus) - Hard credit gate: 5 msgs/day free tier returns 402 + upgrade URL - Stripe: live checkout for Hobby/Pro/Studio + Connect Express for builders (10% fee) - Domains: CF Registrar wrapper, wholesale + flat $1 platform fee - Mobile: SwiftUI + Compose codegen scaffolds + GH Actions for TestFlight/Play - Deploy: GH Ac…