Skip to content

Make ScrollCraft free: drop the export paywall and retire the subscription tiers - #340

Merged
singhharsh1708 merged 1 commit into
mainfrom
feat/free-first-pricing
Aug 26, 2026
Merged

Make ScrollCraft free: drop the export paywall and retire the subscription tiers#340
singhharsh1708 merged 1 commit into
mainfrom
feat/free-first-pricing

Conversation

@singhharsh1708

Copy link
Copy Markdown
Owner

First of three PRs for the new model: most things free, a few premium templates paid, enterprise by contact.

What

  • ZIP export is now free on every plan. The 402 paywall and the editor's checkout detour are gone.
    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 a siteId that isn't a plain string never reaches a Prisma where.
  • The four paid tiers are retired. They stay in plans.ts marked legacy because existing subscribers carry those values in the database.
  • Free grew from 1 saved site to 3. That is above what BASIC stored (2), so a new siteAllowance() floors every plan at the free allowance — nobody who paid ends up worse off than someone who didn't.
  • Pricing page rewritten: billing toggle, promo field, five-tier grid and Razorpay checkout all removed. Now Free + Enterprise-by-contact.
  • Upgrade CTAs replaced across homepage, dashboard and the templates gallery.

Test changes

exportPaywall.test.ts is renamed to exportSiteSource.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: hostile siteId values (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.ts lost "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, and BASIC specifically 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 build clean; suite 453 → 455.
  • Checked the built HTML: pricing renders ₹0 / Everything, free / 3 saved websites / Contact us, with no residual "Upgrade", "Basic Plus", "₹1,999", "Monthly/Annual" or "per site" copy.
  • Caught and reverted a regression of my own along the way: wiring ?topic= into /contact via useSearchParams needed 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 /contact link and the page prerenders again.

Premium templates are not advertised anywhere yet, because they don't exist yet — they land in the next PR.

…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.
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
scrollcraft Ready Ready Preview Aug 26, 2026 8:26pm

@singhharsh1708
singhharsh1708 merged commit 406926b into main Aug 26, 2026
3 checks passed
@singhharsh1708
singhharsh1708 deleted the feat/free-first-pricing branch August 26, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant