Overview
Clear every item on this list before directing real users to a new deployment. This page is the security and day-one-breakage twin of launch-a-new-site, which covers deploy ordering, DNS, and SEO sequencing. Work through these categories in order; later items depend on earlier ones being clean.
Day-one breakage: verify the app renders and recovers
No white screen on load. Open the app in an incognito window with devtools open. A blank render or frozen spinner on first paint is the single most-reported day-one failure. Check the console for unhandled promise rejections and hydration mismatches.
Forms must not lose user data on validation errors. Fill a form, submit with a bad field, and confirm the other fields retain their values. If the form resets on error, users abandon; fix before launch.
Wrap risky UI in error boundaries. Any component that fetches remote data, renders user-supplied content, or calls a third-party SDK should have an error boundary or equivalent (try/catch in server components, <ErrorBoundary> in React). A single thrown exception should never white-screen the entire page.
Audit primary routes for dead links and 404s. Walk every route listed in your sitemap. Use audit-checklist to run a crawl and catch broken internal links before users do.
Test on slow connections. Throttle devtools to “Fast 3G” and confirm loading states appear, not blank frames. Users on mobile or flaky connections encounter slow renders more often than desktop users on fiber.
Security: close the gaps before traffic arrives
No secrets in the client bundle. Search your built output (dist/ or .next/) for strings that match your secret key patterns. Private keys, service-role tokens, and database URLs must never appear in any file served to the browser. See secrets-and-env for environment variable discipline.
RLS enabled on every table. Supabase (and Postgres in general) disables row-level security by default on tables created via raw SQL. Run SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public'; and confirm rowsecurity = true for every table. A table with RLS disabled and a public Data API key exposes all rows to any request. See supabase-rls for policy patterns.
Rate limiting on public and auth endpoints. Auth endpoints (login, signup, password reset) must be rate-limited before launch; credential-stuffing attacks start within minutes of a new domain going live. A common baseline: 5 login attempts per 15 minutes per IP, 3 password-reset requests per hour. General public API endpoints should have a ceiling even if generous. Cloudflare WAF rules or middleware-level limiting both work; pick one and verify it fires.
Auth enforced on every protected route and API handler. Write a test that calls each protected endpoint without a session token and confirm it returns 401, not data. It is common during development to comment out auth guards and forget to restore them. See auth-sessions for session validation patterns.
Input validated at the boundary. Validate and sanitize all user input on the server, not only in the client form. Client-side validation is a UX courtesy; server-side validation is the security control.
Legal and ops: understand your exposure
Privacy policy and terms of service present and linked. Both pages must be reachable from the footer before launch. Many jurisdictions (GDPR, CCPA) require a privacy policy to be accessible before data collection begins.
Cookie consent if needed. If you set non-essential cookies (analytics, advertising, A/B test buckets) you likely need a consent banner for EU/UK visitors. If you set only a session cookie required for login, you may be exempt; confirm with counsel if unsure. TODO: add a dedicated cookie-consent page with jurisdiction breakdown.
Payments: merchant-of-record and sales-tax exposure understood. If you collect payments, confirm whether your payment processor (see payments-stripe) acts as merchant of record for tax purposes, or whether you are responsible for remitting sales tax. This is not a launch blocker for small volumes, but ignoring it creates retroactive liability. Understand it before revenue starts.
Observability: wired before users arrive
Error tracking live before launch. Install and verify your error tracker (see error-tracking) in the production environment before going live. Confirm a test error reaches the dashboard. Discovering that error tracking was pointed at the wrong DSN after a 3 AM outage is avoidable. Review incident-response so your on-call process is defined before you need it.
Copy-paste checklist
Paste this block into your project TODO.md and check off items before flipping DNS.
## Pre-launch checklist
### Day-one breakage
- [ ] No white screen or frozen spinner on first load (checked incognito)
- [ ] Console clear of unhandled rejections and hydration errors
- [ ] Forms retain field values after a validation error
- [ ] Error boundaries wrap all remote-data and third-party components
- [ ] All primary routes return 200; no 404s on sitemap pages
- [ ] UI tested under simulated slow connection (Fast 3G throttle)
### Security
- [ ] Built output searched for secret key patterns; none found
- [ ] RLS enabled on every public-schema table (verified via pg_tables)
- [ ] Auth endpoints rate-limited (login: ≤5/15 min, reset: ≤3/hr)
- [ ] General public API endpoints have a ceiling rate limit configured
- [ ] Every protected route returns 401 without a valid session token
- [ ] Server-side input validation present on all form and API handlers
### Legal / ops
- [ ] Privacy policy linked from footer
- [ ] Terms of service linked from footer
- [ ] Cookie consent assessed; banner added if non-essential cookies present
- [ ] Payment tax/merchant-of-record exposure documented (if taking payments)
### Observability
- [ ] Error tracker installed and verified in production environment
- [ ] Test error confirmed reaching dashboard
- [ ] On-call / incident-response process definedRelated
- launch-a-new-site; deploy ordering, DNS cutover, and SEO sequencing
- audit-checklist; crawl-based audit to catch broken links and missing tags
- secrets-and-env; environment variable discipline and secret rotation
- supabase-rls; row-level security policy patterns
- error-tracking; setting up and verifying error tracking in production
- payments-stripe; Stripe integration and merchant-of-record notes
- auth-sessions; session validation patterns and auth guard checklist
- incident-response; on-call runbook and post-mortem process