Run the collector
The collector is a single Fastify process that ingests events and serves the query API. You run it
straight from npm — there is nothing to clone. The OSS default store is DuckDB: one
.duckdb file holds both events and metadata, so the collector self-hosts in one process with no
external database service.
OSS quickstart (no Docker, from npm)
Section titled “OSS quickstart (no Docker, from npm)”The scaffolder generates a ready-to-run, Docker-free self-host folder — a strong secret, a local config, a tiny runner, and a client snippet for your engine:
npm create uptimizr@latestFollow the prompts, then start it:
cd <your-folder>npm start # runs `uptimizr serve` under the hoodThe prompts also offer two optional extras so you can go from a bare collector to the full suite and test everything in one go:
- Dashboard — adds
@uptimizr/dashboardand annpm run dashboardscript (analytics UI onhttp://localhost:3000). - Demo — writes a self-contained Babylon scene + tiny static server and an
npm run demoscript (http://localhost:5173) that generates events end-to-end.
Skip the prompts with flags — --full (collector + dashboard + demo), --dashboard, --demo,
or --minimal (collector only):
npm create uptimizr@latest my-analytics -- --fullWith the full suite, run the three processes together and watch events flow from the demo through the collector into the dashboard:
npm start # collector — ingestion + query APInpm run demo # demo scene — paste the projectId, then interactnpm run dashboard # dashboard — point it at the collector with your API keyUse the uptimizr CLI shipped with @uptimizr/collector-server directly:
-
Initialise. Generates a
VISITOR_HASH_SECRET, creates the DuckDB store, mints a first project + API key, and writes a local.env. The project id, endpoint, and key are printed once — copy the key into your app config.Terminal window npx -p @uptimizr/collector-server uptimizr init -
Serve. Runs the ingestion + query API (migrations run automatically). Defaults to
COLLECTOR_STORE=duckdbon port4318.Terminal window npx -p @uptimizr/collector-server uptimizr serve -
Send events. Point your connector’s
endpointat the collector — e.g.http://localhost:4318— then query them back via the HTTP API.trackScene(scene, {projectId: "<printed-project-id>",endpoint: "http://localhost:4318",});
Need more projects/keys later? npx -p @uptimizr/collector-server uptimizr new-project "<name>".
Inspect & back up
Section titled “Inspect & back up”-
Inspect the store directly with the DuckDB CLI (
DUCKDB_PATHdefaults to./data/uptimizr.duckdb):Terminal window duckdb ./data/uptimizr.duckdb "SELECT event_type, count(*) FROM events GROUP BY 1" -
Back up = copy the
.duckdbfile. Reset = delete it and re-runuptimizr init.
Serve the dashboard too
Section titled “Serve the dashboard too”The collector can optionally serve the dashboard static assets at /, so a single process exposes
the ingestion API, query API, UI, and the DuckDB file. See Serve the
dashboard for the all-in-one and standalone options.
Scale path: ClickHouse
Section titled “Scale path: ClickHouse”When you outgrow DuckDB’s single-writer model — concurrent collector instances, high-volume ingestion, or large historical ranges — switch the store to ClickHouse without changing any application code or queries:
export COLLECTOR_STORE=clickhouseexport CLICKHOUSE_URL=http://localhost:8123export CLICKHOUSE_DATABASE=uptimizrexport CLICKHOUSE_USER=defaultexport CLICKHOUSE_PASSWORD=npx -p @uptimizr/collector-server uptimizr serveThis is a single-tenant ClickHouse store: events and metadata (projects, API keys, scene representations) live in one ClickHouse database, so there is no separate metadata service to run. The collector creates the database and tables on first boot. Every aggregation is authored once against the dialect-agnostic query layer, so the full analytics surface — heatmaps, sessions, performance percentiles, mesh dwell, daily rollups — returns identical results to DuckDB (verified by a cross-engine parity suite).
Choose ClickHouse when you need:
- Concurrent writers / horizontal scale — multiple collector instances against one store.
- High-volume ingestion and large time-range queries.
- A shared analytics database your team already operates.
Keep DuckDB (the default) for single-instance self-hosting with no service to run. Spin up a
local ClickHouse with the monorepo’s infra/docker (pnpm stack:up); see
Contributing.
Hosted / managed ClickHouse
Section titled “Hosted / managed ClickHouse”A managed ClickHouse (ClickHouse Cloud, Aiven, or your own TLS-terminated server) works the same
way — point CLICKHOUSE_URL at the HTTPS endpoint and pass the credentials. The client infers
TLS from the https:// scheme, so no extra configuration is needed for publicly-trusted
certificates:
export COLLECTOR_STORE=clickhouseexport CLICKHOUSE_URL=https://your-instance.clickhouse.cloud:8443export CLICKHOUSE_USER=defaultexport CLICKHOUSE_PASSWORD="$YOUR_PASSWORD"export CLICKHOUSE_DATABASE=uptimizrThe collector creates the CLICKHOUSE_DATABASE on first boot, so the connecting user needs the
CREATE DATABASE privilege (the default ClickHouse Cloud user has it) — or pre-create the database
and grant the user access to it. Custom CA bundles and mutual-TLS client certificates are not
currently exposed through env vars.
Configuration
Section titled “Configuration”Key environment variables (the CLI writes a starter .env; see the repo’s .env.example for the
full list):
| Variable | Purpose |
|---|---|
COLLECTOR_STORE | duckdb (default), clickhouse (scale tier), or memory (dev/E2E). |
DUCKDB_PATH | Path to the DuckDB file (default ./data/uptimizr.duckdb). |
CLICKHOUSE_URL | ClickHouse HTTP endpoint when COLLECTOR_STORE=clickhouse (default http://localhost:8123). |
CLICKHOUSE_DATABASE | ClickHouse database name (default uptimizr; created on first boot). |
CLICKHOUSE_USER / CLICKHOUSE_PASSWORD | ClickHouse credentials (default default / empty). |
COLLECTOR_PORT | Port the collector listens on (default 4318). |
VISITOR_HASH_SECRET | Secret for the daily-rotating, server-side visitor hash. |
COLLECTOR_CORS_ORIGINS | Allowed browser origins for ingestion/query (comma-separated). |
ENABLE_RAW_SESSION_RETENTION | Opt-in raw per-session event retention, required for replay. |
See Privacy & configuration for the privacy-relevant settings.