Quick Answer
We ran a full VibeDoctor code scan of vercel/nextjs-subscription-payments, the official Next.js + Stripe + Supabase subscription starter. The report: 93 findings (1 critical, 19 high, 59 medium, 14 low), overall score 70/100. The webhook logic is solid - our Stripe correctness checks stay silent on it, deservedly. But the route that creates checkout and billing-portal sessions has no rate limiting at all, the pinned [email protected] carries five known advisories, and the repo ships zero tests.
Why This Repo Matters
When a vibe coder asks an AI assistant for "Next.js subscriptions with Stripe," the answer is this template's DNA. It is the official starting point, maintained under the Vercel org, and it deserves credit: the webhook in app/api/webhooks/route.ts handles customer.subscription.updated and .deleted, types its renewal objects correctly, and verifies signatures. The renewal bug we found in shadcn's taxonomy is absent here - and our scanner's Stripe object-type and missing-cancellation checks correctly do not fire. Precision matters: a report that cried wolf on the official template would be worthless.
What the template does not give you is everything around the happy path - and that is what clones inherit.
The Scan
One VibeDoctor codebase scan, run on 2026-06-12. Every number below comes from that report.
| Metric | Result |
|---|---|
| Overall score | 70 / 100 |
| Total findings | 93 |
| Critical | 1 |
| High | 19 |
| Medium | 59 |
| Low | 14 |
Finding 1: Checkout Sessions With No Rate Limit (High)
Where: utils/stripe/server.ts, line 89.
The server helper that creates Stripe checkout sessions (and billing-portal sessions) can be invoked with no rate limiting anywhere in the project - no middleware, no limiter dependency, nothing. Every clone of this template ships a route where one scripted user can create Stripe sessions in a tight loop. That is an abuse surface (card-testing rings actively look for exactly this) and a noisy-neighbor problem for your Stripe account long before it is a security headline.
Rate limiting is the kind of thing template authors reasonably leave out - it depends on your infra. But clones do not know that. They ship the absence.
Finding 2: The JWT in the Example Env (Critical, With Honest Context)
Where: .env.local.example, line 4.
Secret detection flags a real JSON Web Token committed in the example env file. Context matters: it is a demo Supabase anon key, the kind that is designed to be public, so as a vulnerability it is a judgment call you can dismiss in one click in the report. But the pattern it teaches is the problem - thousands of cloners learn that tokens belong in committed env files, and the day one of them pastes a service-role key into the same line, it is game over. Any secret scanner in any CI pipeline will also hard-stop on this file forever.
Finding 3: The Pinned Framework Has Five Known Advisories (High)
The template pins [email protected], which now carries five known high-severity advisories (including GHSA-mwv6-3258-q52c and GHSA-q4gf-8mx6-v5v3). This is the quiet tax of template-driven development: the repo was patched-current the day it was published, and every clone since inherits the rot. If your app started here, your lockfile probably still says 14.2.3.
The Rest of the Report
The remaining highs: no React error boundary anywhere in the app (one unhandled render error blanks the whole page), no test directory and a near-zero test ratio, an implicit-any in the same Stripe server helper, and a cluster of accessibility findings (SVGs without titles, a non-null-asserted optional chain in the customer portal form). Fifty-nine mediums round it out - mostly code-quality and config hygiene.
The Takeaway
This is the best-case template - written by experts, webhook done right - and a fresh clone still starts life at 70/100 with an unprotected money route and an aging framework pin. A template gives you the happy path. The audit tells you what the happy path left out, for your specific app, before your users find out.
Built on this template?
A Launch Audit runs this exact report against your app: rate-limit coverage on money routes, webhook correctness, dependency advisories, and a plain-language launch verdict. One-time, per app - no subscription.
GET MY LAUNCH AUDIT →