Document Structure
SECTION 11 — NEWSLETTER JSON SCHEMA (COMPLETE)
11.1 Full Document JSON Structure
This is the canonical data structure produced by the Lexical.dev editor DOM export after transformation. The backend reads this JSON to drive all downstream processes (PDF, PPTX, Mindmap, Compilation aggregation).Production Note: The/* */comments throughout this schema are JSON5-compatible. Strip them using thestrip-json-commentsnpm package or a JSON5 parser before feeding into any standard JSON parser in production.
11.2 Schema Notes for Developer
- The
doc-idformat is:NL-YYYYMMDD-\{4-digit sequence\}for Newsletters. Adjust prefix for other types:CM-for Compilation,MG-for Magazine,MM-for Mindmap. total-pages-generatedandbillable-page-countare set by the backend after WeasyPrint completes PDF generation. These values must not be set before that point.org_idmust be present on every document record. It is the primary tenant isolation key for all queries.editor_idis denormalised for convenience in Editor queue queries but is not the authoritative isolation boundary.image-failuresarray is populated server-side during image upload processing and surfaced to the Editor in the review queue UI.sla-pausedis set totrueby the backend when a WeasyPrint failure escalation occurs. The SLA deadline timers must respect this flag — do not auto-continue while this istrue.translation-disabled-foris an array of document type strings where translation has been disabled. Check this array before invoking the Google Translate API for a given operation.- All entities (news categories, news items, images) must include their
atomic_uidin the JSON schema. See Section 11A for UID format specification. atomic_uidvalues are always backend-generated — never set client-side. The backend checks theatomic_uid_logtable for collisions before assignment.atomic_uidvalues are immutable — once assigned they are never changed, even if the entity content is edited.thumbnailis an object\{ url, atomic_uid, crop \}, not a bare URL string.reference-imagesis an array of\{ url, atomic_uid, crop, origin \}objects, not a keyed map. Both fields may benullas described in the image configuration table in Section 10.3.cropisnullwhen the image has not been cropped. When cropped, it is\{ x, y, w, h, applied_at \}(pixels relative to the original Cloudinary asset). See §10.8 for non-destructive crop semantics. The crop is frozen at document lock (is-locked = true) and the reset action becomes unavailable.- The
atomic_uidfor each image entity is also injected into Cloudinary MIME-level metadata (IPTC/XMP) and into thedata-uidattribute of the corresponding HTML element during WeasyPrint generation. See Sections 11A.5 and 11A.6. Briefschema change (v5):Briefis now a Lexical serialised JSON tree, no longer a plain string. Image nodes appear inline at the paste position. Each inline image node carriesatomic_uidandupload_state(pending|complete|failed). Thereference-imagesarray is derived metadata, built backend-side by walking each Brief tree in document order. Renderers (WeasyPrint, PptxGenJS client-side, HTML export) walk the Brief tree directly and preserve inline order.- Q&A
qanode is optional. When absent, the document has no associated Q&A. When present, each item carriessource_atomic_uidslinking back to the news item(s) used as input — required for aggregation Q&A merging in Compilations / Magazines. See §10.10 and §13.6.