---
title: How publishing and the site fleet work
description: Three independently-deployed layers — the platform, the publishing hub, and a fleet of static Hugo sites — and the identity discipline that keeps published URLs stable.
locale: en
version: 0.2.0
canonical: https://enterium-developer-docs.pages.dev/developers/how-it-works/publishing-and-the-fleet/
---

> Documentation index: https://enterium-developer-docs.pages.dev/developers/llms.txt — every page of this portal has a Markdown twin at <route>.md; the frozen API contract is at https://enterium-developer-docs.pages.dev/developers/api/openapi.json.

**The problem:** one platform publishes to many sites, each with its own
brand, domain and theme. Coupling the content engine to site rendering
makes every theme change a platform deploy and every platform bug a fleet
outage. The design answer is three layers that deploy independently.

## Layer 1 — the three-layer topology

```mermaid
flowchart TB
    P[Platform<br/>generates + gates articles] -- publish payload --> HUB[Publishing hub<br/>separate microservice:<br/>instance registry · renderers · builders]
    HUB -- render to Hugo content --> T[Per-brand site templates<br/>shared theme + brand overrides]
    T -- build + deploy --> FLEET[Fleet of static sites<br/>served by nginx]
    FLEET -- verified live URL --> P
```

The **hub** is a vendored microservice with its own instance registry:
per-site records carrying template, status, deploy target and public URL.
The registry — not the platform database — is the hub's source of truth
for *where* each brand lives. The platform hands the hub a finished
article; everything from "markdown file in the right folder" to "site
rebuilt and rsynced" is the hub's business.

## Layer 2 — the publish flow, end to end

```mermaid
sequenceDiagram
    participant P as Platform
    participant H as Hub API
    participant A as Hugo adapter
    participant B as Builder
    participant S as Site host
    P->>H: publish-live (article payload)
    H->>A: upsert by source_url<br/>(article registry — republish ≠ duplicate)
    A->>B: build site (hugo --minify)
    B->>S: deploy (rsync to web root)
    P->>S: fetch the live URL
    S-->>P: 200 → publication counts
```

Two details carry the reliability:

- **Upsert by source URL.** The hub keeps its own article registry keyed
  by the source URL, so republishing an improved version replaces the
  page instead of minting a duplicate.
- **Slug identity lives on the platform side.** The published-URL registry
  keys identity as *(instance, normalized source URL)* — deliberately not
  the article's internal id, which changes on regeneration. A regenerated
  article **reuses its frozen slug**; a brand-new source mints one. This
  is what protects accumulated SEO equity from being reshuffled by
  routine regeneration.

## Layer 3 — brand configuration is code, not server state

Branding (title, logo, colors, taxonomies, the author roster) lives in
**git templates** per brand over a shared theme. A hand-edit on the web
host survives only until the next build — by design: the template is the
single source of truth, and every deploy reasserts it. New sites start as
**staged port-instances** (reachable, no domain) and convert to production
domains in a short, reversible procedure (DNS → vhost → registry URL →
platform record).

## Layer 4 — deploying the layers themselves

Each layer ships on its own cadence, with its own invariants:

- **Platform** — a four-phase deploy script: preflight (refuses while
  runs are active; snapshots the secret surface), code swap with a
  timestamped backup, container rebuild, postflight (health-wait +
  re-hash of the secret surface — an unexpected diff aborts). Database
  migrations apply automatically at container boot.
- **Hub** — rebuilt from its repo; a template change redeploys per
  instance without touching the platform.
- **This documentation** — built statically, shipped as an immutable
  release directory with a symlink flip; rollback is flipping the symlink
  back.

## Trade-offs

Three layers mean three registries of truth (platform DB, hub instance
registry, git templates) — and the operational cost is keeping their
pointers aligned; misaligned registry state has produced "instance not
found" incidents. The verified-live-URL rule also means publishing is only
as done as the slowest site build — a queue at the hub delays proof, not
just delivery. Both costs are accepted in exchange for fleet-wide brand
changes that never require touching the content engine.

## See it in two minutes

Any published article row carries its live URL; fetch it — that URL
responding is the platform's own definition of "published". The
`instances` API domain lists the fleet the hub serves.
