2026-06-20 19:54:55 +10:00
2026-06-20 15:23:53 +10:00
2026-06-20 16:10:20 +10:00
2026-06-20 13:56:40 +10:00
2026-06-20 17:40:20 +10:00
2026-06-20 19:54:55 +10:00
2026-06-20 17:40:20 +10:00
2026-06-20 17:40:20 +10:00
2026-06-20 15:28:44 +10:00
2026-06-20 15:28:44 +10:00
2026-06-20 16:10:20 +10:00
2026-06-20 19:54:55 +10:00
2026-06-20 15:23:53 +10:00
2026-06-20 15:28:44 +10:00
2026-06-20 15:28:44 +10:00
2026-06-20 19:54:55 +10:00
2026-06-20 17:14:51 +10:00
2026-06-20 17:14:51 +10:00

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.

Sign in as admin locally

OAuth isn't available in local dev. Use the dev-only login instead:

  1. Start the worker: just dev
  2. Open http://localhost:8787/#/dev-login in your browser
  3. Enter your email (pre-filled with wahyd4@gmail.com) and click "Sign in as admin"

Or via CLI:

just dev-admin                    # creates admin user + session
just dev-admin other@example.com  # different email
just dev-logout                   # clears the session cookie

This endpoint is guarded: it only works when PUBLIC_HOST=localhost (or APP_BASE_URL contains localhost). In dev/prod deployments it returns 403. The dev login bypasses OAuth, finds-or-creates the user, promotes them to admin, and sets a heygo_session cookie — exactly what a real OAuth callback would do, minus the provider.

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 dev runs wrangler dev which 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/ (hence just build is required first).
  • The Worker API handles /api/* routes, public shortlink redirects, and private shortlink redirects.
  • Local wrangler.jsonc sets PUBLIC_HOST=localhost and PRIVATE_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 build type-checks the TypeScript project and builds the React SPA into dist/client for Workers Assets.
  • just test runs 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.cc zone 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/health returns JSON health status from the Worker.
  • Unknown /api/* routes return JSON 404 responses.
S
Description
No description provided
Readme
450 KiB
Languages
TypeScript 82.7%
CSS 10.3%
Python 4.5%
Just 1.1%
HCL 0.8%
Other 0.5%