# Civic Ledger content and data model

This Site is generated from `content/site-data.json`. That source file is the editorial record for the launch publication. `scripts/build_site.py` validates its relationships and emits the public HTML, JSON, CSV, RSS and sitemap files under `dist/`.

## Content types

| Type | Stable ID prefix | Public route | Main relationships |
| --- | --- | --- | --- |
| Article | `CL-ARTICLE-` | `/news/{slug}/` | Documents, organisations, municipalities, projects |
| Tender | `CL-TENDER-` | `/tenders/{slug}/` | Institution, municipality, projects, source documents, articles |
| Project | `CL-PROJ-` | `/projects/{slug}/` | Owner, implementing agencies, contractors, tenders, documents, articles |
| Organisation | `CL-ORG-` | `/companies/{slug}/` | Tenders, projects, documents, articles |
| Municipality | `CL-MUNI-` | `/municipalities/{slug}/` | Organisation, tenders, projects, documents, articles |
| Document / source | `CL-DOC-` | `/documents/{id}/` | Institution, municipality, project, tender, article |
| Person | `CL-PERSON-` | Reserved until verified records are supplied | Organisation and source records |
| Sector | `CL-SECTOR-` | Data export | Related records |
| Location | `CL-LOC-` | Data export | Related records |

Every public record has a stable identifier and the fields `created`, `lastUpdated`, `lastVerified`, `source`, `editor`, `status` and `publicationStatus`. Record-specific relations use stable IDs. Dates and monetary values remain in source form where possible; an unknown or undisclosed value is not inferred.

## Status vocabularies

Tender status: `Open`, `Closing Soon`, `Closed`, `Evaluation`, `Awarded`, `Cancelled`, `Extended` or `Withdrawn`.

Project status: `Proposed`, `Planning`, `Procurement`, `Awarded`, `Under Construction`, `Operational`, `Delayed`, `Suspended`, `Cancelled` or `Completed`.

Status history is represented as dated timeline events. New events are appended; prior events are retained. A tender may move to `Awarded` only when an official award record supports the change.

## Provenance and publication

Articles, tenders and projects link to one or more source-document IDs. A document record links directly to the issuing institution’s original source. `lastVerified` records the most recent editorial check, not the source’s publication date. Unknown publication dates remain unstated.

Only published records are emitted to `dist/`. The `draftExamples` collection is editorial-only and is deliberately excluded from site pages, search indexes, RSS and machine-readable exports. Do not place private notes, unpublished identities or internal deliberations in a public record field.

## Build and validation

Run `python3 scripts/build_site.py` from the repository root. The builder stops on duplicate IDs, unresolved relationship IDs, unsupported tender states, tenders without source records, articles without documents or document records without source URLs. Public tables, entity pages and search records are rebuilt from the same source data so linked pages update together.

The launch build is static and server-rendered: core articles, tenders, projects and entity records are readable in HTML without JavaScript. Search and table filters use a small client-side script over the published static index.
