Repository navigation
Studio: plans, limits and Stripe billing - #12
Merged
Merged
Conversation
… decision Studio (apps/studio) moves from Apache-2.0 to FSL-1.1-ALv2: source stays public, free to run for your own team or company, no competing hosted service, and each version becomes Apache-2.0 two years after release. README, NOTICE, Studio's landing page, the site's Studio page, docs and terms say so. Decision 0004 records the pricing and licensing plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plans and limits apply only when BILLING is on (the hosted Studio); a self-hosted Studio has none. One table of limits per plan (plans.ts), 402 plan_limit at workspace create, editor invites and accepts, design systems, Directions and published screens, and Free's history kept to its last ten versions. Fetches by API key are counted in Workers Analytics Engine, rolled up hourly by the cron into usage, and seven days over quota locks editing (never fetching). Stripe through fetch: checkout (founding coupon, Team seats), portal, and a signed webhook that sets the plan; Team's seats follow editors joining and leaving. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…team seats freed The Billing page (Workspace → Billing, shown only where the Studio has plans) gives the plan, seats, usage bars that turn amber at 80%, notices for over quota, a paused workspace and a failed payment, a monthly or yearly toggle, and upgrade or manage buttons for owners. Any 402 opens a dialog that says what ran out and links to the plans. Team gains Remove for owners and Withdraw for open invites, which hold a seat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d what 0004 built The Studio README says how to turn billing on (Stripe products, prices, coupon, webhook events, secrets, the Analytics Engine token) and that a self-hosted Studio has no limits; the site's Studio page gives the plans in plain words; the pricing decision ticks off workstreams 2 and 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
visualfart
force-pushed
the
feat/studio-billing
branch
from
September 29, 2026 00:35
0890b0e to
0e3feaa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Studio gains plans, limits and billing, per decision 0004. All of it applies only when the Worker's
BILLINGison, which only the hosted Studio sets — a self-hosted Studio has no limits and no Billing page, and that's tested both ways.Licensing.
apps/studiomoves to FSL-1.1-ALv2: source stays public, free to self-host for your own team, no competing hosted service, and each version becomes Apache-2.0 two years after release. Every other package stays Apache-2.0.Plans and limits. Migration
0007_plans.sqladds the plan columns and ausagetable.plans.tsholds the one limits table and enforces it at workspace creation, invites and invite accept, design-system import, Directions, screen publish, and version history. Over-limit answers 402 withcode: "plan_limit", which the app turns into an upgrade dialog.Fetch metering. A fetch by API key writes one Analytics Engine data point; an hourly cron rolls it into
usageand sets or clearsover_quota_since. Seven days over quota and edits answer 402 — fetches, reads and billing keep working.Billing. Stripe's REST API through
fetch, no SDK. Checkout, Customer Portal, a webhook whose signature is checked with Web Crypto (HMAC-SHA256, constant-time, 5-minute tolerance), and seat sync that follows the editor count with prorations. The webhook is the only thing that changes a plan.Checked
test/billing.worker.test.ts(signature checked, plan set from the subscription, seats synced, back to Free when it ends, the founding coupon until it runs out, self-hosted has none of it).tsc -bclean;check-docs.tsclean.Before this can take payments
0007_plans.sqlto the remote D1.BILLING,STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET, the fourSTRIPE_PRICE_*,STRIPE_COUPON_FOUNDING,CF_ACCOUNT_ID,CF_ANALYTICS_TOKEN.stripe listen --forward-to localhost:8789/api/billing/webhook, card 4242) before pointing it at live.Live products, prices (USD $8 / $80 Pro, $12 / $120 per editor Team), the founding coupon and the webhook destination are set up in the Stripe account.
Known trade-offs
invoice.payment_failedmarks past_due by customer id. One customer with two subscribed workspaces would mark both.🤖 Generated with Claude Code