Preflight scans your codebase before you deploy, and tells you what would embarrass you in production: the leaked key, the missing variable, the lapsed certificate, the page with no title.

One command, on your machine or in CI. Your code never leaves it and there is no account to make. It knows 72 services and every major framework and CMS. MIT licensed.

Homebrew

brew install preflightsh/preflight/preflight

npm

npm install -g @preflightsh/preflight

Go

go install github.com/preflightsh/preflight@latest

Docker

docker pull ghcr.io/preflightsh/preflight

curl

curl -sSL https://preflight.sh/install.sh | sh

Then, in your project: preflight init once, and preflight scan before every deploy.

Scan

Every check says OK, WARN or FAIL, and what to do about it.

This is a real scan of a small Next.js store with a few launch mistakes planted in it: a SendGrid key in the code, a webhook secret missing from .env, Sentry declared and never started, no favicon and no 404 page.

~/acme-store
preflight scan

 ✈  Preflight Scan Results
   Project: acme-store

  🔍  SEO        SEO metadata                                  ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  🔍  SEO        Canonical URL                                 ⚠ WARN
                    └─ No canonical URL tag found
                       • Add canonical to metadata: alternates: { canonical: 'https://...' }
                       • Or set metadataBase in root layout.tsx
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📱  SOCIAL     OG & Twitter cards configured                 ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📱  MOBILE     Viewport meta tag                             ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  🌐  LANG       HTML lang attribute                           ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  🔍  SEO        Structured data (JSON-LD)                     ⚠ WARN
                    └─ No structured data found
                       • Add JSON-LD script in layout: <script type="application/ld+json">{...}</script>
                       • Or use next-seo package for structured data
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  🔑  SECRETS    Secrets scan                                  ✗ FAIL
                    └─ Potential secrets found in 1 place(s)
                       • lib/mailer.ts:2 (SendGrid API key) [not gitignored]
                       • Remove secrets from source code
                       • Use environment variables instead
                       • Add sensitive files to .gitignore
                       • Consider using git-crypt or similar for encrypted secrets
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📋  ENV        Environment variables                         ⚠ WARN
                    └─ Missing in .env: STRIPE_WEBHOOK_SECRET
                       • Add STRIPE_WEBHOOK_SECRET to .env
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📦  DEPS       Dependency vulnerabilities                    ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  🐞  DEBUG      Debug statements                              ⚠ WARN
                    └─ Found 1 debug statement(s)
                       • app/page.tsx:1 - console.log
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📃  PAGES      Error pages (404, 500)                        ⚠ WARN
                    └─ No custom 404 page found
                       • Create pages/404.tsx (Pages Router)
                       • Or create app/not-found.tsx (App Router)
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  ⚡  PERF       Image optimization                            ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  ⚖️   LEGAL      Privacy & Terms pages                         ⚠ WARN
                    └─ Missing: privacy policy, terms of service
                       • Add a privacy policy page (e.g., /privacy)
                       • Add terms of service page (e.g., /terms)
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  🎨  ICONS      Favicon and app icons                         ✗ FAIL
                    └─ Missing favicon
                       • Add favicon.ico or favicon.png to public/
                       • Use https://realfavicongenerator.net for complete icon set
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📄  FILES      robots.txt                                    ✓ OK
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📄  FILES      sitemap.xml                                   ⚠ WARN
                    └─ sitemap.xml not found
                       • Add sitemap.xml to public/ directory
                       • Consider using next-sitemap or similar generator
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  📄  FILES      llms.txt                                      ⚠ WARN
                    └─ llms.txt not found
                       • Add llms.txt to help AI understand your site
                       • See https://llmstxt.org for specification
  · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

  ────────────────────────────────────────────────────────

 🔌 Checked Services

  🐛  ERRORS     Sentry                                        ⚠ WARN
                    └─ Sentry is declared but initialization not found
                       • Add Sentry.init() to your application entry point
                       • Check Sentry documentation for your framework

  ────────────────────────────────────────────────────────

  ✓ Passed:  7    ⚠ Warnings: 9    ✗ Failed:  2

  ✗ Not ready for launch

Captured from Preflight 0.22.0. The key is made up, and the report shows where a secret is, never the secret.

Why

Because everyone has shipped something broken.

A variable you forgot to set. Debug output left in. A certificate that lapsed over the weekend. A launch with no favicon and no privacy page. None of it is hard to fix; all of it is easy to miss when you are busy shipping.

Preflight is the “did I leave the stove on?” check for your codebase. Run it before you deploy, or put it in CI and stop thinking about it. No account, no dashboard to remember, and nothing to maintain beyond one preflight.yml.

Checks

What it looks for.

  • secretsAPI keys and credentials committed to the code, reported by file and line, never by value.
  • env_parityVariables your .env.example promises that .env doesn’t have.
  • security_headersHSTS, CSP and X-Content-Type-Options, on production and staging.
  • sslA valid certificate, with a warning well before it expires.
  • vulnerabilityKnown holes in your dependencies, through your package manager’s own audit.
  • debug_statementsconsole.log, var_dump and debugger left behind.
  • seo_metaA title, a description, Open Graph and Twitter cards, a canonical URL, JSON-LD.
  • error_pagesYour own 404 and 500 pages, not the framework’s.
  • legal_pagesA privacy policy and terms of service.
  • faviconA favicon, an apple-touch-icon and a web manifest.
  • robots_txtAnd the rest of the files a site should serve: sitemap.xml, llms.txt, ads.txt, humans.txt.

Each has an ID for --only, --skip and preflight ignore. Every check, with its ID.

Services

And the 72 services your app talks to.

Preflight finds the services a project uses and checks each one is wired up: the key is in the environment, the SDK is started, the script is in the layout.

Payments
StripePayPalBraintreePaddleLemonSqueezy
Error Tracking
SentryBugsnagRollbarHoneybadgerDatadogNew RelicLogRocket
Email & Newsletters
PostmarkSendGridMailgunAWS SESResendMailchimpKitBeehiivAWeberActiveCampaignCampaign MonitorDripKlaviyoButtondown
Analytics
FullresPlausibleFathomUmamiGoogle AnalyticsPostHogMixpanelAmplitudeSegmentHotjarDatafa.st
Auth
Auth0ClerkWorkOS
Chat
IntercomCrisp
Notifications
SlackDiscordTwilio
Infrastructure
RedisSidekiqRabbitMQElasticsearchConvexFirebaseSupabase
Storage & CDN
AWS S3CloudinaryCloudflare
Search & SEO
AlgoliaIndexNow
AI & LLMs
OpenAIAnthropicGoogle AIMistralCohereReplicateHugging FaceGrokPerplexityTogether AI
Cookie Consent
CookieConsentCookiebotOneTrustTermlyCookieYesIubenda

Stacks

Whatever you built it with.

preflight init works out your stack, so each check knows which layout holds your <head>, where your public files live and which package manager to ask.

Backend
Ruby on RailsLaravelPHPGoPython/DjangoRustNode.js
Frontend
Next.jsNuxtRemixReactVue.jsViteSvelteAngular
CMS
WordPressCraft CMSDrupalGhostStrapiSanityContentfulPrismic
Static Generators
HugoJekyllGatsbyEleventyAstro

CI

Put it in CI, and a pull request can’t ship a launch mistake.

A scan exits 2 when it finds an error and 1 on warnings only, so the step fails exactly when it should. Add --format json for something a script can read.

.github/workflows/ci.ymlGitHub Actions
- name: Run Preflight
  run: |
    curl -sSL https://preflight.sh/install.sh | sh
    preflight scan --ci

With npm or Docker instead, and how to fail on errors only: the CI docs.

Agents

Or hand it to your coding agent.

Preflight ships an agent skill on skills.sh that teaches Claude Code, Cursor, Codex, OpenCode and more than 50 other agents to run a scan, fix what it finds without ignoring checks to get a pass, and scan again to prove it.

npx

npx --yes skills add preflightsh/preflight --skill preflight

bunx

bunx --yes skills add preflightsh/preflight --skill preflight

Then ask it, in plain words, whether the project is ready to launch. More in the agent skill docs.

Dashboard

Keep a history, and get a fix for every finding.

Add --publish and the run lands on your dashboard at app.preflight.sh, beside every run before it. Open any warning or failure for a step-by-step fix written for your stack. Only a redacted summary leaves your machine: check IDs, statuses and messages, never your code or a secret.

preflight.sh
← All projects

acme-store · just now

acme-store is not ready for launch.

2 failed9 warnings7 passed

Copy all fixes as MarkdownDelete run

Failed

FAIL

Secrets scansecrets

Potential secrets found in 1 place(s)

Copy

AI fix suggestion

A SendGrid API key is hardcoded in lib/mailer.ts. Treat it as leaked: anyone with the repository can send mail as you.

  • Revoke the key in SendGrid under Settings, API Keys, and create a new one.
  • Put the new key in .env as SENDGRID_API_KEY, and add the name to .env.example.
  • Read it from the environment instead of the code:
export const mailer = {
  apiKey: process.env.SENDGRID_API_KEY!,
};

Then rerun preflight scan --only secrets to confirm.

FAIL

Favicon and app iconsfavicon

Missing favicon

Copy

AI fix suggestion

The App Router picks up icons by file name, so no code is needed. Add these to app/:

  • app/favicon.ico, 32 by 32
  • app/icon.png, 512 by 512
  • app/apple-icon.png, 180 by 180

Next.js writes the <link> tags for each one.

Warnings

WARN

Canonical URLcanonical

No canonical URL tag found

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

Structured data (JSON-LD)structured_data

No structured data found

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

Environment variablesenv_parity

Missing in .env: STRIPE_WEBHOOK_SECRET

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

Sentrysentry

Sentry is declared but initialization not found

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

Debug statementsdebug_statements

Found 1 debug statement(s)

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

Error pages (404, 500)error_pages

No custom 404 page found

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

Privacy & Terms pageslegal_pages

Missing: privacy policy, terms of service

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

sitemap.xmlsitemap

sitemap.xml not found

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

WARN

llms.txtllms_txt

llms.txt not found

Copy

AI fix suggestion

Writing a fix for your stack. This takes a few seconds the first time; after that it’s kept on the run.

Passed

  • SEO metadata
  • OG & Twitter cards configured
  • Viewport meta tag
  • HTML lang attribute
  • Dependency vulnerabilities
  • Image optimization
  • robots.txt

The dashboard’s page for the scan above, drawn from its JSON with the app’s own markup; scroll inside it. The two fixes are examples of what the AI writes. Free for 5 published runs a month; unlimited with your own OpenAI or Anthropic key, or $5 a month with the AI on us. How it works.

Run it once before your next deploy, and find out what you missed.

Read the docs Source on GitHub Create an account