# Building artifacts that feel native on Quick

Authority: code-truth as of 2026-07-18 unless a line says otherwise.

Build the artifact for the renderer it will actually use. Quick has two render worlds: Markdown, MDX, CSV,
code, images, and other viewer formats mount through the box viewers; author HTML is served as your document
with Quick chrome injected around it. Do not assume one world styles the other.

## Pick the format

- Use Markdown for reports, memos, specs, briefs, research notes, and anything whose value is reading and
  commenting. The box viewer supplies the document shell, design tokens, section reader, text anchors, table
  cell anchors, file-path chips, and Mermaid rendering. Use MDX only when you need its syntax and can stay
  within the shipped component-free renderer; it does not get Markdown's table or file-path treatment.
- Use HTML or React for interactive tools, dashboards, demos, forms, and simulations. The page owns its CSS,
  layout, responsive behavior, and motion.
- Use CSV when the review target is the data grid itself. CSV cells get structural cell anchors without you
  stamping anything.
- Do not convert a document into a custom SPA just for polish. You lose the renderer's free document affordances
  and make review anchors easier to break.

## What each file type becomes

The decision rule above picks the format; this is the full affordance catalog behind it. Every non-HTML file
you publish mounts a box viewer keyed on its extension:

- `.md` → the themed document viewer: box design tokens, an `h2` section reader (whole-document and
  section-by-section modes), text anchors on visible prose, anchored table body cells (each table is anchored
  separately, so several tables on one page never collide), file-path chips, rendered
  Mermaid, and click-to-zoom on images and diagrams. Choose it when the artifact's value is reading and
  commenting.
- `.mdx` → the themed document viewer with Mermaid rewriting, but without Markdown's GFM table-cell stamping
  or file-path chips. No MDX component registry ships, so undefined JSX components fail rendering.
- `.csv` → a sortable, filterable, paginated data grid: one filter box searches all columns, headers sort, and
  every body cell carries its own row/column anchor. Choose it when the data grid is the deliverable.
- Code files (`py ts tsx jsx go rs java kt rb php c cpp h cs swift sql sh bash yaml yml toml ini conf txt log
  scss less json xml`) → a line-numbered source view with per-line anchors. Choose it when reviewers should
  point at exact lines. `.js`, `.mjs`, and `.css` are deliberately exempt: they serve raw so HTML apps keep
  working.
- Images (`png jpg jpeg gif webp avif bmp ico svg`) → a pinned image view where region comments anchor to the
  image surface. Only direct navigation gets the viewer; an `<img>` inside your own page still loads raw
  bytes. Choose it when the visual itself is the review target.
- `.pdf` → an in-page viewer that redraws each page with a selectable text layer, so both region pins and
  text highlights anchor. Choose it only for documents that already exist as PDFs; author new documents in
  Markdown for the section reader and cheaper anchors.
- A folder → the Drive-style file browser: name search, type-aware rows (kind icon and label; HTML entries
  open in a new tab), and a copy-link control. At any folder URL, `index.html` wins if present; otherwise
  `index.md` / `index.mdx` renders as the page; otherwise a folder holding exactly one file renders that file
  at the folder URL itself. Choose a folder when you ship several artifacts together.
- Anything else serves as raw bytes with a best-effort content type — no viewer, no anchors. Do not ship the
  review target in a format outside this catalog.

## Token values

There is no stable design-system CSS URL for author HTML. The compiled box CSS is resolved through the Vite
manifest and served only at hashed `/__oq/assets/<hash>.css` paths. Do not link those build-specific paths. For
HTML artifacts, copy the load-bearing values instead:

| Role | Token | Value | Use |
| --- | --- | --- | --- |
| Canvas | `--background` | `oklch(0.969 0.009 232)` | Match the `#EFF6FA` Quick canvas. |
| Work surface | `--card` | `oklch(1 0 0)` | Keep cards, sheets, tables, and controls white. |
| Surface float | `--shadow-card` | `0 0 0 1px oklch(0 0 0 / 0.06)` | Start the layered card shadow with the hairline ring. |
| Ink | `--foreground` | `oklch(0.22 0.006 250)` | Use near-black neutral text. |
| Primary action | `--primary` | `oklch(0.55 0.16 256)` | Reserve saturated color for links and main actions. |
| Radius | `--radius` | `0.625rem` | Keep controls modestly rounded. |
| Type | `--font-sans` | `"Inter Variable", ui-sans-serif, system-ui, sans-serif` | Prefer Inter, then system sans. |

Keep the palette mostly neutral: tinted canvas, white work surfaces, dark ink, sparse accent. Use motion only
for state change. Prefer CSS, `150ms` exits, `250ms` entries, `cubic-bezier(0.22, 1, 0.36, 1)` for surfaces,
and `ease-in-out` for text or icon swaps. Do not animate for decoration.

## Base and viewport

- Build with relative refs. For Vite, set `base: './'` or run `vite build --base=./`. For other bundlers, use
  the same relative public base.
- Keep app code relative too: no `fetch("/api/...")`, root imports, or root asset paths. If you need the site
  root, read `window.__OQ_SITE__`.
- Add `<meta name="viewport" content="width=device-width,initial-scale=1">` to full HTML documents.
- Fix every publish warning before sharing. The validator mechanically flags root-absolute JS refs, missing
  relative files, case-only mismatches, missing viewport meta, and local machine file links.
- Check the artifact at the smallest device floor the audience can plausibly use, not only on your monitor.

## Dark mode

Box-rendered pages are light today. Dark tokens exist in the web CSS, but served pages do not toggle `.dark`.

For Markdown, MDX, CSV, code, images, and PDFs, design for the light box. For HTML, choose one complete stance:

- Ship the light Quick-matching palette only.
- Or self-support `prefers-color-scheme` with a complete dark palette for canvas, surfaces, text, borders,
  shadows, charts, and focus states.

Never ship half-light, half-dark HTML that depends on Quick to finish the theme.

## Structure for the section reader (the sidebar)

The document viewer splits the page on `h2` boundaries and turns each one into a navigable section — that list
of `h2`s IS the reader's side navigation. Headings are navigation, not decoration, so author for it:

- Exactly one `h1` — the document title (or a frontmatter `title:`). Everything else is `h2`/`h3`.
- Break the body into several short, self-contained `h2` sections. Six focused sections read (and navigate)
  far better than two sprawling ones — each `h2` is one sidebar entry.
- Write descriptive heading text — "Rollout plan", not "Section 3". The sidebar shows the heading verbatim, so
  a reader should be able to jump straight to what they want from the heading alone.
- Don't skip levels (no `h3` before its `h2`); keep `h3` for detail *inside* a section, never for top-level nav.
- Keep paragraphs and list items short enough that a reviewer can anchor the exact visible text they mean.
- Put comparison data in Markdown tables. Body cells become anchored grid cells; headers are read by position. A
  comment resolves inside the table it was written on, so you can use as many tables as the document needs — even
  with repeated cell text. Reordering tables between versions is what moves their comments.
- Use Mermaid fences for diagrams. The renderer turns them into commentable regions and carries the diagram
  source in review context.
- Give images and diagrams real visual bounds and useful alt text. Region comments need a visible target.

## Pick the doc type first (Diátaxis)

Before drafting, decide which of the four Diátaxis modes the reader needs — mixing them is what makes docs
sprawl and the sidebar incoherent. Each maps to a ready-to-fill template in `references/formats/`:

| Reader need | Mode | Template |
| --- | --- | --- |
| Learn by doing, guided | Tutorial | `formats/tutorial.md` |
| Complete one known task | How-to | `formats/how-to.md` |
| Look up exact facts / an API | Reference | `formats/reference.md` |
| Understand why it works | Explanation | `formats/explanation.md` |

Beyond the four, `references/formats/README.md` maps work products (decision-memo, launch-brief, spec/TRD,
postmortem, research-report, weekly-update, one-pager, meeting-notes, pr-review) to the same fill-in skeletons.
Pick one, follow its skeleton, and don't hop between templates mid-document.

## Rich blocks inside Markdown — plain source, not components

The Markdown viewer's rich treatment comes from source syntax, not a component library. Use these three source
patterns:

- Mermaid diagram — a fenced block tagged `mermaid`. It renders as a commentable region, and its source travels
  into review context. `quick site publish` validates Mermaid in `.md` files before deploy.

        ```mermaid
        sequenceDiagram
          Reviewer->>Agent: leave a comment
          Agent->>Reviewer: publish a fix
        ```

- File-path chip — mention a bare source path in prose and it renders as a monospace chip inside that text block,
  for example internal/pay/refund.go:42. Common code extensions and an optional line or line range are recognized.
  Inline-code and linked paths are left alone.
  The chip is styling, not a separate comment anchor.
- Anchored table — a normal GFM table. Every body cell becomes a cell anchor, with headers read by position, so
  a reviewer can comment on one value. Each table gets its own internal identity, so a comment on the second
  table stays on the second table. Never write that identity yourself — an author-written `data-oq-*` attribute
  points comments at the wrong block.

MDX rewrites Mermaid fences at render time, but it does not ship the Markdown table and file-path transforms,
and publish-time Mermaid validation does not scan `.mdx`. There is no MDX component registry: JSX such as
`<Callout>` fails unless the renderer defines that component.

Do not author `data-oq-island`, `:::callout`, or request-response syntax. Those surfaces do not exist. Quick
selects a viewer from the published file type and mounts it through its internal `data-oq-app` registry; authors
never write `data-oq-*` attributes.

## Review overlay safety

- Keep reviewable prose as stable visible DOM text. Do not regenerate, randomize, or rewrite it after load.
- Keep text selectable. Avoid text-in-canvas-only, image-only prose, and SVG text when reviewers need to quote it.
- Keep important elements in the DOM with stable ids, names, hrefs, roles, or labels. HTML fallback comments
  re-find elements by CSS path and visible text.
- Never author `data-oq-*` attributes. They are reserved for Quick's viewers, review context, anchors, and chrome.
- Ship real `<head>` and `<body>` tags in full HTML so Quick's context script, review overlay, and badge inject
  predictably.
- Do not hide the injected overlay with global resets, fixed layers, or blanket `pointer-events` rules.
