LX Draft — Writing Documents with an AI Agent

Version 2026-05-29

How an AI agent should author .lx.md documents in markdown for LX Draft.

Click to copy the full guide as plain text, then paste it into your AI agent as a prompt. The agent will then know how to produce LX Draft documents.

What is an .lx.md file?

A .lx.md file is a UTF-8 text file with three parts:

  1. YAML frontmatter — metadata and document properties (between --- markers at the top)
  2. Markdown body — the actual content using standard Markdown plus a few extensions
  3. Optional document-assets and document-meta blocks — for embedded images and review data (you usually don't need these)

The simplest .lx.md is just markdown wrapped in frontmatter:

---
format: "lxd/1.0"
title: "My Document"
revision: "v0.1"
status: "draft"
---

# My Document

This is the body. Standard Markdown works fine.

The integrity hash — do NOT write it

LX Draft stores a self-excluding SHA-256 hash in frontmatter.integrity to detect later tampering (it underpins signature auto-clear-on-edit). As an agent, never write or guess the integrity field — omit it entirely. LX Draft computes and injects the correct hash automatically when the document is saved or edited in the app. A hash you invent would be wrong and flag the document as modified. (Unsigned drafts don't need a hash at all; it only matters once a human/Lexis signs the document.)

Standalone vs Lexis (context you should know)

LX Draft is used two ways, and it affects governance (not how you write content):

As an agent you write the same markdown either way. Do not set lexis_controlled yourself, and do not try to sign documents — placing a {signature:...} field is enough; the human or Lexis performs the signing.

Required frontmatter fields

You MUST include these:

format: "lxd/1.0"           # always this exact value
title: "Document Title"     # required
revision: "v0.1"            # use v0.1 for first draft
status: "draft"             # draft | review | approved | released | obsolete

Add these whenever you have the information:

short_title: "Short Name"   # for headers / breadcrumbs
document_number: "T-XXX-001" # if there's a doc numbering scheme
date_created: 2026-03-30    # YYYY-MM-DD
classification: "internal"  # public | internal | commercial-in-confidence | restricted
template: "standard"        # standard | proposal | test-report | datasheet | minutes | review
project: "Project Name"
prepared_for: "Client Name"
author: "Your Name"
font: "Poppins"             # default body font; use Poppins unless told otherwise
cover: true                 # render the LX-branded blue cover page in the PDF

The cover page

LX Draft can render a branded cover page at the front of the PDF — a full-bleed page with a dark background, a blue title block, the document number, and a footer with the LX logo and a metadata table (project, client, author, revision, date). It's gated behind a single frontmatter flag so plain memo-style documents don't get a heavy cover they don't want:

cover: true

The cover only renders in the PDF export (and the in-app Print Preview, which is a PDF rendered in an iframe). The editor canvas itself stays cover-less so you can edit body content without the cover taking up half the screen. If you don't set cover: at all, the cover is suppressed by default.

Fields the cover surfaces. Populate as many as you have; missing fields are skipped gracefully:

When to set cover: true. Use it for formal external deliverables — client proposals, design reports, test reports, formal specifications. Skip it (or set cover: false) for internal memos, meeting minutes, short notes, and anything that's going to be read on-screen rather than printed.

Templates and the cover. If the user has selected a template (e.g. template: "standard" or template: "proposal"), check that template's own frontmatter for cover: true. The shipped LX templates may already enable it — in which case the cover renders automatically without you having to add cover: true to your document. If the template hasn't enabled it but the document should have one, override by setting cover: true explicitly in your document's frontmatter.

Custom cover (cover_html). The built-in cover suits most documents, but you can replace it entirely with your own HTML by setting cover_html. When non-empty it replaces the built-in cover. Field codes (see below) resolve inside it; the HTML is sanitized (scripts/event-handlers stripped, styling + inline style kept). Leave it unset to use the built-in cover.

Headers and footers

Every page of the PDF (not the editor canvas, and not the cover page) can carry a running header and footer. There are two layers and they stack: small field-code text boxes in the margins, and optional full-bleed custom-HTML bands behind them.

header_enabled: true        # default true; false hides the header in the PDF
footer_enabled: true        # default true; false hides the footer
header_left: "{title}"      # field-code text, top-left
header_right: "{date:MMM YYYY}"
footer_left: "Page {page} of {pages}"
footer_center: "{revision}"
footer_right: "{document_number}"
footer_notice: ""           # small centred note under the footer

Defaults vs blank. An absent field falls back to a sensible default (title / date on top; page-of-pages / revision / doc-number on the bottom). A field set to an empty string (header_left: "") stays intentionally blank — use this to clear a default you don't want (e.g. when a custom band supplies the text).

On/off. header_enabled: false / footer_enabled: false omit that band from the PDF entirely (default on). Field values are preserved either way.

Custom HTML branding (header_html / footer_html)

To make a branded bar — like the LX blue gradient header — put HTML in header_html (or footer_html). It renders as a full-bleed band repeated on every content page (never on the cover). The field-code text layers on top of it, so live page numbers still work over a band. Recipe for an LX-blue header:

header_html: '<div style="height:16mm;background:linear-gradient(90deg,#2ba0e8,#4ab4f5);color:#fff;display:flex;align-items:center;justify-content:space-between;padding:0 20mm;box-sizing:border-box;font-weight:700;"><span>{title}</span><span style="font-weight:400;">{date:MMM YYYY}</span></div>'
header_left: ""             # clear default field text so it doesn't collide with the band
header_right: ""

Watermark

A diagonal watermark is driven by classification (there is no separate watermark field): when classification is commercial-in-confidence or restricted, the PDF paints that phrase diagonally across every page, sized to fit. (footer_notice is different — it's the small upright note under the footer.)

Field codes

Header/footer fields and custom-HTML bands support these placeholders, resolved at export:

Page breaks

Force a hard page break in the body with an HTML comment on its own line:

<!-- pagebreak -->

Use it to push a section onto a fresh page (e.g. before a major appendix). Don't overuse it — the exporter already paginates and keeps headings with their content, callouts whole, and table headers with their rows.

Standard Markdown features (just use them)

These work as you'd expect from any Markdown:

Watch the tilde and caret. Because ~text~ renders as subscript and ^text^ as superscript, do not type a bare ASCII ~ to mean "approximately" — a ~500 mAh and a later ~15 mAh will pair up and turn everything between them into subscript. Use the proper Unicode symbols instead (neither triggers sub/superscript):

Likewise avoid a stray ^ in prose (it starts superscript).

LX-specific extensions (use these for engineering docs)

Callout boxes

Use these for tips, warnings, important notes:

> [!NOTE]
> Informational note. Blue left border.

> [!TIP]
> Helpful tip. Green left border, "Tip:" prefix.

> [!IMPORTANT]
> Important caveat. Amber left border, "Important:" prefix.

> [!WARNING]
> Warning text. Red left border, "Warning:" prefix.

> [!STEP]
> Procedural step. Blue left border, no prefix.

Tables

Use GFM pipe tables for all tables, whether the data is a short inline grid, a BOM, a checklist, or a long list of requirements. Pipe-table cells are fully editable in place — clicking a cell selects text normally, and the table can be resized, sorted, and rearranged by the reviewer.

| Reference | Part Number      | Quantity | Manufacturer       |
| --------- | ---------------- | -------- | ------------------ |
| U1        | STM32F405RGT6    | 1        | STMicroelectronics |
| C1        | CL21B104KBCNNNC  | 10       | Samsung            |
| R1        | RC0805FR-07100KL | 4        | Yageo              |

Escape any literal | inside a cell as \|. Cells may contain inline markdown (**bold**, `code`, links, math) but not block content (lists, paragraphs).

Marking a table's semantic data-type (optional)

If a workflow connector or downstream tool needs to identify a table by what kind of data it carries (e.g. "the BOM in this doc"), place an optional <!-- table-type: X --> sentinel comment on the line immediately above the table:

<!-- table-type: bom -->
| Reference | Part Number      | Quantity |
| --------- | ---------------- | -------- |
| U1        | STM32F405RGT6    | 1        |

Common labels: bom, requirements, test-results, registers, checklist. The label is free-text; pick whatever fits. The sentinel is invisible in the rendered document and is preserved through editor round-trips, so a human reader never sees it but a workflow agent can find the right table by scanning for it.

Legacy CSV blocks (deprecated)

Earlier versions of LX Draft supported ```csv:label``` fenced blocks as a separate "rich CSV table" node. That format is now deprecated: it renders as a read-only grid in the editor (cells can't be clicked into), and inline commas inside cells silently split rows into extra columns — both serious authoring traps. Existing documents containing csv: blocks still open and edit cleanly (the editor converts them to native pipe tables on load), but agents should not write new csv: blocks. Always use a pipe table; if data-typing is needed, use the <!-- table-type: X --> sentinel above it.

Equations (LaTeX)

Inline math: $R = V / I$ where $V$ is voltage.

Block math:

$$
P_{total} = \sum_{i=1}^{n} V_i \cdot I_i
$$

Footnotes and endnotes

This statement needs a citation[^1].

This refers to an endnote[^note:pricing].

[^1]: Footnote text — typically appears at the bottom of the page.
[^note:pricing]: Endnote text — appears at the end of the document.

Cross-references and bookmarks

<!-- bookmark: thermal-section -->

See {ref:sec:introduction} for background.
Refer to {ref:bookmark:thermal-section|the thermal section} for details.

Document-property fields (live values from frontmatter)

You can embed a live reference to a frontmatter field in the body. It renders the current value of that field (and updates if the frontmatter changes), and resolves to the value in PDF/DOCX export. Use the {field:NAME} token:

Document number: {field:document_number}
Revision {field:revision} — prepared for {field:prepared_for}.

Valid field names: title, short_title, document_number, revision, author, status, classification, date_created, project, prepared_for.

In the editor, a human inserts these via the Insert Field toolbar button; as an agent, just write the {field:NAME} token in the markdown — it round-trips and resolves on export.

Signature fields

A signature field renders the signer's name (in a cursive font) once the document is signed, or a muted "Your signature here" placeholder when unsigned:

Signed: {signature:author}

Signing itself is a human/Lexis action (see "Standalone vs Lexis" above) — as an agent you place the {signature:...} token where the signature should appear; you do not sign the document.

Page breaks

If you need a hard page break in the printed output:

<!-- pagebreak -->

Multi-column sections

<!-- columns: 2 -->
Content here flows into two columns.
<!-- /columns -->

Text boxes (bordered content)

<!-- textbox -->
Content inside a bordered box.
<!-- /textbox -->

Images

For external images (URLs), use standard Markdown:

![Alt text describing the image](https://example.com/image.png)

For embedded images, use the asset reference syntax:

![Alt text](asset:my-image-id)

Then add the image to a document-assets block at the end of the file (see "Embedded images" below).

Size, alignment and crop are persisted as an HTML comment immediately after the image. You normally don't need to write these (the human adjusts images by dragging in the editor), but they round-trip and the exporter honours them:

![Alt text](asset:my-image-id)<!-- width=320 height=180 align=center crop=10,10,10,10 -->

Table of contents

Insert a self-updating TOC anywhere:

<!-- toc -->

The editor renders this as an actual TOC. In source form it stays as the directive.

Media attachments (preferred: deliver a bundle, don't base64 yourself)

Do not base64-encode media inside the .lx.md. LLM output is unreliable for large binary blobs — you will silently truncate, corrupt, or hit token limits. Instead, deliver two things:

  1. A clean .lx.md (or .md) file with asset:<id> references in the body.
  2. A .zip archive containing the actual media files, named to match those references.

LX Draft's import dialog has a "Document + Archive" tab that does the embedding for you — it reads the archive, matches each ref to a file, base64-encodes server/browser-side, and produces a self-contained .lx.md.

Reference syntax in the markdown

Strongly preferred — use bare asset:<id> references with no folder prefix:

![Tag at 10 o'clock](asset:photo-013435032)
![PCB Layout](asset:pcb-rev-b)

Relative paths (./diagrams/field-plot.png) are accepted as a fallback — LX Draft matches them by exact path then by basename — but they couple the document to the directory layout. Avoid them in agent output.

Absolute filesystem paths (C:\..., /home/...) can never resolve in a browser. Don't use them.

Folder structure

The folder can be flat or have subfolders — both work, because LX Draft matches by filename stem. Filename stems must be unique within the bundle when you use asset:<id> references.

my-report/                        ← name doesn't matter; user picks this folder
├── photo-013435032.jpg           ← matches asset:photo-013435032
├── photo-013449261.jpg           ← matches asset:photo-013449261
└── pcb-rev-b.png                 ← matches asset:pcb-rev-b

If you have many media files of different types, put them in subfolders for your own organisation — the matcher still works:

my-report/
├── photos/
│   ├── photo-013435032.jpg       ← still matches asset:photo-013435032
│   └── photo-013449261.jpg
└── diagrams/
    └── pcb-rev-b.png             ← still matches asset:pcb-rev-b

The asset:<id> reference does not include the subfolder.

Supported media types

Anything LX Draft can render or link: png, jpg/jpeg, gif, webp, svg, bmp, tiff, pdf, mp4, webm, mp3, wav, ogg. The MIME type is inferred from the extension.

Flowcharts and block diagrams — write Mermaid

For flowcharts, block diagrams, and sequence/state/ER diagrams, write a Mermaid diagram in a fenced code block. LX Draft renders it live in the editor and in the PDF export — you do not hand-draw the SVG. Tag the fence ```mermaid so it is recognised (a bare fence whose first line is a Mermaid keyword like flowchart is also auto-detected, but tag it to be safe):

```mermaid
flowchart TB
    A["<b>Shared core</b><br/>control board"] --> B["Path 1"]
    A --> C["Path 2"]
```

Inside node labels you may use <br/> for line breaks and <b>…</b> for bold (they render). Keep one diagram per fence, and write the fence as plain body text — do not wrap it in review/change markers. Mermaid is the best choice for structural diagrams; for schematic sketches or highly custom artwork, use an inline ```svg fence instead (below) — both render the same way and keep the document self-contained.

Mermaid is laid out automatically and can only be changed by editing its text — the human cannot hand-edit a Mermaid diagram graphically (there are no coordinates to drag; the layout engine derives positions from the relationships you describe, so a manual nudge has nowhere to be saved). So if a Mermaid diagram can't capture the detail or exact layout the user wants, or they are unhappy with how it came out and want to fine-tune it by hand, produce an ```svg version instead: an inline SVG fence renders the same way, but the human can open it in the in-app graphical editor (the Edit graphically button) and adjust shapes, arrows and text directly. In short — Mermaid for quick structural diagrams; escalate to an ```svg fence whenever the user needs precise, hand-tunable control.

Inline SVG — self-contained diagrams, no asset bundle

Like Mermaid, a ```svg fenced code block renders live in the editor and in the PDF export — the SVG source sits directly in the document body as plain text. This is the preferred way to hand-author a diagram: no base64, no document-assets block, no separate media bundle to deliver alongside the .lx.md. Use it for schematic sketches, custom layouts, or any vector artwork that doesn't fit Mermaid's flowchart/sequence grammar:

```svg
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="120" viewBox="0 0 300 120">
  <rect x="10" y="10" width="120" height="50" rx="6" fill="#eaf6fe" stroke="#2ba0e8"/>
  <text x="70" y="40" text-anchor="middle" font-family="Inter, sans-serif" font-size="14">Block A</text>
</svg>
```

The content must be a valid standalone <svg>…</svg> document (same explicit width/height rule as below). It is run through a strict sanitizer on render, so do not include <script>, event-handler attributes (onclick, onload, …), <foreignObject>, or external http(s):/javascript: URLs in href/xlink:href — all of these are stripped. Inline data:image/* URIs and local #id references (gradients, clip-paths, markers) are fine. Like a normal image, the rendered fence carries a size/alignment comment that round-trips, so the human can resize or realign it in the editor afterwards — and, unique to ```svg (not Mermaid), the human can click Edit graphically on the block to adjust the drawing by hand in the built-in editor.

Prefer ```mermaid or ```svg fences over the base64 document-assets approach below whenever the diagram is text-derivable or hand-authored — both travel inside the document as text, so the doc stays self-contained. Keep base64/asset embedding for genuinely binary raster media (photos, screenshots).

Engineering diagrams — prefer SVG over ASCII art

For block diagrams, schematic sketches, flowcharts, and similar figures where you want the SVG treated as an image object (draggable, resizable, croppable like a photo) rather than an inline fence, write the diagram as an SVG and embed it like any other image (![alt](asset:my-diagram) + matching my-diagram.svg in the media folder). SVG scales perfectly at any zoom, survives PDF and DOCX export, and remains editable. It is much better than ASCII art in a fenced code block, which depends on a monospace font being installed and renders inconsistently in different browsers and exports. For most diagrams, though, the inline ```svg fence above is simpler and keeps the document self-contained.

Critical: the <svg> root element MUST carry explicit width and height attributes. viewBox on its own is not enough — without intrinsic size, the image collapses to 0×0 in the editor and disappears visually even though it is technically embedded. Set them to the natural pixel dimensions of the diagram (the same numbers you use in viewBox):

<svg xmlns="http://www.w3.org/2000/svg"
     width="920" height="1120"
     viewBox="0 0 920 1120">
  ...
</svg>

Other SVG authoring tips:

Preserve the source the diagram was generated from

When a diagram is derived from a text source — typically an ASCII sketch handed to you, but also Mermaid, Graphviz DOT, or a brief prose description — include that source in the document so a future human or agent can read, copy, and refine it. Place an <!-- ascii-source: ... --> HTML comment immediately above the image's markdown reference:

<!-- ascii-source:
[100–240 V AC]
      │
[EMI Filter]  ← Common-mode choke + X/Y capacitors
      │
[Bridge Rectifier + Bulk Cap]
-->
![Power-flow block diagram](asset:power-flow)

The source is invisible in the rendered document, survives save/load round-trip, and is shown in the editor's Image Properties panel (right-hand sidebar) whenever the image is selected — so a human can read it, copy it, or paste an updated version that will then be used to regenerate the SVG. The label ascii-source is fixed; the content is free-form text. If your source contains a literal -->, the editor inserts an invisible zero-width space to break the closing sequence so the comment doesn't truncate.

What to deliver to the human

You'll get the cleanest result if you deliver:
  1. The .lx.md file (with asset: references, no document-assets block).
  2. A folder of media files matching those references.
The user uploads both via LX Draft's "Document + Archive" import tab — they can pick the folder directly (no zipping needed) or zip it first if their browser doesn't support folder upload.

You don't need to zip anything. Write the files into a folder; LX Draft reads only the files actually referenced by the document and ignores the rest.

If you absolutely cannot deliver media files (e.g. you only have URLs), use plain HTTPS image references. They'll work but won't be embedded — the document depends on the URL staying live.

Manual base64 embedding (only if you have no other option)

The format is documented for completeness. Avoid using it from an agent:

<!-- document-assets

- id: pcb-rev-b
  filename: pcb-layout-rev-b.png
  mime: image/png
  size: 145832
  data: iVBORw0KGgoAAAANSUhEUgAA[... full base64 string, no line breaks ...]

/document-assets -->

The data: field must be the complete base64 (no line breaks, no truncation). The size: field should match the original file's byte length.

Review markers (do NOT use unless instructed)

The <!--[c1]-->...<!--[/c1]--> and <!--{ch1:del}-->...<!--{/ch1}--> syntax is for review comments and tracked changes. Do not generate these manually. Use the API endpoints if you need to add review data programmatically.

Editing existing text in place

To change wording wherever it appears in the document — for example, rewording every mention of a fixed quantity into a range — work like a person using Find & Replace, do NOT write a summary of the places that need changing:

  1. (Optional) Call lxdraft_find_text with the phrase to see every hit and its surrounding context, so you know how many places there are.
  2. Call lxdraft_replace_text with find (the exact words you read) and replace (your new wording). With from omitted it changes the FIRST match from the top of the document, as a tracked change the user reviews.
  3. Read remaining_matches in the result. If it is greater than 0, call lxdraft_replace_text again with from set to the returned next_from, wording that replacement for its own context. Repeat.
  4. Stop when remaining_matches is 0.

Never append an appendix or list describing the changes to make — make each edit with lxdraft_replace_text.

How to use headings, paragraphs, and emphasis

Engineering documents are read for reference, not narrative. Structure beats prose. Use these tools deliberately:

Heading levels carry meaning

Don't skip levels. Going from ## straight to #### confuses readers and breaks the table of contents.

Don't use # (H1) inside the body — the document title is in the frontmatter and rendered as the cover. Body sections start at ##.

Paragraphs vs callouts

Don't overuse callouts. If every other paragraph is a callout, none of them stand out.

Emphasis

Lists

Tables

Use GFM pipe tables for every table — BOMs, checklists, requirements, test results, register maps, sign-off sheets, narrative grids. They're fully editable in place and serialize cleanly. If a downstream tool needs to identify a particular table by its data-type, prefix it with a <!-- table-type: X --> sentinel comment (see the Tables section above). Do not use the legacy ```csv:label``` fence in new documents — it's deprecated.

Document structure for engineering documents

A typical LX engineering document has this structure:

---
[frontmatter]
---

<!-- toc -->

## 1 Introduction

Brief overview of the document and project.

## 2 Scope

What this document covers.

## 3 [Main content section]

### 3.1 Subsection

Content here.

### 3.2 Another subsection

<!-- table-type: requirements -->
| ID      | Description                          | Criticality |
| ------- | ------------------------------------ | ----------- |
| REQ-001 | System must boot in under 5 seconds  | High        |
| REQ-002 | Battery life must exceed 8 hours     | High        |

## 4 [Another main section]

## Appendix

### A. Additional Information

Two ways to deliver a document to LX Draft

If you're an agent producing a document, you have two options:

Option 1: Hand the user a .md file

Just write standard markdown. The user clicks "Import Markdown" in LX Draft and uploads the file. LX Draft wraps it in default frontmatter automatically.

Option 2: Hand the user a complete .lx.md file

Write the full file with frontmatter. The user clicks "Import Markdown" → "Upload File" and selects the .lx.md. It imports as-is.

Common mistakes to avoid

Stuff agents have actually done that broke the import or rendering. Don't repeat these:

Validate your output before delivery

LX Draft has a public validation endpoint. Run your .lx.md through it before handing the document to the user — you'll catch malformed YAML, missing required fields, broken asset references, and the rest of the issues listed above.

From the command line (Node 18+, no npm install needed; the script lives in the LX Draft repo):

node scripts/lint-lxdoc.mjs path/to/your/doc.lx.md

It exits 0 on success and 1 on validation errors, so you can use it in scripts.

As an HTTP endpoint (for agents that have internet but not the LX Draft repo):

POST https://lxdraft.lx-cloud.com/api/validate-public
Content-Type: text/plain

<the entire .lx.md content as the request body>

Returns:

{
  "valid": true,
  "issues": [
    { "rule": "V003", "severity": "warning", "message": "...", "location": "..." }
  ]
}

valid: false means there is at least one error-severity issue. Fix all errors before delivery; warnings are advisory.

Validation rules to follow

Your output will be validated. To avoid rejection:

Quick checklist before delivering

← Back to the LX Draft user guide

# Agent Writing Guide for LX Draft Documents

This guide tells AI agents how to write `.lx.md` documents that LX Draft can render and edit. Give this guide to any agent that needs to produce engineering documents for the LX Design House team.

## What is an .lx.md file?

A `.lx.md` file is a UTF-8 text file with three parts:

1. **YAML frontmatter** — metadata and document properties (between `---` markers at the top)
2. **Markdown body** — the actual content using standard Markdown plus a few extensions
3. **Optional document-assets and document-meta blocks** — for embedded images and review data (you usually don't need these)

The simplest .lx.md is just markdown wrapped in frontmatter:

```
---
format: "lxd/1.0"
title: "My Document"
revision: "v0.1"
status: "draft"
---

# My Document

This is the body. Standard Markdown works fine.
```

## The integrity hash — do NOT write it

LX Draft stores a self-excluding SHA-256 hash in `frontmatter.integrity` to
detect later tampering (it underpins signature auto-clear-on-edit). **As an
agent, never write or guess the `integrity` field — omit it entirely.** LX Draft
computes and injects the correct hash automatically when the document is saved
or edited in the app. A hash you invent would be wrong and flag the document as
modified. (Unsigned drafts don't need a hash at all; it only matters once a
human/Lexis signs the document.)

## Standalone vs Lexis (context you should know)

LX Draft is used two ways, and it affects governance (not how you write content):

- **Standalone** — the document is a plain `.lx.md` file the user opens/saves on
  their own drive (or Google Drive). The user self-signs; revision history is a
  table they maintain.
- **Lexis-managed** — the document is a controlled project artifact. Lexis owns
  its lifecycle (releases, version history, signing). A controlled document
  carries `lexis_controlled: true` in its frontmatter.

As an agent you write the same markdown either way. Do **not** set
`lexis_controlled` yourself, and do **not** try to sign documents — placing a
`{signature:...}` field is enough; the human or Lexis performs the signing.

## Required frontmatter fields

You MUST include these:

```yaml
format: "lxd/1.0"           # always this exact value
title: "Document Title"     # required
revision: "v0.1"            # use v0.1 for first draft
status: "draft"             # draft | review | approved | released | obsolete
```

## Recommended frontmatter fields

Add these whenever you have the information:

```yaml
short_title: "Short Name"   # for headers / breadcrumbs
document_number: "T-XXX-001" # if there's a doc numbering scheme
date_created: 2026-03-30    # YYYY-MM-DD
classification: "internal"  # public | internal | commercial-in-confidence | restricted
template: "standard"        # standard | proposal | test-report | datasheet | minutes | review
project: "Project Name"
prepared_for: "Client Name"
author: "Your Name"
font: "Poppins"             # default body font; use Poppins unless told otherwise
cover: true                 # render the LX-branded blue cover page in the PDF
```

## The cover page

LX Draft can render a branded **cover page** at the front of the PDF — a full-bleed page with a dark background, a blue title block, the document number, and a footer with the LX logo and a metadata table (project, client, author, revision, date). It's gated behind a single frontmatter flag so plain memo-style documents don't get a heavy cover they don't want:

```yaml
cover: true
```

The cover only renders in the **PDF export** (and the in-app Print Preview, which is a PDF rendered in an iframe). The editor canvas itself stays cover-less so you can edit body content without the cover taking up half the screen. If you don't set `cover:` at all, the cover is suppressed by default.

**Fields the cover surfaces.** Populate as many as you have; missing fields are skipped gracefully:

- `title` — the big bold title in the blue title block (already required for the body, used here too).
- `short_title` — used as the visible title if shorter than `title`; otherwise `title` is used.
- `document_number` — rendered immediately under the title in a monospace font (typical doc-control numbering like `T-REV-SCH-CMP` or `PSD-002`).
- `revision` — appears in the metadata table at the bottom of the cover (e.g. `v0.1`).
- `date_created` — appears in the metadata table.
- `project` — appears in the metadata table.
- `prepared_for` — appears in the metadata table (typically the client name).
- `author` — appears in the metadata table.
- `classification` — when set to `commercial-in-confidence` or `restricted`, also paints a classification banner across the cover.

**When to set `cover: true`.** Use it for formal external deliverables — client proposals, design reports, test reports, formal specifications. Skip it (or set `cover: false`) for internal memos, meeting minutes, short notes, and anything that's going to be read on-screen rather than printed.

**Templates and the cover.** If the user has selected a template (e.g. `template: "standard"` or `template: "proposal"`), check that template's own frontmatter for `cover: true`. The shipped LX templates may already enable it — in which case the cover renders automatically without you having to add `cover: true` to your document. If the template hasn't enabled it but the document should have one, override by setting `cover: true` explicitly in your document's frontmatter.

## Standard Markdown features (just use them)

These work as you'd expect from any Markdown:

- `# H1` through `###### H6` for headings
- `**bold**`, `*italic*`, `~~strikethrough~~`, `` `inline code` ``
- `- bullet list` and `1. numbered list` (nest with 2-space indent)
- `| col | col |` pipe tables (with header separator row)
- `> blockquote`
- ` ```language ` fenced code blocks
- `[link text](https://url)` for hyperlinks
- `---` for horizontal rules

## LX-specific extensions (use these for engineering docs)

### Callout boxes

Use these for tips, warnings, important notes:

```markdown
> [!NOTE]
> Informational note. Blue left border.

> [!TIP]
> Helpful tip. Green left border, "Tip:" prefix.

> [!IMPORTANT]
> Important caveat. Amber left border, "Important:" prefix.

> [!WARNING]
> Warning text. Red left border, "Warning:" prefix.

> [!STEP]
> Procedural step. Blue left border, no prefix.
```

### Tables

Use GFM pipe tables for *all* tables, whether the data is a short inline grid, a BOM, a checklist, or a long list of requirements. Pipe-table cells are fully editable in place — clicking a cell selects text normally, and the table can be resized, sorted, and rearranged by the reviewer.

```
| Reference | Part Number      | Quantity | Manufacturer       |
| --------- | ---------------- | -------- | ------------------ |
| U1        | STM32F405RGT6    | 1        | STMicroelectronics |
| C1        | CL21B104KBCNNNC  | 10       | Samsung            |
| R1        | RC0805FR-07100KL | 4        | Yageo              |
```

Escape any literal `|` inside a cell as `\|`. Cells may contain inline markdown (`**bold**`, `` `code` ``, links, math) but not block content (lists, paragraphs).

#### Marking a table's semantic data-type (optional)

If a workflow connector or downstream tool needs to identify a table by what kind of data it carries (e.g. "the BOM in this doc"), place an optional `` sentinel comment on the line immediately above the table:

```

| Reference | Part Number      | Quantity |
| --------- | ---------------- | -------- |
| U1        | STM32F405RGT6    | 1        |
```

Common labels: `bom`, `requirements`, `test-results`, `registers`, `checklist`. The label is free-text; pick whatever fits. The sentinel is invisible in the rendered document and is preserved through editor round-trips, so a human reader never sees it but a workflow agent can find the right table by scanning for it.

#### Legacy CSV blocks (deprecated)

Earlier versions of LX Draft supported ` ```csv:label ` fenced blocks as a separate "rich CSV table" node. That format is now **deprecated**: it renders as a read-only grid in the editor (cells can't be clicked into), and inline commas inside cells silently split rows into extra columns — both serious authoring traps. Existing documents containing `csv:` blocks still open and edit cleanly (the editor converts them to native pipe tables on load), but agents should not write new `csv:` blocks. Always use a pipe table; if data-typing is needed, use the `` sentinel above it.

Reference only — the legacy CSV block format looks like this and is kept here so agents can recognise it when reading older documents (do not write it in new documents):

````markdown
```csv:bom
reference,part_number,quantity,manufacturer
U1,STM32F405RGT6,1,STMicroelectronics
C1,CL21B104KBCNNNC,10,Samsung
R1,RC0805FR-07100KL,4,Yageo
```
````

### Equations (LaTeX)

```markdown
Inline math: $R = V / I$ where $V$ is voltage.

Block math:

$$
P_{total} = \sum_{i=1}^{n} V_i \cdot I_i
$$
```

### Footnotes and endnotes

```markdown
This statement needs a citation[^1].

This refers to an endnote[^note:pricing].

[^1]: Footnote text — typically appears at the bottom of the page.
[^note:pricing]: Endnote text — appears at the end of the document.
```

### Cross-references and bookmarks

```markdown


See {ref:sec:introduction} for background.
Refer to {ref:bookmark:thermal-section|the thermal section} for details.
```

### Document-property fields (live values from frontmatter)

You can embed a *live* reference to a frontmatter field in the body. It renders
the current value of that field (and updates if the frontmatter changes), and
resolves to the value in PDF/DOCX export. Use the `{field:NAME}` token:

```markdown
Document number: {field:document_number}
Revision {field:revision} — prepared for {field:prepared_for}.
```

Valid field names: `title`, `short_title`, `document_number`, `revision`,
`author`, `status`, `classification`, `date_created`, `project`, `prepared_for`.

In the editor, a human inserts these via the **Insert Field** toolbar button; as
an agent, just write the `{field:NAME}` token in the markdown — it round-trips
and resolves on export.

### Signature fields

A signature field renders the signer's name (in a cursive font) once the
document is signed, or a muted "Your signature here" placeholder when unsigned:

```markdown
Signed: {signature:author}
```

Signing itself is a human/Lexis action (see "Standalone vs Lexis" below) — as an
agent you place the `{signature:...}` token where the signature should appear;
you do not sign the document.

### Page breaks

If you need a hard page break in the printed output:

```markdown

```

### Multi-column sections

```markdown

Content here flows into two columns.

```

### Text boxes (bordered content)

```markdown

Content inside a bordered box.

```

### Images

For external images (URLs), use standard Markdown:

```markdown
![Alt text describing the image](https://example.com/image.png)
```

For embedded images, use the asset reference syntax:

```markdown
![Alt text](asset:my-image-id)
```

Then add the image to a `document-assets` block at the end of the file (see "Embedded images" below).

**Size, alignment and crop** are persisted as an HTML comment immediately after
the image. You normally don't need to write these (the human adjusts images by
dragging in the editor), but they round-trip and the exporter honours them:

```markdown
![Alt text](asset:my-image-id)
```

- `width` / `height` — display size in px.
- `align` — `left` | `center` | `right` | `inline`. `left`/`right` float the
  image so body text wraps around it; `center` is a centered block.
- `crop` — `top,right,bottom,left` inset in px (the visible region is the image
  minus these insets). Omit if not cropped.

### Table of contents

Insert a self-updating TOC anywhere:

```markdown

```

The editor renders this as an actual TOC. In source form it stays as the directive.

## Media attachments (preferred: deliver a bundle, don't base64 yourself)

**Do not base64-encode media inside the .lx.md.** LLM output is unreliable for large binary blobs — you will silently truncate, corrupt, or hit token limits. Instead, deliver two things:

1. A clean **`.lx.md` (or `.md`) file** with `asset:` references in the body.
2. A **`.zip` archive** containing the actual media files, named to match those references.

LX Draft's import dialog has a "Document + Archive" tab that does the embedding for you — it reads the archive, matches each ref to a file, base64-encodes server/browser-side, and produces a self-contained .lx.md.

### Reference syntax in the markdown

**Strongly preferred — use bare `asset:` references with no folder prefix:**

```markdown
![Tag at 10 o'clock](asset:photo-013435032)
![PCB Layout](asset:pcb-rev-b)
```

- `` must match a filename **stem** somewhere in the bundle folder (e.g. `asset:photo-013435032` matches `photo-013435032.jpg`).
- The folder name is **irrelevant** — LX Draft strips the top-level folder when matching. Don't put the folder name in the reference.
- The id should be a slug: letters, digits, hyphens. No spaces, no slashes.
- **Don't write `![alt](photos/photo-1.jpg)` or `![alt](report-bundle/photo-1.jpg)`.** If you change the folder name later, every reference breaks. Use `![alt](asset:photo-1)` and let LX Draft handle the lookup.

Relative paths (`./diagrams/field-plot.png`) are accepted as a fallback — LX Draft matches them by exact path then by basename — but they couple the document to the directory layout. Avoid them in agent output.

Absolute filesystem paths (`C:\...`, `/home/...`) can never resolve in a browser. Don't use them.

### Folder structure

The folder can be flat or have subfolders — both work, because LX Draft matches by filename stem. Filename stems must be unique within the bundle when you use `asset:` references.

```
my-report/                        ← name doesn't matter; user picks this folder
├── photo-013435032.jpg           ← matches asset:photo-013435032
├── photo-013449261.jpg           ← matches asset:photo-013449261
└── pcb-rev-b.png                 ← matches asset:pcb-rev-b
```

If you have many media files of different types, put them in subfolders for your own organisation — the matcher still works:

```
my-report/
├── photos/
│   ├── photo-013435032.jpg       ← still matches asset:photo-013435032
│   └── photo-013449261.jpg
└── diagrams/
    └── pcb-rev-b.png             ← still matches asset:pcb-rev-b
```

The `asset:` reference does **not** include the subfolder.

### Supported media types

Anything LX Draft can render or link: `png`, `jpg`/`jpeg`, `gif`, `webp`, `svg`, `bmp`, `tiff`, `pdf`, `mp4`, `webm`, `mp3`, `wav`, `ogg`. The MIME type is inferred from the extension.

### Inline SVG — self-contained diagrams, no asset bundle

Like Mermaid, a ` ```svg ` fenced code block renders live in the editor and in the PDF export — the SVG source sits directly in the document body as plain text. This is the preferred way to hand-author a diagram: no base64, no `document-assets` block, no separate media bundle to deliver alongside the `.lx.md`. Use it for schematic sketches, custom layouts, or any vector artwork that doesn't fit Mermaid's flowchart/sequence grammar:

````markdown
```svg

  
  Block A

```
````

The content must be a valid standalone `` document (same explicit `width`/`height` rule as below). It is run through a strict sanitizer on render, so **do not include** `