About this site
How it's built
One repository produces two distinct outputs: a static public site and a private layer that is only served after the gate has checked who is asking. Research projects publish into the private layer on their own schedule.
The hub
The hub is a static Astro site. One build produces the public pages that anyone can read; a second build produces the private pages. The private build is uploaded to a content bucket rather than to the public origin, so a private route has no public object to fetch.
Satellites and pulled sources
Research projects do not have to live in this repository. A satellite repository publishes a versioned manifest and its rendered pages into the content bucket. A pulled source does the same for material that originates elsewhere. In both cases the manifest is validated before anything is uploaded, so a contract break fails the publish instead of producing a half-live project.
The gate
The gate is a small Cloud Run service. It reads the Firebase session, loads the access policy from Firestore, and decides whether the requested object may be served. The same styled not-found response is returned for a missing private page and a forbidden one, so the response cannot be used to discover which private paths exist.
The gate also owns the owner-only Admin area. Admin is never rendered for a non-owner; the route is server-enforced, and every write is audited.
Guardrails
The public build is checked for the titles, summaries, slugs, routes and payload paths of every private item. A publish allowlist limits what may reach the public origin, and a private-link check makes sure every link in the private build resolves under the gate's base. The leak check has its own self-test: a deliberately injected leak must make it fail.