| name | nextjs-audit |
| description | Full-stack audit for local Next.js + Supabase + Vercel projects. Covers security (RLS, route protection, admin access, email headers, auth), database design (schema quality, indexes, relationships), performance (pagination, N+1 queries, bundle size, caching), and scalability strategy (SaaS readiness, infra growth, data retention). Runs entirely on local code — never hits production. Use when user says "audit", "revisar proyecto", "security check", "performance review", "is my app ready", or invokes /nextjs-audit.
|
Next.js + Supabase + Vercel — Full Stack Audit
Comprehensive local-only audit for projects built on the Next.js + Supabase + Vercel stack. Analyzes code, migrations, RLS policies, route protection, performance patterns, and produces actionable findings with fixes.
Invocation
/nextjs-audit [path]
path is optional. If omitted, use the current working directory.
- The project MUST be a local Next.js project with Supabase. Verify by checking for
next.config.* and supabase/ directory (or .env* with Supabase keys).
Scope
Always local. This skill reads source code, migration files, environment config, and route definitions. It never makes network requests to production, never connects to a live Supabase instance, never deploys anything.
Architecture
The audit runs in 5 phases. The orchestrator coordinates and compiles the final report.
Phase 1: Discovery (project structure, tech stack, dependencies)
│
Phase 2: Security (RLS, auth, routes, admin, email, headers)
│
Phase 3: Database (schema design, indexes, relationships, migrations)
│
Phase 4: Performance (queries, pagination, bundle, caching, fetching)
│
Phase 5: Scalability (infra strategy, SaaS readiness, data retention, growth plan)
│
Final: Compile report + prioritized fix list
Phase Details
Phase 1: Discovery
Understand the project before auditing. Gather:
-
Project structure:
app/ vs pages/ router
- API routes location (
app/api/ or pages/api/)
- Middleware file (
middleware.ts)
- Supabase client initialization (where/how)
- Auth provider (Supabase Auth, NextAuth, custom)
-
Dependencies:
- Read
package.json — note versions of next, @supabase/supabase-js, @supabase/ssr, @supabase/auth-helpers-nextjs
- Check for deprecated packages (auth-helpers is deprecated in favor of @supabase/ssr)
-
Supabase setup:
supabase/ directory presence
- Migration files in
supabase/migrations/
supabase/config.toml settings
- Seed files
- Edge functions in
supabase/functions/
-
Environment variables:
.env.local, .env, .env.example — check what's declared
- Verify
NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY exist
- Check for
SUPABASE_SERVICE_ROLE_KEY usage (should NEVER be in client code)
-
Vercel config:
vercel.json — headers, redirects, rewrites, cron
- Environment variable naming conventions
Output: Project profile summary used by all subsequent phases.
Phase 2: Security
2.1 RLS (Row Level Security)
Read ALL migration files and check:
Common RLS failures to flag:
- Table with no RLS at all (CRITICAL)
- Policy that uses
true as check (allows everything)
- Policy that checks
user_id from the request body instead of auth.uid()
- Missing policy for UPDATE/DELETE (defaults to deny — might be intentional, flag for review)
2.2 Route Protection
404 / Route Exposure:
2.3 Admin Protection
2.4 Email Security
If the project sends emails (check for Resend, SendGrid, nodemailer, Supabase Auth emails):
2.5 Auth & Session
2.6 Rate Limiting
Check if rate limiting is implemented on abuse-prone endpoints:
What to look for in code:
- Packages:
@upstash/ratelimit, rate-limiter-flexible, express-rate-limit, custom Redis-based
- Vercel's built-in:
vercel.json with "rateLimit" config
- Supabase Edge Functions: check if they use rate limiting
- Next.js middleware-based rate limiting (IP + route based)
Common failures:
- No rate limiting anywhere (CRITICAL on auth endpoints)
- Rate limiting only on client side (useless — attacker bypasses)
- Rate limiting by user ID only (unauthenticated endpoints unprotected)
- No rate limiting on expensive operations (AI/LLM calls, file processing)
2.7 CAPTCHA / Bot Protection
Check if CAPTCHA or bot protection exists on public-facing forms:
What to look for in code:
- Packages:
@hcaptcha/react, react-google-recaptcha, @turnstile/react (Cloudflare), react-turnstile
- Server-side verification of CAPTCHA token (not just client-side widget)
- Honeypot fields as lightweight alternative
- Supabase Auth CAPTCHA integration (supports hCaptcha/Turnstile natively)
Common failures:
- CAPTCHA widget present but token never verified server-side (CRITICAL — decoration only)
- No bot protection on signup (mass account creation possible)
- No bot protection on any form that sends emails (spam vector)
- CAPTCHA secret key in client-side code (defeats the purpose)
2.8 Environment Variables & Secret Exposure
How to detect:
- Grep all files for
NEXT_PUBLIC_ and verify each one is safe to expose (only Supabase URL and anon key should be public)
- Grep for hardcoded patterns: API key formats (
sk-, pk_live_, re_, whsec_), base64 tokens, JWTs
- Check if any
process.env.SECRET_* is referenced in files under app/ without "use server" or in page.tsx/layout.tsx client components
- Check git history for accidentally committed
.env files (flag for manual review)
Common failures:
- OpenAI/Anthropic key in
NEXT_PUBLIC_OPENAI_API_KEY (CRITICAL — anyone can steal it from browser DevTools)
- Stripe secret key exposed client-side
- Service role key used in a client component (leaks full DB access)
.env committed to git at some point (even if later removed — it's in history)
2.9 Server-Side Boundary Enforcement
Verify that operations requiring server-side execution are actually server-side:
What to look for:
"use client" files importing sensitive env vars
createBrowserClient() used where createServerClient() should be
- API calls to external services directly from client (instead of proxying through API route)
- Form validation only in client (no server re-validation)
Common failures:
- Calling OpenAI directly from a client component (exposes API key)
- Stripe checkout created client-side with secret key
- File upload goes directly to external service without server validation
- Business logic in client that should be a server action (price calculation, discount application)
2.10 AI/LLM Usage Controls
If the project uses AI services (OpenAI, Anthropic, Replicate, Vercel AI SDK, etc.):
What to look for:
- Packages:
openai, @anthropic-ai/sdk, ai (Vercel AI SDK), replicate, @google/generative-ai
- Usage tracking: is there a
tokens_used or ai_requests counter per user?
- Limits: is there a check before calling AI? (
if (user.aiRequestsToday >= limit) return 429)
- Spending limits: provider dashboard config (can't verify locally — flag for manual check)
Common failures:
- No per-user limit on AI calls (one user can burn $1000 in API costs overnight) — CRITICAL
- AI endpoint accessible without authentication (anyone can use your API key)
- No input length validation (user sends 100k tokens, you pay for it)
- AI response rendered with
dangerouslySetInnerHTML (XSS via prompt injection)
- No timeout on AI calls (user hangs indefinitely on slow response)
2.11 Security Headers (Vercel/Next.js)
Check next.config.js or vercel.json for security headers:
Phase 3: Database Design
Read all migration files (in order) and reconstruct the schema. Analyze:
3.1 Schema Quality
3.2 Indexes
3.3 Relationships
3.4 Multi-tenancy
3.5 Audit & Logging Tables
Phase 4: Performance
4.1 Data Fetching Patterns
4.2 Caching
4.3 Bundle & Loading
4.4 Database Performance
Phase 5: Scalability & Strategy
5.1 Current Architecture Assessment
- What's the current deployment model? (Vercel serverless + Supabase hosted)
- What are the scaling bottlenecks? (DB connections, serverless cold starts, edge function limits)
- Is the app stateless? (Can it scale horizontally?)
5.2 SaaS Readiness (if applicable)
If the app has multi-user/org patterns, assess:
5.3 Growth Strategy Recommendations
Based on the audit findings, provide recommendations on:
- Stay on Vercel + Supabase — when current usage fits free/pro tier limits
- Upgrade tiers — when approaching limits but architecture is fine
- Move to VPS + Docker — when:
- Supabase costs exceed self-hosted PostgreSQL
- Need persistent background workers
- Need more control over DB (extensions, custom configs)
- Volume of data makes Supabase pricing prohibitive
- Hybrid approach — Vercel for frontend, VPS for API/workers/DB
For VPS recommendations, include:
- Suggested architecture (Docker Compose, volumes, backup strategy)
- Migration path from Supabase (pg_dump, storage migration)
- Cost comparison at projected scale
- Monitoring & alerting needs
5.4 Data Retention & Cleanup
5.5 High Availability Considerations
- Vercel: already multi-region by default (note limitations)
- Supabase: single-region by default — recommend read replicas if needed
- Point-in-time recovery configured?
- Backup strategy for user-uploaded files (Supabase Storage)
- Graceful degradation if Supabase is down (queue writes, show cached data)
Output Format
The final report is saved to {project_root}/AUDIT-REPORT.md with this structure:
# Audit Report: {project_name}
**Date:** {date}
**Stack:** Next.js {version} + Supabase + Vercel
**Router:** App Router / Pages Router
**Score:** {X}/100
## Executive Summary
{3-5 sentences: overall health, critical issues, top priorities}
## Scores by Category
| Category | Score | Critical | Major | Minor |
|----------|-------|----------|-------|-------|
| Security | X/25 | N | N | N |
| Database | X/25 | N | N | N |
| Performance | X/25 | N | N | N |
| Scalability | X/25 | N | N | N |
## Critical Findings (fix immediately)
{Findings that represent security vulnerabilities or data loss risk}
## Major Findings (fix soon)
{Findings that impact reliability, performance, or maintainability}
## Minor Findings (nice to have)
{Improvements that would enhance quality but aren't urgent}
## Scalability Strategy
{Growth recommendations based on Phase 5 analysis}
## Fix Checklist
- [ ] {Prioritized list of fixes, ordered by impact}
- [ ] ...
## Detailed Findings
### Security
{Full details per finding with code references and fix examples}
### Database
{Full details per finding with migration examples}
### Performance
{Full details per finding with before/after code}
### Scalability
{Full details per recommendation}
Scoring Rubric
Each category is 25 points. Deductions:
- Critical finding: -5 points each
- Major finding: -3 points each
- Minor finding: -1 point each
- Minimum score per category: 0 (no negatives)
A project scoring 80+ is in good shape. Below 60 needs significant work. Below 40 has critical issues.
What This Skill Does NOT Do
- Does NOT connect to live Supabase instances
- Does NOT run the project or make HTTP requests
- Does NOT modify any code (audit only — fixes are separate)
- Does NOT check deployed Vercel configuration (only local vercel.json)
- Does NOT run tests or build the project
If the user wants fixes applied after the audit, that's a separate ASDLC cycle using the audit report as input.