React Router
Create a React Router status page with Heyo Status or add a live page and API to an existing app.
Creating a new React Router status page? The Framework Mode starter gives you a live page, API, theme, database and local scheduler. Choose a deployment target for production cron setup. If status belongs inside an existing app, follow the manual route and page steps below.
Create a project
Pass react-router to select the framework without a prompt. Omit flags to
choose a deployment, database and theme interactively.
If you skipped dependency installation in the creator, install the project's
dependencies before starting it. Replace the example monitors in
heyo-status.config.ts. For SQLite or Vercel/PostgreSQL, bun dev starts
the local scheduler; bun run check runs one check without a global CLI
install. Cloudflare/D1 uses Worker cron triggers instead and has no check
script. For direct shell commands, see the CLI guide.
Add status to an existing app
The route and page below work in an existing React Router Framework Mode app. They still need persistent storage and a production scheduler; the starter includes the platform-specific deployment setup.
1. Install and configure
Install the package in the app's root directory:
You only need a global CLI install
if you want to type heyo-status … directly in your shell.
At the project root, add a config (use a persistent SQLite disk when self-hosting; Cloudflare uses D1, Vercel PostgreSQL):
To test a monitor before scheduling it, install the global CLI and run
heyo-status check run from the project root. It reads the config and database
without a running React Router server (and requires Bun 1.4.3+). For
Cloudflare/D1, use Worker cron triggers instead; a local shell has no D1
binding.
2. Add the API and page routes
The API route must match the default basePath, /api/heyo-status.
The loader serves GET; action serves POST, PATCH, PUT and DELETE. Keep
the basePath and route path in sync if you change either.
3. Render the current snapshot
Load the stylesheet once in src/root.tsx:
Fetch the snapshot in the server loader rather than the component, so the rendered page always reflects the most recent checks. A dynamic import keeps SQLite out of the browser bundle.
Pass basePath, branding, colors, mode, metrics and subscriber settings
from the config when using those features. For the persisted light/dark toggle,
include statusThemeBootstrapScript in the document head; the generated
src/root.tsx already does so.
4. Schedule checks
The API route does not schedule work. Run statusPage.cron.runChecks,
summarize and cleanup on their configured schedules. Use Cloudflare
triggers, Vercel
Cron, or one scheduler on your
server.