---
title: "Repo tour"
description: "The four live repos, what each one holds, and where to knock first."
---

> Documentation Index
> Fetch the complete documentation index at: https://internal.curate.memorial/llms.txt
> Use this file to discover all available pages before exploring further.

# Repo tour

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`](https://gitlab.com/revere-curate/curate-server) | Go API + background worker (one image), all Terraform, the engineering docs | AWS ECS, `ap-east-2` |
| [`curate-tenant`](https://gitlab.com/revere-curate/curate-tenant) | Consumer SPA, tenant-admin SPA, and the tenant edge Worker | Cloudflare Workers |
| [`curate-platform`](https://gitlab.com/revere-curate/curate-platform) | Platform super-admin SPA and its edge Worker | Cloudflare Workers |
| [`curate-content`](https://gitlab.com/revere-curate/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`.

Source: https://internal.curate.memorial/architecture/repos/index.mdx
