Magic-link auth (closed signup)
No public registrations. Stripe later becomes the account-creation event; email links sign users in without passwords.
A real SaaS layout with an edge API: fast UX, safe-by-default auth, and a path to billing + licensing.
Fast pages, clean components, and environment-driven links to API, docs, and portal.
D1 holds users and entitlements; KV holds sessions, one-time tokens, and rate-limits.
No public signup. Stripe (later) creates accounts; magic links authenticate without passwords.
The site, portal, and API work best when each surface has one job. This baseline keeps the product legible now and leaves room for harder controls later.
No public registrations. Stripe later becomes the account-creation event; email links sign users in without passwords.
Bind licenses to users and enforce entitlements from the edge API. Track activations per machine and revoke when needed.
D1 stores users, purchases, and entitlements. KV stores one-time tokens, sessions, and best-effort throttling.
Signature verification and idempotency tables are in place. Add Stripe keys later without rebuilding the backend shape.
Separate surfaces keep the customer dashboard, licenses, billing, and future admin tools behind the right role boundaries.
Minimal surface area, explicit allowlists, bounded request bodies, and a clear upgrade path to durable rate limiting.
A few decisions that keep this demo secure-by-default.
No. The API is configured with ALLOW_SIGNUP=false so accounts are only created after Stripe checkout (or seeded by an admin).
It avoids passwords, reduces support burden, and works well on Cloudflare Workers. Links are short-lived and throttled.
The recommended model is asymmetric signatures: server signs a license payload, and the desktop app verifies using a public key.
Best-effort today using KV. For stronger guarantees (especially around email + checkout) move rate limiting to Durable Objects.
Buy ChartGPT once. Connect your OpenAI, Anthropic, Google, or OpenRouter API key. Send NinjaTrader chart context into your AI workflow.