This is the abridged developer documentation for StatusBeam # StatusBeam > An open-source, CDN-native status page generator — a modern take on upptime. Renders every byte at the edge from its own store, so your page never hits third-party rate limits. ## Why StatusBeam [Section titled “Why StatusBeam”](#why-statusbeam) No client-side rate limits Upptime calls the GitHub API from the visitor’s browser (60 req/h/IP), so popular pages break with a “rate limit exceeded” screen. StatusBeam renders every byte at the edge from its own store — the browser never talks to a third-party API. Reliable scheduling Upptime rides best-effort GitHub Actions cron (a “every 5 min” job can slip to 15–60 min). StatusBeam uses Cloudflare Cron Triggers, which fire on time. A store that scales Instead of walking git commit history through a rate-limited API, StatusBeam uses Cloudflare D1 + KV, purpose-built for time-series reads. A current frontend Upptime’s page is built on end-of-life Svelte 3 + Sapper. StatusBeam is Astro + shadcn/ui, shipping \~0 JS for everything but the interactive charts. ## AI-friendly by default [Section titled “AI-friendly by default”](#ai-friendly-by-default) Every page is available as clean Markdown at `.md.txt`, the whole site is published as [`/llms.txt`](/llms.txt) and [`/llms-full.txt`](/llms-full.txt), and each page has a **Copy Markdown** button plus **Open in ChatGPT / Claude** actions. See [AI & LLM endpoints](/reference/ai-and-llms/). # Introduction > What StatusBeam is, how the three-layer architecture works, and why it runs entirely on Cloudflare. **StatusBeam** monitors your services, records their uptime as durable time-series data, and publishes a fast, good-looking status page to the edge. It keeps the parts of [upptime](https://github.com/upptime/upptime) people love — config-as-YAML, zero servers to babysit, badges, a public JSON API — while fixing upptime’s biggest structural weaknesses. ## Architecture [Section titled “Architecture”](#architecture) StatusBeam is deliberately split into three independent layers. Each can be understood, deployed, and replaced on its own. 1. **Check layer — Cloudflare Cron Worker.** Cron Triggers ping every configured service on schedule, derive `up` / `degraded` / `down` from the status code and response time, write time-series to D1 and the current snapshot to KV, and on a status change enqueue a notification and purge the page/badge cache by tag. 2. **Notify layer — Queue consumer.** Fans out status changes to Slack, webhooks, and (soon) email and RSS/Atom. 3. **Display layer — Astro site on Cloudflare.** Renders the page at the edge from D1/KV — the browser never calls a third-party API, so there are no client rate limits. Fronted by Workers Cache; the check layer purges by tag on change, so updates are near-instant rather than TTL-bound. Because the check and display layers live on Cloudflare — **not** on the infrastructure being monitored — your status page stays up even when your own services are down. That resilience is the whole point of a status page. ## Next steps [Section titled “Next steps”](#next-steps) * [Quick Start](/getting-started/quick-start/) — get a page running locally. * [Configuration](/guides/configuration/) — the single `status.config.yml` file. * [Deploy to Cloudflare](/guides/deployment/) — provision D1/KV and ship it. # Quick Start > Clone StatusBeam, install the toolchain, and run the status page locally. This gets a StatusBeam page running on your machine. To publish it to the edge, follow [Deploy to Cloudflare](/guides/deployment/) afterwards. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * [mise](https://mise.jdx.dev/) (manages the pinned Node + Bun toolchain) * A Cloudflare account (only needed when you deploy) ## Steps [Section titled “Steps”](#steps) 1. **Clone the repository.** ```bash git clone https://github.com/pleaseai/statusbeam.git cd statusbeam ``` 2. **Install the toolchain and dependencies.** ```bash mise trust && mise install bun install ``` 3. **Create your config.** Copy the example and edit the services you want to monitor (see [Configuration](/guides/configuration/)). ```bash cp status.config.example.yml status.config.yml ``` 4. **Run the dev servers.** ```bash bun run dev ``` This starts the Turborepo `dev` pipeline — the Astro status page and the check Worker in watch mode. ## What’s next [Section titled “What’s next”](#whats-next) Your page renders from local data. When you’re ready to publish, provision D1 + KV and deploy the Worker and site to Cloudflare — see [Deploy to Cloudflare](/guides/deployment/). # Configuration > The single status.config.yml file — services, check types, notifications, and theme. StatusBeam is configured by a **single YAML file**, `status.config.yml`. At deploy time you upload it to the Worker’s KV `config` key; that is the only thing you configure. ## Example [Section titled “Example”](#example) ```yaml name: Acme Status sites: - name: Website url: https://example.com check: http # http | tcp | ssl | statuspage | incidentio expectedStatusCodes: [200] maxResponseTime: 2000 # ms; slower responses are marked "degraded" - name: API url: https://api.example.com/health check: http # Read status straight from an Atlassian Statuspage. `url` is the page's base # URL; StatusBeam appends /api/v2/summary.json automatically. - name: Claude url: https://status.claude.com check: statuspage # Add `component` to track one service on the page instead of the whole page. - name: Claude API url: https://status.claude.com check: statuspage component: Claude API (api.anthropic.com) # incident.io status pages serve the same Statuspage-compatible summary.json, # so `incidentio` reads them identically — use whichever names your vendor. - name: OpenAI url: https://status.openai.com check: incidentio notifications: slack: webhookUrl: https://hooks.slack.com/services/T00000000/B00000000/XXXX webhooks: - url: https://example.com/status-hook theme: logoUrl: /logo.svg darkMode: true locale: en # en | zh | ja | ko — fallback UI language ``` ## Fields [Section titled “Fields”](#fields) ### `sites[]` [Section titled “sites\[\]”](#sites) | Field | Type | Notes | | --------------------- | --------- | ------------------------------------------------------------------------------------ | | `name` | string | Display name for the service. | | `url` | string | Endpoint to check (or status-page base URL for `statuspage`/`incidentio`). | | `check` | enum | `http` \| `tcp` \| `ssl` \| `statuspage` \| `incidentio`. | | `expectedStatusCodes` | number\[] | Codes treated as healthy (HTTP checks). | | `maxResponseTime` | number | Milliseconds; slower responses are marked **degraded**. | | `component` | string | For `statuspage`/`incidentio`: track one component by name (case-insensitive) or id. | ### `notifications` [Section titled “notifications”](#notifications) * `slack.webhookUrl` — incoming webhook for a Slack channel. * `webhooks[].url` — arbitrary HTTP endpoints that receive status-change events. Caution Keep real webhook URLs out of the committed example — they are secrets. Put them only in the private config you upload to KV. ### `theme` [Section titled “theme”](#theme) * `logoUrl` — logo shown on the page. * `darkMode` — enable the dark theme. * `locale` — fallback UI language (`en` | `zh` | `ja` | `ko`), used only when a visitor’s browser language isn’t one of the supported locales. # Deploy to Cloudflare > Provision D1 + KV, wire the resource IDs, and deploy the Worker and status page to Cloudflare. StatusBeam runs entirely on Cloudflare: a Cron Worker for checks and an Astro site for the page, backed by D1 (time-series) and KV (current snapshot). The repo ships a scripted path and a manual one — the outline below mirrors the repo’s `DEPLOYMENT.md`, which is the authoritative reference. ## Steps [Section titled “Steps”](#steps) 1. **Provision D1 + KV.** Create the D1 database and KV namespace in your Cloudflare account. 2. **Wire the resource IDs** into each app’s `wrangler.jsonc` (the `database_id` and KV `id` placeholders). 3. **Write your config** — see [Configuration](/guides/configuration/). 4. **Apply the D1 schema** to create the time-series and incident tables. 5. **Upload the config to KV** under the `config` key. 6. **Set secrets** for optional integrations (Slack/webhook URLs live inside the KV `config`, cache-purge credentials as Worker secrets). 7. **Deploy.** ```bash bun run deploy ``` This deploys the check Worker and the web app to Cloudflare. 8. **Verify** the first cron run has populated D1/KV and the page renders. ## Deploying these docs [Section titled “Deploying these docs”](#deploying-these-docs) This documentation site is a separate app (`apps/docs`). It is a fully static Starlight build deployed to a **Cloudflare Pages** project (`statusbeam-docs`) — no D1/KV, no server adapter: ```bash bun run --filter '@statusbeam/docs' deploy ``` The site is reached at **`docs.statusbeam.dev`** (a custom domain on the Pages project), while its bundled assets (`_astro/*` JS, CSS, fonts) load from the project’s own **`statusbeam-docs.pages.dev`** origin. That split is configured via Astro’s [`build.assetsPrefix`](https://docs.astro.build/en/reference/configuration-reference/#buildassetsprefix) in `astro.config.ts`; the cross-origin assets are made CORS-readable by `public/_headers`. # AI & LLM endpoints > How this documentation is made consumable by LLMs and AI agents — llms.txt, raw Markdown endpoints, and per-page AI actions. This site is built to be consumed by LLMs and coding agents, not just humans. Three mechanisms are always available. ## `/llms.txt`, `/llms-small.txt`, and `/llms-full.txt` [Section titled “/llms.txt, /llms-small.txt, and /llms-full.txt”](#llmstxt-llms-smalltxt-and-llms-fulltxt) Following the [llms.txt standard](https://llmstxt.org/), the site publishes: * **[`/llms.txt`](/llms.txt)** — a structured overview: title, description, and a curated list of links to every page. * **[`/llms-small.txt`](/llms-small.txt)** — a compact variant of the overview, trimmed for smaller context windows. * **[`/llms-full.txt`](/llms-full.txt)** — the entire documentation concatenated into one Markdown file, ready to paste into a model’s context. Point an assistant at any of these URLs to give it the whole product’s docs at once. *Generated at build time by [`starlight-llms-txt`](https://github.com/delucis/starlight-llms-txt).* ## Raw Markdown endpoints (`.md.txt`) [Section titled “Raw Markdown endpoints (.md.txt)”](#raw-markdown-endpoints-mdtxt) Every page is also served as clean, navigation-free Markdown by appending `.md.txt` to its path. For example, this page is available at: ```plaintext /reference/ai-and-llms.md.txt ``` Custom components (asides, cards, tabs) are converted to plain Markdown, so an agent or crawler gets structured content without HTML, CSS, or scripts. *Provided by [`starlight-md-txt`](https://www.npmjs.com/package/starlight-md-txt).* ## Per-page AI actions [Section titled “Per-page AI actions”](#per-page-ai-actions) Every page has, under its title: * **Copy Markdown** — copies the page’s raw Markdown to your clipboard. * **Open in …** — a dropdown that opens the current page in **ChatGPT**, **Claude**, or **Cursor** with a prompt referencing the page URL. *Provided by [`starlight-page-actions`](https://github.com/dlcastillop/starlight-page-actions).*