- justfile with recipes for: build, dev, test, migrate, db helpers, deploy (dev/prod), terraform infra, and smoke test - README rewritten with quick start, command tables, and first-time local setup guide - All commands verified working locally
Heygo
Heygo is an independent Cloudflare React + Workers scaffold for a future shortlinks app.
This repository lives at /home/ai-bot/code/heygo and is intentionally separate from the old Linux/Django Links repository. The old Links repository under /home/ai-bot/code/links is read-only reference material only and must not be modified by this project.
Quick start (local)
Prerequisites: Node.js 18+, npm, and just installed.
git clone https://github.com/wahyd4/heygo.git
cd heygo
npm install
just build # build React SPA into dist/client
just migrate-local # apply D1 schema to local SQLite
just dev # start Worker on http://localhost:8787
Open http://localhost:8787 in your browser — the SPA and API are both served by the Worker.
Just commands
Run just (no args) to list all recipes. The most common ones:
| Command | What it does |
|---|---|
just build |
Type-check TypeScript + build React SPA into dist/client |
just dev |
Start Cloudflare Worker locally on port 8787 (API + SPA) |
just dev-ui |
Start Vite dev server on port 5173 with HMR (frontend only) |
just test |
Run the full Vitest suite (134 tests) |
just test-watch |
Run tests in watch mode |
just smoke |
Build, migrate, start worker, curl health — quick end-to-end check |
just typecheck |
Type-check without emitting |
Local D1 database helpers
| Command | What it does |
|---|---|
just migrate-local |
Apply D1 migrations to local SQLite |
just db-tables |
List all tables in local D1 |
just db-links |
List all links in local D1 |
just db-query "SELECT …" |
Run arbitrary SQL on local D1 |
just add-link <alias> <url> |
Insert a test public shortlink |
just rm-link <alias> |
Delete a link by alias |
just db-reset |
Drop local D1 and re-apply migrations |
First-time local setup
npm install
just build
just migrate-local
# optional: add a test shortlink to try it out
just add-link claude https://claude.ai
# start the Worker
just dev
Then test it:
curl -I http://localhost:8787/claude # → 302 redirect to claude.ai
curl http://localhost:8787/missing # → 404 HTML page
curl http://localhost:8787/api/health # → {"ok":true,"service":"heygo-worker"}
Open http://localhost:8787 for the SPA management UI.
How local dev works
just devrunswrangler devwhich starts a local Cloudflare Workers runtime (Miniflare) with a local D1 SQLite database at.wrangler/state/.- The Worker serves the built React SPA from
dist/client/(hencejust buildis required first). - The Worker API handles
/api/*routes, public shortlink redirects, and private shortlink redirects. - Local
wrangler.jsoncsetsPUBLIC_HOST=localhostandPRIVATE_HOST=localhost, so both public and private routes resolve on the same port. This is fine for testing APIs, the SPA, and public redirects. Private shortlink auth flows are covered by unit tests (tests/private-redirect.test.ts). - To iterate on the React frontend with hot reload, use
just dev-ui(Vite on port 5173) in a separate terminal. Note: Vite and the Worker run on different ports, so/api/*calls from Vite won't reach the Worker unless you set up a proxy.
Verification
just build # tsc --noEmit && vite build
just test # vitest run
just buildtype-checks the TypeScript project and builds the React SPA intodist/clientfor Workers Assets.just testruns Vitest tests against the Worker API handler.
Deployment
Heygo ships as a single Cloudflare Worker fronted by two custom domains: a public shortlink host and a private shortlink host. There are two environments, each with its own D1 database, KV namespace, Worker, and domains.
| Environment | Public host | Private host | Worker | D1 database |
|---|---|---|---|---|
| dev | dev.heygo.cc |
my.dev.heygo.cc |
heygo-dev |
heygo-shortlinks-dev |
| prod | heygo.cc |
my.heygo.cc |
heygo |
heygo-shortlinks |
The Worker reads PUBLIC_HOST, PRIVATE_HOST, APP_BASE_URL, and
COOKIE_DOMAIN from env vars (set in each wrangler config), so the same code
serves every environment without hardcoded hostnames.
Prerequisites
- A Cloudflare account with the
heygo.cczone added. - A Cloudflare API token with D1, Workers KV, Workers Scripts, and Workers Routes permissions.
- Terraform >= 1.5 installed.
1. Provision infrastructure with Terraform
The terraform/ directory provisions the D1 database, KV namespace, and both
Worker custom domains. See terraform/README.md for full details.
export CLOUDFLARE_API_TOKEN=*** # fill account_id + zone_ids in tfvars first
just infra-init
just infra-plan-dev # review, then:
just infra-apply-dev
just infra-plan-prod # review, then:
just infra-apply-prod
2. Copy Terraform outputs into Wrangler configs
After just infra-apply-dev, read the created resource IDs:
just infra-output dev
Paste the printed d1_database_id into wrangler.dev.jsonc
(d1_databases[].database_id) and kv_namespace_id into
wrangler.dev.jsonc (kv_namespaces[].id). Repeat for prod outputs into
wrangler.prod.jsonc. The placeholder 00000000-... IDs are there until you
fill them in.
3. Apply D1 migrations to remote
just migrate-dev
just migrate-prod
4. Deploy the Worker
just deploy-dev # builds + deploys to dev.heygo.cc + my.dev.heygo.cc
just deploy-prod # builds + deploys to heygo.cc + my.heygo.cc
Dev environment
The dev environment uses dev.heygo.cc (public) and my.dev.heygo.cc (private),
both under the .heygo.cc cookie domain. Session cookies set by the app UI on
dev.heygo.cc are automatically visible to my.dev.heygo.cc, so private
shortlink auth works out of the box — no extra configuration needed.
Prod works the same way: heygo.cc and my.heygo.cc share .heygo.cc.
All deployment commands
| Command | What it does |
|---|---|
just infra-init |
terraform init |
just infra-plan-dev |
Review infra changes for dev |
just infra-apply-dev |
Apply infra for dev |
just infra-plan-prod |
Review infra changes for prod |
just infra-apply-prod |
Apply infra for prod |
just infra-output <dev|prod> |
Show Terraform outputs (D1 ID, KV ID) |
just migrate-dev |
Apply D1 migrations to remote dev database |
just migrate-prod |
Apply D1 migrations to remote prod database |
just deploy-dev |
Build + deploy Worker to dev |
just deploy-prod |
Build + deploy Worker to prod |
Current API skeleton
GET /api/healthreturns JSON health status from the Worker.- Unknown
/api/*routes return JSON404responses.