One scan. One verdict: ship, or not yet.
Should It Launch is a production-readiness audit for AI-built websites. Paste a URL and it renders the site in a real headless browser, checks it across eight dimensions, and returns a single gate verdict: Ship, Ship with fixes, or Not ready. Every finding carries code-level evidence and a paste-ready fix prompt, so the person who generated the site can hand the fix straight back to the machine that built it.
/ one scan · three exits
Project breakdown
AI site builders produce demos. Clients get handed production.
A site that came out of v0, Lovable, or Cursor looks finished the moment it renders. The failure modes that actually hurt (an API key sitting in the bundle, a contact form wired to nothing, an admin route that never checks who is asking) are exactly the ones a demo never shows. And the existing tools grade one dimension at a time: Lighthouse for performance, Observatory for headers. Nobody hands you the one answer a handoff needs.
So the brief was one URL in, one gate out. Render the site the way a visitor's browser does, check the eight things that decide whether it survives contact with real users, and say Ship, Ship with fixes, or Not ready, with evidence backing the call. Three free scans a day, no card, no account, so an agency can gut-check a client build in the time it takes to paste a URL.
A real browser, eight dimensions, and a verdict that refuses to average.
The engine is its own Cloudflare Worker. It renders the target in Browser Rendering, captures what actually shipped, and runs eight analyzers over the result: secrets, forms, access controls, security headers, performance, SEO, accessibility, and the unglamorous rest. Scoring is versioned ruleset math, and the verdict is a gate: one confirmed critical means Not ready no matter how pretty the other seven dimensions look.
- Secret detection suppresses before it matches: publishable keys (Stripe
pk_, Firebase, Supabase anon, Sentry DSN) are allowlisted up front so they can never false-positive, dangerous keys need an assignment context rather than mere proximity, and a Shannon-entropy pass catches unknown high-entropy strings - Anything secret-shaped is redacted from evidence and stored captures before it is written anywhere
- The SSRF guard validates the resolved IP, not the URL string: decimal, octal, hex, and IPv4-mapped IPv6 literals are all decoded, reserved ranges including cloud metadata are blocked, both A and AAAA records resolve over DNS-over-HTTPS, and every redirect hop plus the post-render final URL is re-checked
- A dimension the scan could not assess is reported as unassessed, and an unassessed dimension can never earn a confident Ship
- A labeled golden set runs the real pipeline inside the test suite and holds three zeros: no false positives, no false negatives on the labeled findings, no wrong verdicts
The scanner is metered like money, because it is money.
Around the engine sits a full SaaS on the same D1 database: accounts on better-auth, Stripe billing spoken over plain REST with no SDK, monitors that re-audit on a schedule or on a deploy webhook, regression alerts over Resend, a hosted report served through a visibility-gated proxy, and an embeddable trust badge that resolves server-side to a real settled audit, so it cannot be forged or frozen green.
- Credits live in an append-only ledger: the balance is computed, never stored, a reserve is a single conditional insert, and a refund carries a consume-guard so a slow-but-delivered audit cannot be refunded after its report went out
- Paid audits ride a Queue with a dead-letter lane; the consumer is idempotent against at-least-once delivery with a claim-based state machine
- The engine imports the ledger code from the web app instead of duplicating money SQL: one source of truth, two runtimes
- A post-build step hashes every inline script and style into the CSP, so the static site ships without
unsafe-inline; the hosted report uses a per-response nonce instead - The landing page flies a scroll-driven route past the planets, lit by a small WebGL2 shader that is strictly additive: any failure or slow frame removes it and leaves exactly the page that shipped without it
What I picked, and what I didn't.
-
01
The verdict is a gate, not an average.
A weighted average lets a leaked key hide behind a pretty performance score. Should It Launch scores all eight dimensions, then decides the verdict in priority order: any confirmed critical or ship-blocking finding forces Not ready, any dimension under its floor forces Ship with fixes, and only a clean board earns Ship. The honesty rule is written into the scorer: a floored dimension that only produced a skip counts as unassessed, not as passing.
Considered: one blended 0-100 score (rejected, it buries ship-blockers), per-tool scores like the incumbents (rejected, that fragmentation is the problem the product exists to end)
-
02
Validate the IP you resolved, not the URL you were given.
A scanner that fetches arbitrary URLs is a server-side request forgery machine unless you make it not one. The guard resolves both A and AAAA records over DNS-over-HTTPS, decodes every IP-literal disguise an attacker uses (decimal, octal, hex, IPv4-mapped IPv6), blocks the reserved ranges including the cloud metadata address, and re-validates after every redirect hop and again on the final URL after render. Forty tests hold that wall.
Considered: a hostname blocklist (rejected, trivially bypassed by DNS rebinding or an open redirect), leaning on the browser sandbox (rejected, the checker also fetches outside the browser)
-
03
Money is an append-only ledger, not a balance column.
The credit balance is a sum of deltas, computed at read time. Reserving a credit is a single conditional insert that only lands if the balance stays positive, so concurrent audits cannot spend the same credit twice under D1's serialized writes. Refunds carry a consume-guard: once a report is delivered, the credit that paid for it can no longer flow back. The ledger closed a real refund-after-consume leak found during hardening.
Considered: a stored balance column (rejected, it races), trusting the queue to deliver exactly once (rejected, Cloudflare Queues are at-least-once by contract)
Live at shoulditlaunch.com, free scans open.
The whole loop runs in production: paste a URL, get the free static scan, sign up, spend a credit on the full rendered audit, read the hosted dossier, wire a monitor, embed the badge. Three free scans a day with no card and no account, exactly as the hero promises. And where a finding cannot be verified live, the scanner says so: an unverified secret is deliberately reported one severity below a verified one.
The scanner holds itself to the standard it grades. No unsafe-inline
in its own CSP, an accuracy gate in CI that tolerates zero false positives,
and evidence attached to every claim it makes about someone else's site.