# reportix-composer — complete library (all audiences)

_Generated whole-library download. See `agent-manifest.json` → `library` for discovery._

## Table of contents

- **Overview** (`00-overview`, developers)
- **Overview** (`00-overview`, builders)
- **Packages** (`01-packages`, developers)
- **Getting Started** (`02-getting-started`, developers)
- **Getting Started** (`02-getting-started`, builders)
- **SDK** (`03-sdk`, developers)
- **CLI** (`04-cli`, developers)
- **HTTP API** (`05-api`, developers)
- **MCP** (`06-mcp`, developers)
- **Templates** (`07-templates`, developers)
- **Templates** (`07-templates`, builders)
- **Image Assets** (`08-assets`, developers)

---

# Overview — developers

# Overview — Developers

**Audience:** Engineers choosing how to consume Reportix Composer.  
**Twin:** [Builders version](../builders/BOOK.md)

---

## 1. What it is

Turn Markdown into styled **PDF**, **Word (DOCX)**, **PowerPoint (PPTX)**, and **HTML** using swappable templates.

**Not** a CMS or collaborative editor — a render pipeline: Markdown in, branded document out.

One engine powers every surface: SDK, CLI, HTTP API, MCP server, Playground UI, and Studio UI.

---

## 2. Formats and surfaces

| Capability | Details |
| --- | --- |
| Formats | HTML, PDF (Playwright Chromium), DOCX, PPTX (landscape 16:9) |
| Templates | Built-ins (`clean-report`, `letter`, `technical-doc`, `cover-report`) + your own |
| Frontmatter | YAML (e.g. `title`, `logo`, `subtitle`) fills template slots |
| Image assets | Register once; reference as `{{image:<token>}}` in body or frontmatter |
| Surfaces | SDK, CLI (`reportix-composer`), HTTP API, MCP, Playground (`:6461`), Studio (`:6463`) |

All published packages are public under `@x12i/reportix-composer-*` on npm.

PDF needs Chromium once per machine: `npx playwright install chromium`. Requires **Node.js 20.11+**.

---

## 3. How rendering works

1. **Parse** Markdown (including YAML frontmatter).
2. **Resolve** `{{image:<token>}}` references via AssetStore.
3. **Load template** by id — built-in or user template from disk.
4. **Inject** CSS into `layout.html` and fill slots (`<!--CONTENT-->`, `<!--TITLE-->`, meta slots).
5. **Emit** HTML string, PDF via pooled Chromium, DOCX/PPTX from the Markdown AST.

Always call `shutdown()` in SDK/long-lived processes so the browser exits cleanly.

### Known limitations

- **HTML/PDF images**: absolute `http(s)` URLs, data URIs, or `{{image:<token>}}` assets.
- **DOCX / PPTX images**: local paths, URLs, and assets are best-effort; failures become `[image: alt]`.
- **DOCX / PPTX code blocks**: monospace + shading — no syntax highlighting.
- **PPTX overflow**: long content under a single H1 is not auto-split (may clip).
- **Raw HTML in Markdown**: kept for HTML/PDF; dropped for DOCX and PPTX.

---

## 4. Where to go next

| Goal | Book / use case |
| --- | --- |
| First successful file | Getting Started · `pick-a-surface` |
| Which package to install | Packages · `map-packages` |
| Custom look | Templates · `author-templates` |
| Logos / charts | Image Assets · `register-image-assets` |
| Agent tools | MCP · `wire-mcp-agents` |

---

# Overview — builders

# Overview — Builders

**Audience:** Template authors and Studio users.  
**Twin:** [Developers version](../developers/BOOK.md)

---

## 1. What it is

Reportix Composer turns Markdown into branded **PDF**, **DOCX**, **PPTX**, and **HTML** using templates you can browse and edit in Studio.

You do not need to change the renderer to ship a new look — author HTML+CSS templates (or draft from a screenshot) and pick them at render time.

---

## 2. Formats and surfaces

| You want… | Use |
| --- | --- |
| Try Markdown → preview / download | Playground (repo, port **6461**) |
| Browse / create / design templates | Studio (repo, port **6463**) — gallery + Template Designer |
| Built-in looks without custom work | `clean-report`, `letter`, `technical-doc`, `cover-report` |
| Shared logos / charts | Image assets (`{{image:<token>}}`) registered once |

Developers wire SDK/CLI/API/MCP; builders own template content and design screenshots for `create-from-image`.

---

## 3. How rendering works

Markdown (+ optional frontmatter such as `title`, `logo`, `subtitle`) is poured into a template shell. Image asset tokens resolve before emit. HTML/PDF share the same layout; DOCX and PPTX map structure from headings and paragraphs.

PPTX: each `#` (H1) starts a new landscape 16:9 slide.

---

## 4. Where to go next

- **Getting Started** — see the product end-to-end once.
- **Templates** — layout contract, slots, Studio Designer (`author-templates`).
- **Studio Template Designer** guide — Design / Code / Settings and PDF proof.

---

# Packages — developers

# Packages — Developers

**Audience:** Engineers choosing which `@x12i/reportix-composer-*` package to install.

---

## 1. Package table

| Package | When to install |
| --- | --- |
| `@x12i/reportix-composer-core` | In-process HTML/PDF/DOCX/PPTX + `TemplateStore` + `AssetStore` |
| `@x12i/reportix-composer-cli` | Shell command `reportix-composer` |
| `@x12i/reportix-composer-api` | Network service `reportix-composer-api` |
| `@x12i/reportix-composer-api-client` | Typed `fetch` client for the HTTP API |
| `@x12i/reportix-composer-mcp-server` | MCP tools over stdio |
| `@x12i/reportix-composer-types` | Shared Zod schemas / TS types |
| `@x12i/reportix-composer-templates` | Rarely — pulled in by core |

Not published: `apps/playground`, `apps/studio` (run from this monorepo).

Knowledge for agents/humans: `@x12i/reportix-composer-docs` (this library) — install as a **devDependency** only.

---

## 2. Dependency shape

```
@x12i/reportix-composer-types
        ↑
@x12i/reportix-composer-templates ──→ @x12i/reportix-composer-core ──→ CLI / API / MCP
                                   ↓
                         @x12i/reportix-composer-api-client  (HTTP → API)
```

Core formats: **HTML**, **PDF**, **DOCX**, and landscape **PPTX** (H1 = new slide).

---

## 3. Naming note

Short names like `@x12i/core` / `@x12i/cli` are already used by another x12i project on npm, so this product publishes under `@x12i/reportix-composer-*`.

---

# Getting Started — developers

# Getting Started — Developers

**Audience:** First-time integrators.  
**Twin:** [Builders version](../builders/BOOK.md)

---

## 1. Prerequisites

- Node.js **20.11+**
- Chromium for PDF: `npx playwright install chromium`

---

## 2. Option A — CLI

```bash
npm install -g @x12i/reportix-composer-cli
npx playwright install chromium

reportix-composer templates list
reportix-composer render --in report.md --template clean-report --format pdf --out report.pdf
reportix-composer render --in report.md --template clean-report --format pptx --out report.pptx
```

---

## 3. Option B — SDK

```bash
npm install @x12i/reportix-composer-core
npx playwright install chromium
```

```ts
import { renderToPdf, renderToPptx, shutdown } from "@x12i/reportix-composer-core";
import { writeFile } from "node:fs/promises";

const pdf = await renderToPdf("# Hello\n\nWorld", "clean-report");
await writeFile("report.pdf", pdf);

const pptx = await renderToPptx("# Hello\n\nWorld", "clean-report");
await writeFile("report.pptx", pptx);
await shutdown();
```

---

## 4. Option C — HTTP API

```bash
npm install -g @x12i/reportix-composer-api
npx playwright install chromium
reportix-composer-api   # http://localhost:6460
```

```ts
import { ReportixComposerClient } from "@x12i/reportix-composer-api-client";

const client = new ReportixComposerClient({ baseUrl: "http://localhost:6460" });

const result = await client.compose({
  markdown: "# Hello",
  templateId: "clean-report",
  output: { format: "pdf" }
});
```

---

## 5. Option D — MCP

```json
{
  "mcpServers": {
    "reportix-composer": {
      "command": "npx",
      "args": ["-y", "@x12i/reportix-composer-mcp-server"]
    }
  }
}
```

---

## 6. Built-in templates

- `clean-report` — multi-section reports
- `letter` — short correspondence
- `technical-doc` — technical documentation
- `cover-report` — cover-style layout with `logo` / `subtitle` frontmatter (pair with image assets)

Create your own with CLI `templates create-from-html` / `create-from-image`, the SDK, or Studio. Register shared images via `reportix-composer assets` (see the Image Assets book).

---

# Getting Started — builders

# Getting Started — Builders

**Audience:** People trying Playground/Studio before writing code.  
**Twin:** [Developers version](../developers/BOOK.md)

---

## 1. Prerequisites

From this monorepo:

```bash
pnpm install
pnpm playwright:install
pnpm build
pnpm dev
```

- Playground: **6461**
- Studio: **6463**
- API: **6460**

---

## 2. Option A — CLI

Ask a developer to install `@x12i/reportix-composer-cli`, or use Playground export once `pnpm dev` is running.

---

## 3. Option B — SDK

Developers embed `@x12i/reportix-composer-core`. Builders supply template HTML/CSS and sample Markdown.

---

## 4. Option C — HTTP API

Studio and Playground talk to the local API. Optional `REPORTIX_COMPOSER_API_KEY` protects non-health routes.

---

## 5. Option D — MCP

Agents can render, create templates, and upload image assets when the MCP server is configured.

---

## 6. Built-in templates

Start with `clean-report` or `cover-report` (logo + subtitle covers). Clone look-and-feel via Studio create-from-HTML, create-from-image (`ANTHROPIC_API_KEY` required for image drafts), or open the Template Designer after forking a built-in.

---

# SDK — developers

# SDK — Developers

**Audience:** Engineers embedding `@x12i/reportix-composer-core` in Node.js.

---

## 1. Install

```bash
npm install @x12i/reportix-composer-core
npx playwright install chromium
```

---

## 2. Render

```ts
import { renderToHtml, renderToPdf, renderToDocx, renderToPptx, shutdown } from "@x12i/reportix-composer-core";

const md = `---
title: Q1 Report
---

# Summary

Body here.
`;

const { html, title } = await renderToHtml(md, "clean-report");
const pdf = await renderToPdf(md, "clean-report", {
  pdf: { format: "Letter", landscape: false }
});
const docx = await renderToDocx(md, "technical-doc");
const pptx = await renderToPptx(md, "clean-report"); // landscape 16:9; each H1 = new slide

await shutdown();
```

Always call `shutdown()` when your process is done (or on SIGTERM in long-lived servers) so Playwright exits cleanly.

Optional render options include `templatesDir` and `assetsDir` when stores are not at the defaults.

---

## 3. Template store

```ts
import { TemplateStore } from "@x12i/reportix-composer-core";

const store = new TemplateStore({
  templatesDir: "./my-templates" // optional; else REPORTIX_COMPOSER_TEMPLATES_DIR or ~/.reportix-composer/templates
});

const all = await store.list();
const one = await store.get("clean-report");

await store.createFromHtml({
  id: "brand-report",
  name: "Brand Report",
  layoutHtml: "<!doctype html><html><head></head><body><main><!--CONTENT--></main></body></html>",
  stylesCss: "main { max-width: 720px; margin: 0 auto; }"
});

await store.update("brand-report", { name: "Brand Report v2" });
await store.delete("brand-report");
```

Built-in templates cannot be updated or deleted. Use `store.duplicate(sourceId, { id, name })` to fork a built-in into the user store.

---

## 4. AI template from image

```ts
import { readFile } from "node:fs/promises";
import { createTemplateFromImage, shutdown } from "@x12i/reportix-composer-core";

const imageBuffer = await readFile("design.png");
await createTemplateFromImage({
  id: "from-design",
  name: "From Design",
  imageBuffer,
  imageMediaType: "image/png",
  anthropicApiKey: process.env.ANTHROPIC_API_KEY!
});
await shutdown();
```

---

## 5. Image assets

```ts
import { AssetStore, renderToHtml } from "@x12i/reportix-composer-core";
import { readFile } from "node:fs/promises";

const assetsDir = "./my-assets";
const assets = new AssetStore({ assetsDir });
const buffer = await readFile("logo.png");
const asset = await assets.create({
  buffer,
  filename: "logo.png",
  mimeType: "image/png",
  token: "brand-logo"
});

const md = `---
title: Cover demo
logo: "{{image:${asset.token}}}"
subtitle: Confidential
---

# Body
`;

const { html } = await renderToHtml(md, "cover-report", { assetsDir });
```

See the Image Assets book for CLI/API/MCP equivalents.

---

# CLI — developers

# CLI — Developers

**Audience:** Engineers using the `reportix-composer` binary.

---

## 1. Install

```bash
npm install -g @x12i/reportix-composer-cli
npx playwright install chromium
```

Binary name: `reportix-composer`.

---

## 2. Render

```bash
reportix-composer render --in report.md --template clean-report --format pdf --out report.pdf
reportix-composer render --in report.md --template letter --format docx
reportix-composer render --in report.md --template clean-report --format pptx
reportix-composer render --in report.md --template technical-doc --format html
reportix-composer render --in report.md --template cover-report --format pdf --out cover.pdf
```

---

## 3. Templates

```bash
reportix-composer templates list
reportix-composer templates list --json
reportix-composer templates show clean-report
reportix-composer templates create-from-html --id my-layout --name "My Layout" \
  --layout layout.html --styles styles.css
reportix-composer templates create-from-image --id from-shot --name "From Shot" \
  --image design.png
reportix-composer templates delete my-layout
```

`--templates-dir` overrides the user templates directory on any command.

---

## 4. Assets

```bash
reportix-composer assets add ./logo.png --token brand-logo
reportix-composer assets list
reportix-composer assets remove brand-logo
```

`--assets-dir` (or `REPORTIX_COMPOSER_ASSETS_DIR`) overrides the asset store on any command that resolves `{{image:<token>}}`.

---

# HTTP API — developers

# HTTP API — Developers

**Audience:** Engineers running or calling `@x12i/reportix-composer-api`.

---

## 1. Run

```bash
npm install -g @x12i/reportix-composer-api
npx playwright install chromium
reportix-composer-api
```

Optional env:

| Variable | Purpose |
| --- | --- |
| `REPORTIX_COMPOSER_API_PORT` / `PORT` | Listen port (default **6460**) |
| `REPORTIX_COMPOSER_API_KEY` | If set, require `Authorization: Bearer <key>` (except `/health`) |
| `REPORTIX_COMPOSER_TEMPLATES_DIR` | User templates directory |
| `REPORTIX_COMPOSER_ASSETS_DIR` | Image asset store directory |

---

## 2. Call with curl

```bash
curl -s http://localhost:6460/health

curl -s http://localhost:6460/templates | jq .

curl -s -X POST http://localhost:6460/compose \
  -H 'content-type: application/json' \
  -d '{"markdown":"# Hello","templateId":"clean-report","output":{"format":"html"}}' | jq .

curl -s -X POST http://localhost:6460/compose \
  -H 'content-type: application/json' \
  -d '{"markdown":"# Hello","templateId":"clean-report","output":{"format":"pdf"}}' \
  --output report.pdf

curl -s -X POST http://localhost:6460/templates/clean-report/duplicate \
  -H 'content-type: application/json' \
  -d '{"id":"my-copy","name":"My Copy"}' | jq .

curl -s -X POST http://localhost:6460/templates/my-copy/preview \
  -H 'content-type: application/json' \
  -d '{"sample":{"markdown":"# Hello"},"format":"html","anatomy":true}' | jq .

curl -s -F file=@logo.png -F token=brand-logo http://localhost:6460/assets | jq .
```

---

## 3. Typed client

```bash
npm install @x12i/reportix-composer-api-client
```

```ts
import { ReportixComposerClient } from "@x12i/reportix-composer-api-client";

const client = new ReportixComposerClient({
  baseUrl: "http://localhost:6460",
  apiKey: process.env.REPORTIX_COMPOSER_API_KEY
});

const pdf = await client.compose({
  markdown: "# Hello",
  templateId: "clean-report",
  output: { format: "pdf" }
});
const templates = await client.listTemplates();

const copy = await client.duplicateTemplate("clean-report", { id: "my-copy", name: "My Copy" });
const preview = await client.previewTemplate(copy.manifest.id, {
  sample: { markdown: "# Hello" },
  format: "html",
  anatomy: true
});
```

Asset upload/list/delete are HTTP multipart/JSON routes; the typed client does not wrap them yet.

---

## 4. Route summary

| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/health` | Liveness (no auth) |
| `GET` | `/templates` | List templates |
| `GET` | `/templates/:id` | Get template |
| `POST` | `/templates/from-html` | Create from HTML + CSS |
| `POST` | `/templates/from-image` | Create from image (multipart) |
| `PATCH` | `/templates/:id` | Update user template (`name`, `description`, `layoutHtml`, `stylesCss`, `page`, `theme`, `visual`, `renderFirstHeading`) |
| `POST` | `/templates/:id/duplicate` | Fork built-in or user template into the user store |
| `POST` | `/templates/:id/preview` | Preview unsaved patch as HTML or PDF (`sample`, optional `patch`, `anatomy`) |
| `DELETE` | `/templates/:id` | Delete user template |
| `GET` | `/assets` | List image assets |
| `POST` | `/assets` | Multipart upload (`file`; optional `token`, `filename`) |
| `GET` | `/assets/:token` | Asset metadata |
| `GET` | `/assets/:token/raw` | Raw image bytes |
| `DELETE` | `/assets/:token` | Delete asset |
| `POST` | `/compose` | Compose Markdown → HTML/PDF/DOCX/PPTX (set `output.format`) |

---

# MCP — developers

# MCP — Developers

**Audience:** Engineers wiring agents to Reportix Composer.

---

## 1. Run configure

```bash
npm install -g @x12i/reportix-composer-mcp-server
npx playwright install chromium
```

Example MCP client config:

```json
{
  "mcpServers": {
    "reportix-composer": {
      "command": "npx",
      "args": ["-y", "@x12i/reportix-composer-mcp-server"],
      "env": {
        "ANTHROPIC_API_KEY": "optional"
      }
    }
  }
}
```

Optional env:

- `REPORTIX_COMPOSER_TEMPLATES_DIR` — user template store
- `REPORTIX_COMPOSER_ASSETS_DIR` — image asset store

---

## 2. Tools

- `list_templates` / `get_template`
- `render_markdown_to_html` (returns HTML inline)
- `render_markdown_to_pdf` / `render_markdown_to_docx` / `render_markdown_to_pptx` (write a file; optional `outPath`)
- `create_template_from_html` / `create_template_from_image` / `delete_template`
- `list_image_assets` — list registered assets
- `upload_image_asset` — `{ filePath, token? }` → `{ token, reference: "{{image:...}}" }`

PPTX is always landscape 16:9; each `#` heading starts a new slide.

---

# Templates — developers

# Templates — Developers

**Audience:** Engineers integrating template stores and manifests.  
**Twin:** [Builders version](../builders/BOOK.md)

---

## 1. Built-ins

Shipped in `@x12i/reportix-composer-templates` (read-only):

| Id | Use |
| --- | --- |
| `clean-report` | General multi-section reports |
| `letter` | Letters / short correspondence |
| `technical-doc` | Technical documentation |
| `cover-report` | Cover-style layout; reads frontmatter `logo` and `subtitle` |

---

## 2. Layout contract

Every template directory needs:

1. `template.json` — manifest (validated by `TemplateManifestSchema`)
2. `layout.html` — must include `</head>` and slot tokens
3. `styles.css` — injected before `</head>`

Common HTML slots:

- `<!--CONTENT-->` — rendered Markdown body (required)
- `<!--TITLE-->` — document title
- additional `metaSlots` declared in the manifest

---

## 3. User templates

Writable location (never overwrites built-ins):

- default: `~/.reportix-composer/templates`
- override: `REPORTIX_COMPOSER_TEMPLATES_DIR`, SDK `templatesDir`, or CLI `--templates-dir`

Create via CLI, SDK `TemplateStore#createFromHtml` / `createTemplateFromImage` / `duplicate`, API, MCP, or Studio.

`create-from-image` needs `ANTHROPIC_API_KEY`.

HTTP helpers for the Designer: `POST /templates/:id/duplicate` and `POST /templates/:id/preview` (unsaved `patch` + sample Markdown → HTML or PDF).

---

## 4. Images in Markdown

- Prefer `{{image:<token>}}` for logos and charts registered in AssetStore (see Image Assets book)
- Also supported: absolute `http(s)` URLs or data URIs (HTML/PDF)
- DOCX / PPTX: local paths, URLs, and assets are best-effort; failures become placeholders

Frontmatter fields such as `logo` and `subtitle` are filled into meta slots when the template declares them (e.g. `cover-report`).

---

## 5. PPTX

Every manifest includes a `pptx` block. Built-ins and new templates default to **landscape 16:9** (13.333″ × 7.5″).

- Each `#` (H1) starts a new slide
- Optional title slide when a document title is present (frontmatter / first heading)

---

# Templates — builders

# Templates — Builders

**Audience:** Authors designing layouts in Studio or from HTML/CSS.  
**Twin:** [Developers version](../developers/BOOK.md)

---

## 1. Built-ins

Start here before inventing a new layout:

| Id | Best for |
| --- | --- |
| `clean-report` | Multi-section reports |
| `letter` | Short correspondence |
| `technical-doc` | Technical documentation |
| `cover-report` | Cover pages with `logo` + `subtitle` frontmatter |

---

## 2. Layout contract

A template folder is three files:

| File | Role |
| --- | --- |
| `template.json` | Id, name, page/theme/DOCX/PPTX styles, meta slots |
| `layout.html` | Shell with `</head>` and `<!--CONTENT-->` |
| `styles.css` | Look-and-feel injected into the shell |

Keep slot names stable; renderers fill them from Markdown and frontmatter.

---

## 3. User templates

Your custom templates live under `~/.reportix-composer/templates` (or a path your team sets). Built-ins are never overwritten.

Create from:

- Studio UI (HTML or design screenshot)
- **Fork to edit** a built-in (duplicate into the user store)
- CLI `create-from-html` / `create-from-image`
- Asking an agent via MCP when configured

Screenshot drafts need an Anthropic API key.

---

## 4. Studio Designer

Open **Design** on a user template (fork a built-in first if needed):

- Structured controls for brand colors, typography, content styling, and PDF page setup
- Live preview + optional **Anatomy** labels + on-demand **PDF proof**
- **Code** tab for raw `layoutHtml` / `stylesCss`
- **Settings** for name/description and heading policy

Design controls apply to **HTML and PDF** only. See the Studio Template Designer guide for the full walkthrough.

---

## 5. Images in Markdown

Prefer registered image assets (`{{image:<token>}}`) for logos and charts so every surface resolves the same bytes. Absolute HTTPS URLs also work for HTML/PDF previews.

---

## 6. PPTX

Slides are landscape 16:9. Structure decks with `#` headings — one H1 per slide. Put deck title in YAML frontmatter `title` for an opening title slide.

---

# Image Assets — developers

# Image Assets — Developers

**Audience:** Engineers registering reusable images for Markdown and frontmatter.

---

## 1. What assets are

Register an image once, then reference it anywhere as `{{image:<token>}}` — in Markdown body images or in frontmatter fields such as `logo`.

At render time the engine resolves every `{{image:<token>}}` to a `data:` URI (HTML/PDF) and embeds the bytes for DOCX/PPTX. Unknown tokens fail fast with `AssetNotFoundError`.

---

## 2. Storage

- Default directory: `~/.reportix-composer/assets`
- Override: `REPORTIX_COMPOSER_ASSETS_DIR`, SDK `assetsDir`, or CLI `--assets-dir`

Each asset is a folder `<token>/` containing `meta.json` and `asset.bin`.

Supported MIME types: `image/png`, `image/jpeg`, `image/webp`.

---

## 3. Reference form

```markdown
---
title: Q1 Report
logo: "{{image:brand-logo}}"
subtitle: Confidential
---

# Summary

![Revenue chart]({{image:q1-chart}})
```

The builtin `cover-report` template reads frontmatter `logo` and `subtitle` for a cover-style layout.

---

## 4. CLI

```bash
reportix-composer assets add ./logo.png --token brand-logo
reportix-composer assets list
reportix-composer assets remove brand-logo

reportix-composer render --in report.md --template cover-report --format pdf --out report.pdf
```

Use `--assets-dir` (or `REPORTIX_COMPOSER_ASSETS_DIR`) on any command that resolves tokens.

---

## 5. HTTP API

| Method | Path | Description |
| --- | --- | --- |
| `POST` | `/assets` | Multipart upload (`file` required; optional `token`, `filename`) |
| `GET` | `/assets` | List assets |
| `GET` | `/assets/:token` | Asset metadata |
| `GET` | `/assets/:token/raw` | Raw image bytes |
| `DELETE` | `/assets/:token` | Delete asset |

The typed `@x12i/reportix-composer-api-client` does not wrap asset routes yet — use multipart/curl for uploads.

---

## 6. MCP

- `upload_image_asset` — `{ filePath, token? }` → returns `{ token, reference: "{{image:...}}" }`
- `list_image_assets` — list registered assets

---

## 7. SDK

```ts
import { AssetStore, renderToHtml } from "@x12i/reportix-composer-core";
import { readFile } from "node:fs/promises";

const assetsDir = "./my-assets";
const assets = new AssetStore({ assetsDir });
const buffer = await readFile("logo.png");
const asset = await assets.create({
  buffer,
  filename: "logo.png",
  mimeType: "image/png",
  token: "brand-logo"
});

const md = `---
title: Cover demo
logo: "{{image:${asset.token}}}"
---

# Body
`;

const { html } = await renderToHtml(md, "cover-report", { assetsDir });
```

Pass `assetsDir` on render options when the store is not at the default path.
