• Identity + quotas: We normalize to either “ip:<addr>” (guest) or “user:<id>” (Supabase JWT). Caps are enforced in Cloudflare KV: daily (“plat:day”), monthly (“plat:mon”), plus separate BYOK counters and a soft-lock flag to avoid hot-spot abuse.
• Error handling: We rotate between multiple OpenRouter keys (platform pool) and retry on 429/5xx with small jitter. BYOK path is single-attempt (we don’t want to amplify user key errors).
• JSON discipline: The frontend asks the model for a strict JSON shape (linkedin, x, email{subject,body}, instagram) and tries to parse a minimal slice if the model returns extra text. We know strict JSON from LLMs is never 100%; this has worked well enough for now.
• Security: BYOK is header-only, not persisted; we don’t log it. OAuth state uses an HMAC-signed payload + short TTL.
• Stripe: Checkout for plan selection; Portal for self-serve management; webhook updates the user’s KV record (plan/sub status).
• Performance: Worker-only architecture, no origin server. All state in KV is small (counters + per-user record). Cold starts haven’t been an issue in practice.
Open questions we’re exploring:
• Better “usage transparency” for BYOK (per-model cost hints).
• Notion export to a DB template w/ properties (channel, status, publish date).
• Trello labels/checklists on export.
If you hit rough edges, paste repro steps and we’ll ship a fix. Also happy to share the Worker structure in more detail if interesting.
Technical details / tradeoffs:
• Identity + quotas: We normalize to either “ip:<addr>” (guest) or “user:<id>” (Supabase JWT). Caps are enforced in Cloudflare KV: daily (“plat:day”), monthly (“plat:mon”), plus separate BYOK counters and a soft-lock flag to avoid hot-spot abuse. • Error handling: We rotate between multiple OpenRouter keys (platform pool) and retry on 429/5xx with small jitter. BYOK path is single-attempt (we don’t want to amplify user key errors). • JSON discipline: The frontend asks the model for a strict JSON shape (linkedin, x, email{subject,body}, instagram) and tries to parse a minimal slice if the model returns extra text. We know strict JSON from LLMs is never 100%; this has worked well enough for now. • Security: BYOK is header-only, not persisted; we don’t log it. OAuth state uses an HMAC-signed payload + short TTL. • Stripe: Checkout for plan selection; Portal for self-serve management; webhook updates the user’s KV record (plan/sub status). • Performance: Worker-only architecture, no origin server. All state in KV is small (counters + per-user record). Cold starts haven’t been an issue in practice.
Open questions we’re exploring: • Better “usage transparency” for BYOK (per-model cost hints). • Notion export to a DB template w/ properties (channel, status, publish date). • Trello labels/checklists on export.
If you hit rough edges, paste repro steps and we’ll ship a fix. Also happy to share the Worker structure in more detail if interesting.