Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LaunchPreflight

Pre-launch checklists for web developers, freelancers and agencies.

LaunchPreflight is the checklist you run before a website goes live. Every project starts with 42 curated checks across SEO, security, performance, DNS & SSL, analytics and backups — each one with a short explanation of why it matters and what to actually do about it. Track status per check, leave notes, add checks of your own, and watch a weighted readiness score tell you whether you are genuinely ready to ship or just close to it.

Everything runs in the browser. No account, no backend, no data leaving the machine.

Try the live demo →

LaunchPreflight dashboard

The demo is the real application with the bundled example project. Live verification is the one thing it cannot do there: that needs the companion process on your own machine, and the deployed origin is deliberately not on its allowlist — otherwise a public web page could drive a local service. Clone the repository and run npm run dev to see that part.


Features

  • Multiple projects — create, rename, reconfigure and delete website projects, each with its own URL, environment (Production / Staging / Development) and optional launch date.
  • A real checklist, not a stub — 42 predefined checks written as guidance, not labels. Each carries a description, a "why this matters" explanation and two to four concrete steps.
  • Weighted readiness score — Critical checks count 4×, Important 3×, Recommended 2×, Optional 1×. A check in progress earns half its weight, one needing attention a quarter. The result is a single honest percentage rather than a count of ticked boxes.
  • Launch gate — any unresolved Critical check means Not ready to launch, however high the percentage is.
  • Custom checks — add your own with a title, description, category and priority. They behave exactly like predefined ones, and unlike them they can be deleted.
  • Filter and search — filter by status or category, search titles and descriptions, and clear it all in one click.
  • Detail panel — a docked panel on wide screens, a drawer on smaller ones, with guidance, status actions and an autosaving notes field.
  • Markdown export — a launch report grouped by category, with critical issues pulled to the top and your notes included, ready to hand to a client.
  • Templates — four built-in checklists (standard, WordPress, headless/Jamstack, static), plus your own: save any project's checklist as a template, and share it as a file.
  • Reports — every project side by side, a client-facing summary per project, readiness over time as a trend, and everything still outstanding grouped by priority.
  • Settings — pick the default checklist and environment for new projects, choose a date format, and export or import all your data as a single JSON file.
  • Live verification — a "Live verification" KPI sits beside the readiness score and opens the full report; an Auto column in the checklist shows the automatic verdict per check. An optional companion process on your own machine runs 30 real probes covering 30 of the 42 checks: HTTP status and redirect chains, security headers, the TLS certificate, DNS records and TTL, SPF/DMARC, leftover .env and .git files, framework debug output, version disclosure, robots.txt, the sitemap, title, meta description, canonical, OpenGraph, favicon, 404 handling, compression, cache policy, mixed content, image weight and formats, lazy loading, third-party scripts, the analytics tag, a consent tool, search-engine verification and form spam protection.
  • Post-launch monitoring — every run is kept, and the Reports page shows what regressed or improved since the run before, so a certificate quietly expiring or a header disappearing after a deploy shows up.
  • Dark by default, light on request — both themes are first-class, and the choice survives a reload without a flash of the wrong palette.
  • Local persistence — everything lives in localStorage, validated on read so a corrupt or hand-edited store recovers instead of white-screening.

Tech stack

Concern Choice
UI React 19, TypeScript (strict)
Build Vite 8
Styling Tailwind CSS v4 (CSS-first @theme tokens)
Components shadcn/ui-style primitives on Radix UI, vendored into src/components/ui
Icons Lucide
State Zustand with the persist middleware
Validation Zod 4 — schemas are the source of truth for the domain types
Tests Vitest
Lint / format oxlint, Prettier

No backend, database, authentication or payment dependency — by design.

Live verification and monitoring

A browser cannot verify someone else's website. It is not allowed to read another origin's response headers, status codes or HTML, and a no-cors request returns an opaque result with no headers and an empty body — so the only thing the page itself could ever establish is "the host answered". For a launch tool, a green tick that means nothing is worse than no tick at all.

So the real checks run in a small companion process on your machine. npm run dev starts it alongside the app, and the app finds it by itself — there is nothing to configure and no token to paste. Press Verify in the project header and it works.

npm run dev                            # app + verifier together
npm run verify https://your-site.com   # one-off, prints a table
npm run verify:serve                   # just the daemon

The twelve checks with no probe — backups, restore drills, admin account audits, whether tracking actually records, the redirect map from the old site — are not observable from the public internet. They stay manual rather than getting a probe that guesses.

The daemon binds to the first free port among 4319-4321 and the app probes the same three, so a busy port is not a dead end. If it is not running, the app says so and keeps working without it; start it later and the page picks it up within a few seconds, no reload.

Results never overwrite your own status. The manual status remains the truth for the readiness score; the automatic verdict appears next to it, and the app warns you when the two disagree.

Monitoring is the same runs kept over time: the Reports page compares the newest run with the one before and lists what regressed or improved. Schedule npm run verify from cron or launchd if you want it to keep checking after launch without opening the app.

Safety. Four independent checks, because a local service that fetches arbitrary URLs is otherwise a convenient tool for probing your own network:

  • It binds to 127.0.0.1, so nothing on the network can reach it.
  • It answers only requests addressed to a loopback hostname. Without this, DNS rebinding would defeat everything else: an attacker points their own domain at 127.0.0.1, their page becomes same-origin with the daemon, and no CORS check ever runs.
  • It answers only browser origins on its allowlist, so another site's JavaScript gets a 403 before any work happens — on the preflight and on the request itself.
  • It refuses to probe loopback, link-local and RFC1918 addresses, cloud metadata endpoints included, unless you pass --allow-private.

Point it at sites you are responsible for. One probe requests a short list of paths that should never survive a deploy — /.env, /.git/HEAD, lockfiles — and reports whether they are publicly readable. That is what makes the "secrets kept out of the repository" check verifiable at all. It only issues GET requests and reads at most two kilobytes, but in someone else's logs it looks like scanning, and running it against infrastructure you do not own may be unlawful where you are. SECURITY.md has the detail.

--token <value> additionally requires a bearer token on every request. It is off by default: those four checks are what actually keep other pages out, and requiring a paste step bought nothing but setup friction. When it is on, /health advertises it and the app asks you for the address under Settings → Live verification → Advanced.

Installation

Requires Node 20.19+ (or 22.12+) and npm.

npm install

Development

npm run dev

Then open http://localhost:5173. On first run the app seeds a realistic demo project (example.com, 87% ready, two outstanding critical checks) so the dashboard is worth looking at immediately. Its URL is a documentation domain, so live verification is deliberately unavailable for it — point a project at a site you actually run.

Other scripts:

npm run build          # typecheck + production build
npm run preview        # serve the production build
npm run typecheck      # app and verifier
npm run lint           # oxlint
npm run format         # prettier --write .
npm run dev:app        # the app alone, without the verifier
npm run verify <url>   # run the probes once
npm run verify:serve   # start the verifier daemon alone

Tests

npm run test        # single run
npm run test:watch  # watch mode

Tests cover the logic that is easy to get quietly wrong: the weighted readiness score, per-category progress, checklist filtering, Markdown report generation, template capture and instantiation, the readiness history, date formatting, backup serialisation and validation, the store's actions, the persistence layer's recovery from malformed data, drift detection between verification runs, the verifier's HTML extraction and attribute parsing, its probe registry, and its refusal of private and loopback targets. One test pins the demo project to 87% and exactly two unresolved critical checks, so the seed cannot drift without failing the suite.

Architecture

src/
├── components/
│   ├── ui/          Vendored shadcn/ui primitives (button, dialog, sheet, select, …)
│   ├── layout/      App chrome: sidebar, headers, logo, theme toggle, nav config
│   └── common/      Cross-feature pieces: empty states, coming-soon, badges
├── features/
│   ├── checklist/   The checklist itself: readiness, category cards, table, detail panel
│   ├── projects/    The projects section, and its create/settings/delete dialogs
│   ├── templates/   The templates section: list, preview, save and share
│   ├── reports/     Portfolio comparison, per-project report and the readiness trend
│   ├── settings/    Preferences and the local-data import/export tools
│   └── export/      Wiring the Markdown report to a browser download
├── data/            The 42 default checks, the platform-specific extras, the built-in
│                    templates, and the demo project seed
├── hooks/           useMediaQuery, useTheme, useFormatDate, useDebouncedCallback
├── lib/             Pure domain logic: scoring, categories, filtering, markdown, templates,
│                    history, backup serialisation, dates
├── store/           Zustand store, selectors and the validating localStorage adapter
└── types/           Zod schemas; every TypeScript type is inferred from one

verifier/            The optional local companion process
├── bin.ts           CLI: verify once, or serve the daemon
├── server.ts        Loopback HTTP daemon: CORS allowlist, token auth
├── safety.ts        Refuses private, loopback and link-local targets
├── run.ts           Fetches the page once, then runs every probe against it
└── probes/          One module per area: transport, headers, tls, dns, seo, assets,
                     analytics, exposure

The layering is deliberate:

  • types/ holds Zod schemas, and the TypeScript types are z.infer of those schemas — so the runtime validation at the storage boundary and the compile-time types can never disagree.
  • lib/ is pure functions over those types. calcReadiness, calcCategoryProgress, filterItems and buildMarkdown take data and return data, which is why they are cheap to test and why the tests run in milliseconds without a DOM.
  • store/ is the only place that mutates state or touches localStorage. The side effect of actually downloading a file lives in lib/download.ts, kept separate from the pure buildMarkdown that produces its contents.
  • features/ and components/ render that state. Presentation metadata — labels, icons, badge tints — lives once in lib/constants.ts rather than being spread across components.

Two conventions worth knowing:

  • ChecklistView is mounted with key={project.id}, so switching project resets filters and the selected check without a synchronising effect.
  • Dialog forms are mounted with their dialog, which resets their fields on open — again, no effect.

Roadmap

  • A scheduled mode for the verifier, so monitoring does not depend on remembering to press Verify.
  • Verifying automatically on open, rather than only when Verify is pressed.
  • Alerting on a regression, via a webhook or mail from the verifier.
  • Per-page probes rather than homepage-only, driven by the sitemap.
  • Deep links per project and check (React Router), so a check can be shared as a URL.
  • Bulk status actions and keyboard shortcuts for working through a long list quickly.
  • PDF export alongside Markdown, and a printable client report.
  • Editing a template's checks directly, rather than only capturing them from a project.
  • Reordering checks, and grouping them into phases within a category.

Contributing

Bug reports and pull requests are welcome. CONTRIBUTING.md covers the setup, the layout of the code, and the two rules that matter when adding a probe: never guess, and check your findings against a real site before trusting them.

Security issues should not go in a public issue — see SECURITY.md.

License

MIT © 2026 Florian Behrend

About

Pre-launch checklist tool for web developers, freelancers and agencies. Runs entirely in your browser.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages