Skip to content
FM Journal
ArticlePublished: Updated 2 min readSample

Reading shared configuration at build time

Why every app in the ecosystem fetches one registry before it builds, and why a failed fetch should fail the build instead of falling back.

Illustration: a document at the centre of three orbits, with dashed lines reaching out to small bodies.

Every project in the ecosystem needs a few shared facts: where Support lives, what the Gateway URL is, which projects are public. Hardcoding them in each repository works until the first rename. After that, every copy drifts on its own schedule.

One registry, many readers

The registry is a plain JSON file generated from small source files and validated against JSON Schemas. Apps don't install it as a package; they fetch the published file before dev, build, typecheck and test, and keep only the fields they use.

  • The sync step validates what it reads, not the whole registry, and ignores fields it doesn't know.
  • It writes a minimal projection to a git-ignored file, so the full registry never reaches a visitor's browser.
  • It resolves deployment URLs the same way everywhere: an explicit url as written, otherwise the subdomain plus the primary domain.

No stale fallback

The tempting design is a checked-in snapshot that takes over when the fetch fails. It keeps the build green and quietly ships yesterday's facts. A failed sync here removes the generated file and fails the command, so a broken registry stops a deploy instead of reaching visitors.

scripts/sync-ecosystem.mjsCode: js
const response = await fetch(CONFIG_URL, { cache: "no-store" });if (!response.ok) throw new Error(`Config fetch failed: HTTP ${response.status}`);const projection = projectEcosystem(await response.json());
Diagram: source files are validated into a published ecosystem.json; a sync step before every build turns it into a small projection, and a failed fetch or validation stops the build.
The registry's path into one app. The dashed line is the failure path: it ends the build.
ApproachWhen the fetch failsWhat visitors see
Checked-in snapshotThe build passesPossibly outdated facts
No fallback (this journal)The build stopsThe last working deployment
Two ways to handle an unavailable registry.
Code: bash
curl -s https://raw.githubusercontent.com/Fikrimarzuki/ecosystem-config/main/dist/ecosystem.json | node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>console.log(Object.keys(JSON.parse(s).projects).length))'

What it costs

Builds need the network, and a registry outage blocks deploys. For a small ecosystem that is the right trade: the failure is loud, short and obvious, and the alternative fails silently.

ArticlePublished: 1 min readSample

Typed local content before a CMS

Starting a journal with typed data files and a small repository interface, so a database or CMS can arrive later without rewriting the pages.