Velvet monitors websites and HTTP endpoints from GitHub Actions, records incidents and planned maintenance in GitHub Issues, and publishes a themeable status page through GitHub Pages. A public website needs only a name and URL.
- Direct IPv4
GETandHEADchecks from GitHub-hosted runners. - Five-minute status checks and separate six-hour response-time samples.
- Automatic incident creation after confirmed failures and automatic recovery.
- Planned maintenance that remains visible as a neutral history event.
- Up to 365 days of availability, response-time, incident, and maintenance data.
- Four system themes, detailed visual configuration, service icons, analytics, SEO output, custom domains, and selectable history ranges.
- A static GitHub Pages site that keeps working independently of the optional browser setup service.
GitHub is part of the platform. Every installation uses GitHub Actions for scheduling, GitHub Issues for incidents and maintenance, a dedicated Git branch for generated data, and GitHub Pages for the public site.
velvet.ymldefines the repository, page, services, and optional advanced checks.- The native Velvet monitor checks every configured endpoint over IPv4. The status workflow runs every five minutes; the response workflow runs four times per day.
- Successful runs publish one validated snapshot to the dedicated
velvet-databranch. The monitor never rewrites the default branch. - The Pages workflow builds the site, social card, and SEO files from that snapshot.
- The browser validates
status.json,response-times.json, andincidents.jsonbefore rendering them. Endpoint URLs and secrets never enter these public documents.
Invalid configuration, an unavailable configured secret, unsafe request setup, invalid stored data, or a GitHub write conflict leaves the last valid public snapshot untouched.
Open setup.velvet.li. The onboarding asks for the repository and page name, services, an optional custom domain, and one of the four system themes. After GitHub approval it creates the repository, enables Pages, starts monitoring, and waits for the first deployment.
The setup service is used only while installing. The generated repository and status page do not depend on it afterward.
The Velvet template is the direct template path and requires no local build:
- Choose Use this template, then create a repository.
- Edit
velvet.yml: replace the repository identity, set the public page name, and list the services. - Enable Issues under Settings > General > Features.
- Set Settings > Pages > Source to GitHub Actions.
- Commit the configuration. The first status run creates
velvet-data, then the Pages workflow publishes the site.
Both setup paths create the same repository structure and use the same validated configuration contract.
This is a complete one-service velvet.yml:
schemaVersion: 1
repository:
owner: your-username
name: your-status-repo
statusPage:
name: Example Status
services:
- name: Website
url: https://example.comThe default check sends GET, follows up to five redirects, waits at most ten
seconds, and considers only a final HTTP 200 healthy. Velvet ignores the
response body unless an explicit JSON assertion is configured.
services:
- name: API
checks:
- name: Application health
url: https://api.example.com/health
expectedStatusCodes: [200]
jsonAssertions:
- path: /status
equals: okJSON assertions use RFC 6901 JSON Pointers and compare the selected value with
one configured string, number, boolean, or null. They are for dedicated
health endpoints, not a requirement for normal websites.
See CONFIGURATION.md for every service, page, theme, incident, retention, permission, secret, recovery, and custom-domain option.
- Each check gets one initial request and at most one immediate retry.
- Two consecutive failed measurements confirm an outage by default. Two consecutive successful measurements confirm recovery.
- A pending failure or recovery appears as degraded. Invalid configuration or an internal error does not count as endpoint downtime.
- Status runs update availability and incidents. Response-only runs add samples without changing the confirmed service state.
- Planned maintenance never changes measured availability. It is displayed as a neutral event and retained in history.
- The default retention period is 365 days, which is also the maximum. Closed GitHub Issues are never deleted.
The monitor uses the repository-scoped GITHUB_TOKEN. Public checks need no
user-managed secret. A private endpoint may reference one repository secret by
environment-variable name; only that named secret is mapped into the monitor
workflow, and its value never belongs in velvet.yml.
Velvet v2 performs direct IPv4 checks from GitHub-hosted runners and has no remote probe dependency. IPv6 monitoring is deferred until GitHub-hosted runners provide documented native IPv6 connectivity. A configured service is therefore monitored over IPv4 only.
The monitor owns exactly these generated files on velvet-data:
.velvet/monitor-state.jsonvelvet-data/v1/status.jsonvelvet-data/v1/response-times.jsonvelvet-data/v1/incidents.json
Every successful run commits a complete validated snapshot. The default branch,
velvet.yml, workflows, and all other user-controlled files remain separate.
Rerun the failed workflow after correcting configuration, permissions, secrets,
or a temporary GitHub failure. There is no need to assemble or repair a partial
snapshot manually.
The Configurator edits the same velvet.yml format and previews the real status
page. Its current local distribution opens and saves YAML only on the computer:
./config start
./config stop
./config version
./config helpIt is available at http://127.0.0.1:2342 while running. Template updates from
the Configurator are planned separately and do not change the v2 monitoring
contract documented here.
Velvet v1.8 used Upptime as its temporary monitor and could route IPv6 checks through Globalping. Velvet v2 replaces both with the native IPv4 monitor.
Use vum for a non-destructive conversion. It runs
as a dry run by default, pins the source revision, validates the complete
result, and reports anything that cannot be migrated safely:
vum --repository owner/status
vum --repository owner/status --write --destination ./velvet-migrationResolve every open legacy incident before writing the migration bundle. Review the generated provenance report, preserve applicable data-license notices, and switch the repository to the native workflows only after the imported status, history, incidents, maintenance, and custom-domain settings match the report. Unsupported IPv6 and Globalping checks are listed in the report and are not silently converted into IPv4 checks.
For rollback, keep the pre-migration commit or tag and the previous deployment until the native status, response, incident, maintenance, and Pages workflows are verified. If cutover fails, disable the native schedules and revert the reviewed cutover commit as one unit. Do not run both monitor stacks against the same repository. Generated data and historical Issues remain recoverable from Git history; source license notices must not be deleted.
The compatibility packages remain in this repository solely for migration and provenance. They are not part of a new Velvet installation.
Velvet pins Bun 1.3.14 as its package manager and runtime.
| Environment | Supported path |
|---|---|
| Local macOS | Bun 1.3.14 on Apple Silicon or Intel |
| Linux CI | oven-sh/setup-bun@v2 reading the root packageManager pin |
| Playwright | Chromium installed through bunx --bun playwright |
| Composite Actions | oven-sh/setup-bun@v2 with Bun 1.3.14 pinned explicitly |
bun install --frozen-lockfile
bun run lint
bun run typecheck
bun run test
bun run buildSee CHANGELOG.md for release notes, RELEASING.md for the release process, and LICENSING.md for source-data and third-party license boundaries.
Velvet is published under the MIT license.