- Node.js 22+
- npm
- A Cloudflare account (for production deployment)
- Wrangler CLI (included via dev dependencies)
# 1. Install dependencies
npm install
# 2. Create local secrets
cp .dev.vars.example .dev.varsEdit .dev.vars:
JWT_SECRET=a-random-secret-at-least-32-chars-long
ALLOW_REGISTRATION=true# 3. Apply database migrations locally
npm run db:migrate:local
# 4. Start the dev server
npm run devOpen http://localhost:5173 — both the React frontend and the Hono API run on the same port via Vite's Cloudflare integration.
Vite dev server (port 5173)
├── React frontend (HMR via Vite)
└── Cloudflare Worker (via wrangler --remote)
└── Miniflare D1 (SQLite, local file)
The Worker and D1 run locally through Miniflare — no Cloudflare account needed for development.
Registration is gated by ALLOW_REGISTRATION. Set it to true in .dev.vars, register one account, then set it back to false.
# Authenticate wrangler with your Cloudflare account
npx wrangler login
# Verify
npx wrangler whoaminpx wrangler d1 create tracker-dbCopy the returned database_id and paste it into wrangler.jsonc:
npm run db:migrate:remotenpx wrangler secret put JWT_SECRET
# Generate one with: openssl rand -base64 32
# At least 32 characters — this is ENFORCED, not advisory. A missing or short
# secret makes the app refuse to issue sessions (it would otherwise sign them
# with an empty key, which anyone could forge).
npx wrangler secret put ALLOW_REGISTRATION
# Set to "true" initially, then "false" after creating your accountnpm run deployYour app is now live at https://tracker.<your-subdomain>.workers.dev.
npx wrangler deploy --routes "https://tracker.yourdomain.com/*"Or add the domain in the Cloudflare dashboard under Workers & Pages > tracker > Triggers.
The repo includes a GitHub Actions workflow (.github/workflows/ci.yml) that on every push/PR runs:
- TypeScript type checking (
npm run typecheck) - Integration tests (
npm test) - Production build (
npm run build)
On pushes to main it also deploys the Worker to Cloudflare automatically (PRs only build+test — they never ship). The deploy job needs these repository secrets:
| Secret | Value |
|---|---|
CLOUDFLARE_API_TOKEN |
Cloudflare API token with Workers & D1 permissions |
CLOUDFLARE_ACCOUNT_ID |
Your Cloudflare account ID |
Migrations are still manual. The deploy job ships the Worker only — it does not run
db:migrate:remote. Apply migrations deliberately after reading the deploy prerequisites (a missingJWT_SECRETor thetoken_versionmigration makes everything 500), then the next push tomaindeploys the code.
To run your own instance:
- Fork the repo
- Clone your fork
- Follow steps 1–5 above
The project is MIT-licensed — no attribution required, but appreciated.