Anatomy of this starter
Three ideas carry the whole kit.
One tenancy contract
Every request under /app/[orgSlug] resolves getAppContext(orgSlug): session → user → org →
membership. No membership and no org look identical — a 404, never a 403, so workspace existence
never leaks. Feature queries take that context, get their database through the getOrgDb(ctx)
seam, and filter by ctx.org.id. Per-tenant databases later become a config change, not a rewrite.
Durable work without a vendor
Jobs live in a table. The runner claims them with an optimistic update, retries with exponential backoff, dead-letters with the error kept, and supports continuations — a handler can reschedule itself with a new payload, which turns any job into a multi-phase state machine. That's the substrate provider Batch APIs need, at fifty percent token cost.
A deletable example
features/example-notes exists to be read and then removed in one commit. It demonstrates the
query pattern, the orgAction pipeline, plan limits, a metered AI call with versioned prompts,
and the isolation tests every feature is expected to extend. Your product starts at
docs/product-spec-template.md.