Skip to content

Repo tour

The four live repos, what each one holds, and where to knock first.

Updated View as Markdown

Four live repos, plus one retired. The split is by audience, not technology: curate-tenant is everything a tenant touches, and everything else is ours.

Published content was originally going to sit with the platform app, on that same reasoning. It ended up in its own repo for two reasons: content contributors — writers, vendors authoring guides — would otherwise hold write access to the super-admin app’s code, and the content stack is a separate toolchain on its own cadence.

Repo Holds Deploys to
curate-server Go API + background worker (one image), all Terraform, the engineering docs AWS ECS, ap-east-2
curate-tenant Consumer SPA, tenant-admin SPA, and the tenant edge Worker Cloudflare Workers
curate-platform Platform super-admin SPA and its edge Worker Cloudflare Workers
curate-content Marketing site, public guides, and this handbook Cloudflare Workers
curate-documentation Retired — UAT-era artifacts and the pre-migration doc site

curate-server — the command centre

The backend, but also the coordination point for everything else: it holds the only Terraform root and every document that describes more than one repo. When you need to know how the system behaves, this is where the answer lives.

Two binaries share one image and the same internal packages — the API server and a background worker. Postgres, S3, KMS, and Resend hang off them. Its docs/ folder is the source of record described below.

curate-tenant — everything a tenant hostname serves

One origin per tenant, one Worker serving all of it:

Path App Users
/ apps/consumer families and visitors
/admin apps/admin operator staff
/api/* proxied to the backend
  • apps/
    • consumer/ family-facing SPA — react-router, Tailwind 4
    • admin/ tenant-admin SPA, mounted under /admin
    • emails/ React Email templates — isolated, hands off to the backend
  • packages/
    • api/ typed API client — openapi-fetch + generated types
    • ui/ shared UI components
  • worker/ serves both SPAs and proxies /api
  • .gitlab-ci.yml quality gates only — deploys run on Workers Builds

Two invariants live here and are easy to break by accident:

  • Same-origin /api everywhere. Never introduce an absolute API host.
  • Admin is mounted at /admin, which means three things must agree: the Vite base, the router basename, and the Worker’s /admin mount.

curate-platform — the surfaces we operate

The super-admin SPA (tenant onboarding, admin assignment) and nothing else. Its packages/api and packages/ui are deliberate copies of curate-tenant’s — duplicated rather than published to a registry, which is overhead the team size does not justify while the platform app changes rarely. Revisit if the copies ever drift painfully.

curate-content — published content, no application

Two standalone Astro projects, each its own deploy:

  • sites/
    • external/ → curate.memorial
      • src/pages/ marketing pages
      • src/content/docs/ public role guides — zh-TW default, en prefixed
    • internal/ → internal.curate.memorial — Access-gated (this site)
      • src/content/docs/ this handbook
  • .docs-synced the curate-server commit this site last absorbed

The directories are named for audience and access — open versus gated — because that is the axis that actually separates them. Naming them marketing and docs would have described half of external each and gone stale immediately.

No auth, no API calls, nothing to break against a backend.

Where documentation lives

Authored in curate-server/docs/; this site follows. Engineering docs live in the repo where the work happens, so a doc can ride the same merge request as the change that invalidates it. That folder is a working set — files are deleted, merged, and summarized freely as understanding improves.

Pages here are authored views, organized for reading rather than mirrored from files, which is why no page tells you which source file it came from. The single coupling is a watermark, .docs-synced at the curate-content root, holding the curate-server commit this site last absorbed. From curate-server, make docs-drift prints how far behind the site is; an update pass ends with make docs-mark.

If a page here and current curate-server/docs disagree, the repo wins. See How this handbook works on the handbook home.

Every other repo keeps exactly one README.md as its front door. Anything bigger — or anything describing more than that repo — is authored in curate-server/docs.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close