Skip to main content
ADR-008accepted

Static JSON over CMS for Decision Records

Context

Architecture Decision Records are a new content type being added to the portfolio. The existing content model uses a MongoDB-backed API for all data. Adding ADRs to the API would follow the established pattern: create a new collection, add CRUD endpoints, fetch at build time. However, ADRs have fundamentally different characteristics than other content types. They are authored infrequently (one every few months), require careful version control (decisions should be traceable to commits), and their content is inherently static — a recorded decision doesn't change after acceptance. Storing them in the database would add operational overhead (new endpoints, new admin UI forms, new backup considerations) for content that benefits more from version control than from a CMS workflow.

Decision

Store ADRs in a local JSON file (data/adrs.json) imported directly at build time, bypassing the API entirely. The JSON file lives in the repository alongside the code, tracked by Git with full commit history. getStaticProps imports the JSON directly — no HTTP fetch, no network dependency, no API availability requirement at build time. The data model includes all fields needed for rendering (adrNumber, title, status, date, context, decision, consequences, technicalContext, friendlyUrl, relatedAdrs) in a single flat array.

Consequences

Positive: Zero network dependency for ADR pages at build time — the data is local, so builds never fail due to API unavailability. Full Git history on ADR content enables blame, diff, and audit trail on decision records. Pull requests that modify ADRs show content changes in the same diff as code changes, enabling holistic review. No new API endpoints, no new database collection, no new admin forms — the entire feature is self-contained in the frontend repository. Build time for ADR pages is effectively zero (local file read vs HTTP fetch). Negative: Content editing requires a code commit and deploy rather than an admin UI interaction. No API endpoint means AI agents and other consumers cannot query ADRs through the existing API — they must consume the rendered pages or llms.txt. The data format is coupled to the frontend's rendering expectations with no abstraction layer. These trade-offs are deliberate: ADRs are engineering artifacts that belong in version control, not in a content management system.

Calibrated Uncertainty

Predictions at Decision Time

Expected the local JSON approach to eliminate build-time API failures for ADR pages. Predicted the data would remain small enough (<50KB) that file I/O cost is negligible. Assumed infrequent editing (one ADR per month at most) would make the commit-to-deploy workflow acceptable. Predicted the Git history on ADR content would provide meaningful audit trail value.

Measured Outcomes

Build reliability for ADR pages is 100% — zero dependency on network or API availability, exactly as predicted. The data file is currently at ~35KB (12 ADRs with calibration data), well within the <50KB prediction. Editing frequency has been higher than expected during the initial authoring phase (12 ADRs created in 2 days), but this is a burst pattern that will normalize. The Git history has already proven valuable: diff-reviewing calibration field additions shows exactly what metadata was added to each ADR and when. The unexpected outcome: the JSON file doubles as machine-readable documentation — other developers can read the raw data without needing the rendered UI.

Unknowns at Decision Time

Did not anticipate adding calibration fields to the ADR schema, which significantly increased the per-record size. The original estimate assumed ~1KB per ADR; with calibration data, each ADR is ~3KB. This doesn't affect performance but changes the maintenance experience — editing a 35KB JSON file is less ergonomic than editing a 12KB one. Also unknown: whether the ADR collection would remain small (12 records) or grow to a point where a flat JSON file becomes unwieldy. The current trajectory suggests 15-20 ADRs within a year, which is still manageable.

Reversibility Classification

Two-Way Door

Migrating ADRs to the MongoDB API requires: creating an ADRs collection, adding a CRUD endpoint, writing a one-time data migration script from JSON to MongoDB documents, and changing getStaticProps from a local import to an API fetch. The data model is already JSON — no transformation needed, just transport. Estimated effort: 3-4 hours. The reverse direction (API to local JSON) is equally simple: export the collection, save as file.

Strongest Counter-Argument

The MongoDB API is the established pattern for all other content types. Breaking that pattern for ADRs introduces inconsistency — a new developer would need to learn two data access patterns instead of one. Storing ADRs in the database would also enable future features: querying ADRs from the AI profile endpoint, full-text search across ADR content, and admin UI editing. The counter-counter: pattern consistency has value, but the Git version control benefit is a category-level advantage that the database model cannot replicate. ADRs are engineering decisions, not content — they belong in the code repository.

Technical Context

Stack
JSONGitNext.js getStaticPropsLocal import
Data Size
<20KB
Network Dependencies
0
Build Time Contribution
<1s
Constraints
  • Editing requires code commit
  • No API exposure for ADRs
  • Version controlled content

Related Decisions