Make ScrollCraft free: drop the export paywall and retire the subscription tiers - #340
Merged
Merged
Conversation
…ption tiers Everything the product does is now free — every template and preset, the editor, publishing, and ZIP export. Revenue moves to enterprise work arranged by email, with individually purchased premium templates to follow. - export-site no longer charges. The 402 paywall and the editor's checkout detour are gone. The security property that shared that code path is kept and now stands on its own: when a request names a siteId, the stored row is authoritative and the lookup is scoped to the caller, so nobody can export a site they do not own, and a siteId that is not a plain string never reaches a Prisma where clause. - The four paid tiers are retired. They stay in plans.ts marked legacy because existing subscribers carry those values in the database, and a new siteAllowance() floors every plan at the free allowance — the free tier grew from 1 site to 3, which is above what BASIC stored, and nobody who paid may end up worse off than someone who did not. - The pricing page loses the billing toggle, the promo field, the five-tier grid and the Razorpay checkout, and becomes Free plus Enterprise-by-contact. - Copy that sold upgrades is gone from the homepage, dashboard and gallery. The Razorpay endpoints stay in place: the webhook must keep handling refunds and chargebacks on payments already taken, even though no UI starts a new one. Premium templates are not advertised anywhere yet, because they do not exist yet — they land next.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
First of three PRs for the new model: most things free, a few premium templates paid, enterprise by contact.
What
The security property that lived in the same code path is kept and now stands on its own: when a request names a
siteId, the stored row is authoritative and the lookup is scoped to the caller — so nobody can export a site they don't own — and asiteIdthat isn't a plain string never reaches a Prismawhere.plans.tsmarkedlegacybecause existing subscribers carry those values in the database.siteAllowance()floors every plan at the free allowance — nobody who paid ends up worse off than someone who didn't.Test changes
exportPaywall.test.tsis renamed toexportSiteSource.test.ts— "paywall" became a lie, but roughly half of what it covered is still live and load-bearing. The paywall assertions are replaced with the ones that survive: hostilesiteIdvalues (filter object, empty, over-long, array, number, null) are discarded and never queried, a site the caller doesn't own 404s, and the route never answers 402 on any session shape.siteAllowance.test.tslost "a higher plan allows strictly more than a lower one" — that ladder no longer holds by design. It now asserts the invariant that replaced it: no plan resolves below the free allowance, andBASICspecifically floors up to it.Deliberately left alone
The Razorpay endpoints stay live. No UI starts a new subscription, but the webhook must keep handling refunds and chargebacks on payments already taken. Deleting them is a separate cleanup.
Verified
tsc,eslint,next buildclean; suite 453 → 455.?topic=into /contact viauseSearchParamsneeded a Suspense boundary, which stopped the whole page prerendering (killing the SEO added in bug: /showcase and /contact are in the sitemap but reuse the homepage title and meta description verbatim #253). The preselect wasn't worth a page refactor, so the enterprise CTA is a plain/contactlink and the page prerenders again.Premium templates are not advertised anywhere yet, because they don't exist yet — they land in the next PR.