Skip to main content

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 the strip-json-comments npm package or a JSON5 parser before feeding into any standard JSON parser in production.

11.2 Schema Notes for Developer

  • The doc-id format is: NL-YYYYMMDD-\{4-digit sequence\} for Newsletters. Adjust prefix for other types: CM- for Compilation, MG- for Magazine, MM- for Mindmap.
  • total-pages-generated and billable-page-count are set by the backend after WeasyPrint completes PDF generation. These values must not be set before that point.
  • org_id must be present on every document record. It is the primary tenant isolation key for all queries. editor_id is denormalised for convenience in Editor queue queries but is not the authoritative isolation boundary.
  • image-failures array is populated server-side during image upload processing and surfaced to the Editor in the review queue UI.
  • sla-paused is set to true by the backend when a WeasyPrint failure escalation occurs. The SLA deadline timers must respect this flag — do not auto-continue while this is true.
  • translation-disabled-for is 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_uid in the JSON schema. See Section 11A for UID format specification.
  • atomic_uid values are always backend-generated — never set client-side. The backend checks the atomic_uid_log table for collisions before assignment.
  • atomic_uid values are immutable — once assigned they are never changed, even if the entity content is edited.
  • thumbnail is an object \{ url, atomic_uid, crop \}, not a bare URL string. reference-images is an array of \{ url, atomic_uid, crop, origin \} objects, not a keyed map. Both fields may be null as described in the image configuration table in Section 10.3.
  • crop is null when 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_uid for each image entity is also injected into Cloudinary MIME-level metadata (IPTC/XMP) and into the data-uid attribute of the corresponding HTML element during WeasyPrint generation. See Sections 11A.5 and 11A.6.
  • Brief schema change (v5): Brief is now a Lexical serialised JSON tree, no longer a plain string. Image nodes appear inline at the paste position. Each inline image node carries atomic_uid and upload_state (pending | complete | failed). The reference-images array 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 qa node is optional. When absent, the document has no associated Q&A. When present, each item carries source_atomic_uids linking back to the news item(s) used as input — required for aggregation Q&A merging in Compilations / Magazines. See §10.10 and §13.6.