Documentation

From workflow run
to status light.

Install the GitHub App, build a URL, and place a live GitHub Actions indicator anywhere that accepts an image. No personal access token and no request-time GitHub API polling.

01 / GETTING STARTED

Publish your first status light

Status Lights is a free GitHub App for public repositories. GitHub sends signed workflow and job events to the service, which stores only the latest state needed to return a compact SVG.

Public repositories only. Status-light URLs are public and unauthenticated. Do not install the public service on a private repository.

Before you start

  • A public repository that uses GitHub Actions.
  • Permission to install a GitHub App for the repository owner or organization.
  • The workflow filename, such as pages.yml or ci.yaml.

1 Install the GitHub App

Open the Status Lights GitHub App, choose Install, and select only the public repositories whose status you want to publish.

Repository access Level Used for
Actions Read-only Receive workflow and job status events
Metadata Read-only Identify the repository and default branch; granted automatically
Everything else No access No code, workflow, settings, or repository write permission

Status Lights cannot push code, change workflows, merge pull requests, or modify repository settings. It never asks for a personal access token.

2 Run the workflow once

Run the workflow on the repository's default branch after installing the App. GitHub does not replay older events during installation, so a new workflow or job light is gray and reports unknown until its first new event arrives.

3 Build the URL

The easiest route is the interactive builder. Enter the owner, repository, workflow filename, and optionally a job display name.

Workflow light
https://g.statuslights.dev/github/{owner}/{repository}/{workflow}.svg
Job light
https://g.statuslights.dev/github/{owner}/{repository}/{workflow}/job/{job-name}.svg

For a job, use the display name shown on the Actions page or the workflow's name: value—not the key beneath jobs:. Job names are case-sensitive. URL-encode spaces and other path characters.

Example job URL
https://g.statuslights.dev/github/KingBain/status-lights/pages.yml/job/Validate%20site.svg

4 Embed the light

Use the generated SVG URL anywhere a remote image is supported.

Markdown image
![Pages workflow status](https://g.statuslights.dev/github/KingBain/status-lights/pages.yml.svg)
Linked to the workflow
[![Pages workflow status](https://g.statuslights.dev/github/KingBain/status-lights/pages.yml.svg)](https://github.com/KingBain/status-lights/actions/workflows/pages.yml)

The same URL works in Markdown dashboards, HTML pages, documentation sites, and issue descriptions.

Change or remove access

Open your GitHub account or organization settings, go to Applications → Installed GitHub Apps, and choose Configure beside Status Lights. You can change the selected repositories or uninstall the App. Removed repositories return the unknown state.

02 / REFERENCE

URL format and options

Supported routes
/github/{owner}/{repository}/{workflow}.svg
/github/{owner}/{repository}/{workflow}/{option}/{value}...svg
/github/{owner}/{repository}/{workflow}/job/{job-name}.svg
/github/{owner}/{repository}/{workflow}/job/{job-name}/{option}/{value}...svg

The optional job/{job-name} selector must immediately follow the workflow. Add appearance options after the workflow or job selector as path pairs.

Repository names beginning with a period. Prefix the repository segment with @ so front-end web servers do not treat it as a hidden path. For example, use @.github for a repository named .github. The interactive builder applies this escape automatically.
Option Purpose Example
sizeLight height in pixelssize/40
widthFixed width in pixelswidth/160
fontSans, mono, or serif font stackfont/mono
font-sizeText size in pixelsfont-size/16
radiusCorner radius in pixelsradius/6
textFixed text; may include {status}text/Build%3A%20%7Bstatus%7D
success-colorSuccessful state coloursuccess-color/1a7f37
failure-colorFailed state colourfailure-color/cf222e
running-colorIn-progress state colourrunning-color/bf8700
unknown-colorUnknown state colourunknown-color/6e7781
Prefer the builder for customized lights. It handles option order and URL encoding and lets you preview all four states before copying the live URL.

03 / TROUBLESHOOTING

Common problems

The light is gray or unknown
  1. Confirm that the App is installed for the repository.
  2. Run the workflow on the default branch after installation.
  3. Use the workflow filename, including .yml or .yaml.
  4. For a job URL, use the exact, case-sensitive display name.
The light shows an older result

Browsers and image proxies can cache an SVG briefly. Confirm that the latest run was on the default branch, then allow the cache to refresh.

The URL returns an error image

Use the interactive builder to validate the path and options. If the problem remains, open an issue in the Status Lights repository.

04 / SELF-HOSTING

Operate your own instance

The backend is a dependency-free PHP 8.3+ service. It accepts signed GitHub App webhooks, stores the latest default-branch state locally, and serves the SVG routes without calling GitHub on each image request.

Register the App

Under Settings → Developer settings → GitHub Apps, configure:

  • Your website as the Homepage URL.
  • https://your-host.example/webhooks/github as the Webhook URL.
  • A secret containing at least 32 random bytes (64 hexadecimal characters).
  • Actions: read-only; Metadata read-only is automatic.
  • Workflow run and Workflow job repository events.
  • Installation lifecycle events so selected repositories can be tracked.

Do not grant write permissions. A callback URL is not needed.

Configure the host

Required environment variable
STATUS_LIGHTS_GITHUB_WEBHOOK_SECRET=<same secret configured in GitHub>
Environment variable Default Purpose
STATUS_LIGHTS_GITHUB_WEBHOOK_SECRETUnsetVerify GitHub webhook signatures
STATUS_LIGHTS_APP_STORE_DIRapp-dataWritable persistent state directory
STATUS_LIGHTS_MAX_WEBHOOK_BYTES1048576Maximum accepted webhook body size
STATUS_LIGHTS_RUN_RETENTION_DAYS7Workflow run-link retention
STATUS_LIGHTS_DELIVERY_RETENTION_DAYS7Replay-record retention
STATUS_LIGHTS_RUN_PRUNE_INTERVAL_SECONDS86400Minimum time between pruning scans
STATUS_LIGHTS_HTTP_CACHE_TTL60Browser and image-proxy cache duration

Route /health, /webhooks/github, and /github/... to generator/app.php. Keep the writable state directory and all source files outside direct HTTP access, use HTTPS, and rate-limit public SVG routes before PHP.

Verify and maintain

Health check
https://your-host.example/health

Confirm that app_store_writable and webhook_secret_configured are both true. Schedule the pruning command at least daily:

Prune transient records
STATUS_LIGHTS_APP_STORE_DIR=/path/to/app-data \
  php scripts/prune-app-runs.php

The complete runtime and deployment reference remains beside the backend source in generator/README.md.

05 / SECURITY

Security model

  • Webhook bodies are bounded before parsing and verified with HMAC-SHA256.
  • Duplicate GitHub delivery IDs are claimed atomically and ignored safely.
  • Public route identifiers and runtime record keys are strictly allow-listed.
  • Runtime state lives outside direct HTTP access.
  • The App uses read-only Actions and Metadata permissions—never repository write access.
  • Public SVG traffic should be rate-limited at the web server, edge, or WAF.