[Free check]
Check your Next.js app
in one command.
24 checks for the problems that pass lint, types and the build: open AI endpoints, retired models, unsigned webhooks, missing row level security and leaked keys. Runs locally in about a second. No install, no account.
$ npx whirlwindaiSource on GitHub·npm·MIT licence
whirlwindai check · acme-notesNext.js 15.2 (App Router) · Supabase · Stripe · OpenAI, AnthropicAI cost✗ Every endpoint that calls a model checks who is calling ai-auth✗ app/api/summarize/route.ts calls a model (OpenAI) with no sign-in checkAnyone on the internet can call it and spend your AI budget.✗ No retired or deprecated model IDs models✗ lib/ai.ts uses claude-3-5-sonnet-20241022, which the provider has retiredAuth✗ No open redirects open-redirect✗ app/auth/callback/route.ts redirects to the "next" query parameter uncheckedDatabase! Privileged database functions are locked down supabase-rpc! supabase/migrations/001_init.sql add_credits() is SECURITY DEFINER and callable by anyoneSupabase exposes it at /rest/v1/rpc/add_credits.3 problem(s), 1 warning(s) · 24 checks · 0.1s
What it checks
The mistakes AI agents make most
Secrets
- .env files committed to git
secrets-tracked - OpenAI, Anthropic, Stripe, Google, Resend and GitHub keys in the code
secrets-hardcoded - Secrets in NEXT_PUBLIC_ variables, which ship to every visitor
secrets-public
AI cost
- API routes and server actions that call a model without checking who is calling
ai-auth - Model calls with no rate limit, credits or quota
ai-limit - Model IDs the provider has retired or deprecated
models
Payments
- Stripe webhooks that skip the signature check
stripe-webhook - Checkout amounts or price IDs taken from the request
stripe-price - Success and cancel URLs built from the caller's Origin header
stripe-redirect - Lemon Squeezy, Paddle, Polar, Clerk and GitHub webhooks that don't verify the sender
webhooks
Auth
- ?next= and similar parameters redirected to without a check
open-redirect - Links built from the caller's Origin or Host header, especially emailed ones
origin-links - Server code trusting auth.getSession()
supabase-session
Database
- Tables without row level security, and policies that allow any write
supabase-rls - SECURITY DEFINER functions anyone can call through the API
supabase-rpc - Tables the code queries that no migration creates
supabase-tables - Firebase rules that allow everyone, including expired test-mode rules
firebase-rules - SQL built by pasting values into the query text
raw-sql
Code
- Local and @/ imports that point at nothing
imports - a + "text" || fallback, where the fallback can never run
precedence - Dynamic pages that return a 500 instead of a 404 for an unknown ID
not-found - Missing error and not-found pages
error-pages - next.config letting /_next/image fetch from any host
image-proxy - Environment variables the code reads that .env.example doesn't list
env-example
Checks for a service only run when your project uses it. AI: OpenAI, Anthropic, Gemini, Vercel AI SDK, LangChain, LlamaIndex, Mastra, Bedrock, Groq, Mistral, Replicate and more. Auth: Supabase, Auth.js, Clerk, Kinde, Better Auth, Lucia, iron-session, tRPC, next-safe-action. Data: Supabase, Firebase, Prisma, Drizzle, pg. Payments: Stripe, Lemon Squeezy, Paddle, Polar.
How it works
Reads your code. Sends nothing.
The check reads your project on your machine, in a git repo following your .gitignore. It works with the App Router and the Pages Router, JavaScript and TypeScript, import aliases from your tsconfig, and monorepos (run it on each app, for example npx whirlwindai apps/web). Build scripts, tests, generated code and examples are skipped.
Add --deep to ask OpenAI, Anthropic and Google which models your keys can actually use. Each key is sent only to its own provider.
It reads code rather than running it, so it can miss a problem written in an unusual way, or flag something that is fine. Silence a finding with a comment that names the check and the reason: // whirlwind-check-ignore: ai-auth internal tool. Every check was tuned against real open-source apps, including Vercel's AI chatbot, Commerce and SaaS starter, Dub and chatbot-ui.
In CI
Check every pull request
The check exits 1 on problems and 2 on warnings only, so one line in a workflow stops a change that opens an AI route or skips a webhook signature from merging.
# .github/workflows/check.yml
name: check
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npx whirlwindai # fails the build on problemsComing next: Watch
Know before a model is retired
Some problems arrive without a code change. Providers retire models, deprecate APIs and change limits, and the first sign is usually an error in front of a user. The free check sees your code as it is when you run it.
Watch runs those checks for you:
- ·A nightly live check of every model, service and key your app uses, with an email or Slack alert when one is deprecated or stops working
- ·Findings posted on your pull requests, with a history across pushes
- ·One view across all your repos, with shared ignore rules for teams
It isn't built yet. Join the waitlist and you'll hear first, with early pricing.
The free check and Whirlwind
Find the problems, or start without them
The free check is the general version of the Whirlwind audit, for an app you already have. Whirlwind is the Next.js AI SaaS starter where these problems are fixed from the start, with checks built for its own architecture that your agent runs after every change.
| Free check | Whirlwind | |
|---|---|---|
| 24 general checks, on any Next.js app | ✓ | ✓ |
| Those problems fixed in the code from day one | · | ✓ |
| 33 audit checks written for the template's architecture | · | ✓ |
| Live doctor: every service, migration and AI model | Models only, with --deep | ✓ |
| 27 end-to-end tests: signup, checkout, credits | · | ✓ |
| Contract files, so your agent avoids the mistakes in the first place | · | ✓ |
| Price | Free, open source | One payment |