Impeccable
bestofjs/bestofjs
A skill your agent uses when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a…
Technical reference for writing or editing open-doc pages — file contract, the A4/B4/A3 page canvas, print type scale, the vertical budget that decides where a page breaks, tables, charts, table of…
$ npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install simonliu-ai-product/open-doc doc-authoring --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/simonliu-ai-product/open-doc.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/core/skills/doc-authoring .claude/skills/doc-authoring && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "doc-authoring" agent skill from https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoring into .claude/skills/doc-authoring/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-authoring", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoringType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install simonliu-ai-product/open-doc doc-authoring --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/simonliu-ai-product/open-doc.git skills-src && mkdir -p .agents/skills && cp -r skills-src/packages/core/skills/doc-authoring .agents/skills/doc-authoring && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "doc-authoring" agent skill from https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoring into .agents/skills/doc-authoring/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-authoring", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install simonliu-ai-product/open-doc doc-authoring --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/simonliu-ai-product/open-doc.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/packages/core/skills/doc-authoring .cursor/skills/doc-authoring && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "doc-authoring" agent skill from https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoring into .cursor/skills/doc-authoring/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-authoring", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/simonliu-ai-product/open-doc.git --path packages/core/skills/doc-authoring--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install simonliu-ai-product/open-doc doc-authoring --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/simonliu-ai-product/open-doc.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/packages/core/skills/doc-authoring .gemini/skills/doc-authoring && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "doc-authoring" agent skill from https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoring into .gemini/skills/doc-authoring/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-authoring", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install simonliu-ai-product/open-doc doc-authoringInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/simonliu-ai-product/open-doc.git skills-src && mkdir -p .github/skills && cp -r skills-src/packages/core/skills/doc-authoring .github/skills/doc-authoring && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "doc-authoring" agent skill from https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoring into .github/skills/doc-authoring/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-authoring", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install simonliu-ai-product/open-doc doc-authoring --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/simonliu-ai-product/open-doc.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/packages/core/skills/doc-authoring .opencode/skills/doc-authoring && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "doc-authoring" agent skill from https://github.com/simonliu-ai-product/open-doc/tree/main/packages/core/skills/doc-authoring into .opencode/skills/doc-authoring/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-authoring", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
doc-authoringTechnical reference for writing or editing open-doc pages — file contract, the A4/B4/A3 page canvas, print type scale, the vertical budget that decides where a page breaks, tables, charts, table of…
Doc Authoring is an agent skill from simonliu-ai-product/open-doc. Technical reference for writing or editing open-doc pages — file contract, the A4/B4/A3 page canvas, print type scale, the vertical budget that decides where a page breaks, tables, charts, table of contents, page numbers, running headers/footers, and assets. Consult this whenever you are about to write or modify any file under docs/<id/, including from inside the create-doc workflow, or for any ad-hoc document edit. Triggers on phrases like "edit the report", "fix this page", "add a section", "change the…
Its SKILL.md is about 6.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 6 other files, including reference files (for example `references/assets.md`, `references/design-system.md` and `references/long-form.md`).
It sits in Frontend & Design, covering Typography. The repository describes itself as: The document framework built for agents — write reports as React, get real A4 pages, an outline, page numbers, and a PDF. The licence is MIT.
Read from SKILL.md and the folder at commit af6095d. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
nodeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Doc Authoring loads about 6.8k tokens when it runs, and up to ~13k if it reads all its reference files. Until then it costs about 155 tokens; SKILL.md has 3,263 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from simonliu-ai-product/open-doc at commit af6095d, republished under its MIT licence (© simonliu-ai-product). 3,263 words, ~6,782 tokens.
.claude/skills/doc-authoring/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.This skill is the technical reference for everything inside docs/<id>/index.tsx. It owns no workflow:
create-doc owns "draft a new document" — it asks the scoping questions, then delegates the how to this skill.Read the matching reference before using a primitive:
| Primitive | Read before | File |
|---|---|---|
design const + var(--od-*) tokens | writing any new document | references/design-system.md |
flow() auto-pagination | any body content (the default) | references/pagination.md |
| Vertical budget (fixed pages) | laying out a cover or divider by hand | references/pagination.md |
| Tables, stat rows, inline charts | rendering data of any kind | references/tables-and-charts.md |
Assets + <ImagePlaceholder> | importing images or leaving a placeholder | references/assets.md |
Footnotes, <Figure>, <Ref>, <DataTable> | any note, numbered figure, cross-reference, or .csv | references/long-form.md |
If themes/<id>.md exists at the project root and the document is meant to follow it, the theme file overrides the defaults in this skill — its palette, typography, page setup, and paste-ready components are authoritative. Read the theme file end-to-end before applying anything else here, and set meta.theme: '<id>' so the document back-links to it (chip on the document card, listing on /themes/<id>).
Themes are produced by the create-theme skill and are pure documentation: copy the design const and the Title / Footer / Table components straight into the document. mode: dark in a theme's frontmatter applies to its cover, not to body pages — anything that prints stays light.
docs/<kebab-case-id>/.docs/<id>/index.tsx. Images/fonts go under docs/<id>/assets/.package.json, open-doc.config.ts, or other documents.react, @open-document/core, and standard web APIs are available.index.tsx plus assets/ — nothing else. Helper components and constants live inside index.tsx; no sibling .tsx files, no README.md.// docs/<id>/index.tsx
import type { DocMeta, DocPage } from '@open-document/core';
const Cover: DocPage = () => <div>…</div>;
const Body: DocPage = () => <div>…</div>;
export const meta: DocMeta = {
title: 'Q3 Infrastructure Review',
subtitle: 'Platform team',
author: 'Platform Engineering',
pageSize: 'A4',
orientation: 'portrait',
createdAt: '2026-08-15T13:44:40.268Z',
};
export default [Cover, Body] satisfies DocPage[];export default is a non-empty array of entries. An entry is either a zero-prop React component (one fixed page) or a flow(<>…</>) section the framework paginates by measuring. Mix them freely — the usual shape is a fixed cover, a fixed contents page, then one flow section for the body.flow() for body content. Hand-splitting prose into fixed pages produces documents where every heading starts a half-empty page. Read references/pagination.md before writing either kind.meta.pageSize is 'A4' | 'B4' | 'A3' (default 'A4') and meta.orientation is 'portrait' | 'landscape' (default portrait). These six combinations are the only sheets there are — there is no Letter, no A5, no custom size, and no way to set a page's dimensions by hand. The same value drives the on-screen page, the @page size when printing, and the HTML export.meta.lang is the document's language as a BCP 47 tag — set it for anything not in English: 'zh-Hant-TW', 'zh-Hans', 'ja', 'ko'. Every sheet carries it, so it decides the glyph shapes of shared Han characters, the line-breaking rules (no ,。」 at the start of a line), and the language exported HTML and Word declare. The sheet already sets CJK text properly — strict kinsoku, and an eighth-em gap where a CJK character meets a Latin letter or digit with no space typed — so don't hand-insert spaces for that; a block that must not get the gap takes textAutospace: 'no-autospace'.export const records = rows (an imported .csv) makes the document print once per row. Pages read the current row with useRecord() or print one value with <Field name="company" />; meta.recordName: 'certificate-{name}' names each row's file ({#} is the row number) and meta.recordLabel names rows in the viewer's picker. open-doc export <id> --each writes one file per row. A flow section's blocks are fixed when the module loads, so content that varies by row goes inside blocks — a block can render nothing for a row — never as a different number of blocks.meta.createdAt is an ISO 8601 string literal set once when the doc is scaffolded — the home page sorts on it. Immediately before writing the file, run node -e "console.log(new Date().toISOString())" and paste the exact output. It must stay a plain string literal (no new Date(...)): the framework reads it with a regex at build time, it never evaluates the module.import { flow, type DocEntry } from '@open-document/core';
const Body = flow(
<>
<h1 style={h1}>1. Findings</h1>
<p style={p}>…</p>
<Table>…</Table>
</>,
{ footer: Footer },
);
export default [Cover, Contents, Body] satisfies DocEntry[];Each direct child of the fragment is one atomic block. Blocks never split across pages; headings glue to what follows them; a caption marked data-od-keep-with-previous stays with its figure. Everything else — where the breaks land, how many pages the section becomes, the running footer on each — is the framework's job.
Fixed DocPage components remain the right tool for the cover, a contents page, or a divider whose layout is the content. Those pages are subject to the vertical budget below.
| Size | Portrait px (96dpi) | Text block at 76px margins |
|---|---|---|
| A4 (210 × 297mm) | 794 × 1123 | 642 × 971 |
| B4 (JIS, 257 × 364mm) | 971 × 1376 | 819 × 1224 |
| A3 (297 × 420mm) | 1123 × 1587 | 971 × 1435 |
Landscape swaps the two numbers. B4 and A3 are for wide tables, plans, and posters — a body of prose set the full width of an A3 sheet is unreadable, so give a large sheet columns or wider margins.
You design as if the viewport is literally the page in CSS pixels. The viewer only scales the whole sheet.
font-size, padding, and positioning. No rem, no vw/vh, no % for type.width: '100%'; height: '100%'.style={{ … }}. Any CSS you load is global — scope classnames carefully.<ul>/<ol> needs an explicit listStyle: 'disc outside' / 'decimal outside' or it renders as unindented plain lines.| Element | Size | Notes |
|---|---|---|
| Cover title | 40–52px | Cover page only |
| H1 / section opener | 26–32px | One per section |
| H2 / subsection | 18–22px | |
| H3 / run-in heading | 15–17px | Often bold body size |
| Body | 13–15px | 1.5–1.65 line-height |
| Caption / table cell | 10–12px | Tables can go to 11px |
| Footnote / footer | 9–10px |
A DocPage does not scroll or reflow: anything past the bottom edge is silently cropped, so do the math before writing JSX. (Inside a flow() section the framework measures for you — this arithmetic is exactly what it removes.)
Usable height = page_height − 2 × margin (A4 @ 76px margins → 971px).
Text height = font_size × line_height × line_count. A paragraph that wraps to 4 lines counts as 4.
Lines per page ≈ 971 / (14 × 1.55) ≈ 44 lines of body copy on A4 — that is the whole budget for one page.
references/pagination.md has the worked example, the character-count estimate for how many lines a paragraph will wrap to, and the rules for where to split.
The framework builds the document outline by scanning rendered pages for h1, h2, h3 (or any element carrying data-od-heading). That outline powers the sidebar and <TableOfContents />.
<h1>/<h2>/<h3> elements for section titles, styled inline. Don't fake a heading with a <div> — it disappears from the outline and the TOC.<div data-od-outline="skip"> if you must use a heading tag for styling reasons.data-od-outline="skip". A contents list that opens with the cover and lists itself reads as a bug.data-od-heading="Short title" when the visible heading is long or contains markup.Bare elements on the sheet start from a base drawn from the design, not from a blank reset: headings are bold at --od-size-h1/h2/h3 in the heading font, paragraphs, lists, quotes and tables have a bottom margin, lists have their markers and indent, links take --od-accent with an underline, code/pre use --od-font-mono, and a quote carries a rule on its leading edge. Anything you set inline replaces it, so style the elements that matter to the layout explicitly — margins above all, since they decide where a page breaks.
Four primitives resolve themselves from the rendered pages, the same way the
contents list does. Read references/long-form.md before using any of them.
<Footnote> — numbered by position, printed at the foot of the page its
marker landed on, and its height is taken out of that page's budget before the
packer breaks. On a fixed page, add <Footnotes /> where they should print.<Figure caption id> — a numbered figure (or kind="table"), caption and
content in one unbreakable block. <ListOfFigures /> / <ListOfTables />
build the lists.<Ref to="id" /> — "Figure 3", plus the page when the target is elsewhere.<DataTable rows={…}> — a print-shaped table from an imported .csv.<Diagram chart={…} caption> — an architecture or flow drawing from an
imported .mmd. Given a caption it numbers as a figure, like <Figure>.<Chart data x y caption> — a bar, line or pie chart from rows, in the
document's colours; numbers as a figure. See references/tables-and-charts.md.meta.labels sets what they are called (圖, 表) — the numbering itself is
structural.
Write the drawing as Mermaid-flavoured text in docs/<id>/<name>.mmd, import
it, and hand it to <Diagram>:
%% docs/my-doc/architecture.mmd
flowchart TD
Client[使用者] -->|HTTPS| Gate{驗證}
Gate -->|通過| App[應用伺服器]
Gate -.->|拒絕| Deny([401])
App --> DB[資料庫]import { Diagram } from '@open-document/core';
import architecture from './architecture.mmd';
<Diagram chart={architecture} caption="請求路徑" width={420} />It is compiled to SVG at build time and drawn with the document's own theme variables, so it prints with the same ink and faces as the prose around it. Never reach for an image of a diagram when the diagram can be written.
Supported: flowchart/graph with TD or LR; nodes as A[box], A(round),
A([stadium]), A[(database)], A{decision}, A((circle)); links -->,
---, -.->, ==> with optional |labels|; chains A --> B --> C; %%
comments. A link back to an earlier step is drawn round the side, clear of the
steps in between. Anything else
in Mermaid's syntax — subgraphs, class diagrams, sequence diagrams — is not
supported, and a bad diagram fails the build with the line to fix.
Keep width inside the text block: a drawing wider than the column is a layout
fault, and open-doc check reports it as one.
import { TableOfContents } from '@open-document/core';
const Contents: DocPage = () => (
<div style={page}>
<h1 style={h1}>Contents</h1>
<TableOfContents maxLevel={2} />
</div>
);Page numbers come from the scan, so they are always correct — never hand-write a contents list. The outline fills in after the first render pass; that is expected and it is resolved before PDF/HTML export serializes the pages.
import { useDocPageCount, useDocPageNumber } from '@open-document/core';
const Footer = () => {
const page = useDocPageNumber();
const total = useDocPageCount();
return (
<div style={{ position: 'absolute', left: 76, right: 76, bottom: 40, display: 'flex', justifyContent: 'space-between', fontSize: 10, color: 'var(--od-muted)' }}>
<span>Q3 Infrastructure Review</span>
<span style={{ fontVariantNumeric: 'tabular-nums' }}>{page} / {total}</span>
</div>
);
};3 / 12. Both hooks are 1-based and return 0 outside a page.flow() section takes both — flow(<>…</>, { header: Header, footer: Footer }) — and prints them on every page it expands into; on a fixed page, drop the component in yourself. Cover pages normally omit them.top: 32 for a header, bottom: 40 for a footer); they do not consume the text block's vertical budget — but keep at least 24px of clearance between the body copy and either one.import { type DesignSystem, type DocMeta, type DocPage, useDocPageCount, useDocPageNumber } from '@open-document/core';
export const design: DesignSystem = {
palette: {
bg: '#ffffff',
text: '#16181d',
muted: '#6b7280',
accent: '#1d4ed8',
rule: '#e5e7eb',
},
fonts: {
heading: '-apple-system, BlinkMacSystemFont, "Inter", system-ui, sans-serif',
body: '-apple-system, BlinkMacSystemFont, "Inter", system-ui, sans-serif',
mono: 'ui-monospace, "SF Mono", Menlo, monospace',
},
typeScale: { title: 44, h1: 28, h2: 20, h3: 16, body: 14, caption: 10 },
margin: 76,
leading: 1.55,
radius: 6,
};
const page = {
width: '100%',
height: '100%',
boxSizing: 'border-box' as const,
padding: 'var(--od-margin)',
background: 'var(--od-bg)',
color: 'var(--od-text)',
fontFamily: 'var(--od-font-body)',
fontSize: 'var(--od-size-body)',
lineHeight: 'var(--od-leading)',
position: 'relative' as const,
};
const h1 = {
fontFamily: 'var(--od-font-heading)',
fontSize: 'var(--od-size-h1)',
lineHeight: 1.2,
fontWeight: 650,
margin: '0 0 20px',
};
const Footer = () => {
const n = useDocPageNumber();
const total = useDocPageCount();
return (
<div
style={{
position: 'absolute',
left: 'var(--od-margin)',
right: 'var(--od-margin)',
bottom: 40,
display: 'flex',
justifyContent: 'space-between',
fontSize: 'var(--od-size-caption)',
color: 'var(--od-muted)',
}}
>
<span>Q3 Infrastructure Review</span>
<span style={{ fontVariantNumeric: 'tabular-nums' }}>
{n} / {total}
</span>
</div>
);
};
const Cover: DocPage = () => (
<div style={{ ...page, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }}>
<p style={{ fontSize: 12, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--od-accent)', margin: 0 }}>
Platform Engineering
</p>
<h1 style={{ ...h1, fontSize: 'var(--od-size-title)', margin: '16px 0 12px' }}>
Q3 Infrastructure Review
</h1>
<p style={{ color: 'var(--od-muted)', margin: 0 }}>August 2026</p>
</div>
);
const Section: DocPage = () => (
<div style={page}>
<h1 style={h1}>1. Summary</h1>
<p style={{ margin: '0 0 14px' }}>
One paragraph per idea. Keep the page inside its vertical budget.
</p>
<Footer />
</div>
);
export const meta: DocMeta = {
title: 'Q3 Infrastructure Review',
subtitle: 'Platform team',
pageSize: 'A4',
createdAt: '2026-08-15T13:44:40.268Z',
};
export default [Cover, Section] satisfies DocPage[];A finished report commonly runs 800–2000 lines. When you only need one page, don't read the whole file — locate it first:
grep -n ": DocPage = " docs/<id>/index.tsxThen Read with offset + limit (~150 lines covers a page plus its helpers). Read the whole file only for cross-page work (renumbering sections, palette audit, reordering).
Renumbering is a real cost. If sections are numbered ("3.2 Findings"), inserting a page means editing every downstream heading. Prefer appending, or use unnumbered headings when the document is still churning.
A document is not a slide deck. Long-form copy is the point — but it still has rules:
Q3 billing export, 2026-08-01) — a report that can't be traced gets ignored.<ImagePlaceholder> for a chart or an explicit TODO: marker in the copy and tell them at hand-off.docs/ with a live thumbnail of page 1.F).@page size) and export HTML (self-contained, printable).index.tsx and the pages update live./assets in the dev UI): upload, rename, and delete files in the global assets/ folder or any document's assets/ folder, with an "unused" badge and a copy-ready import line. Files you reference in source are what it scans, so an import you write by hand shows up there immediately.docs/<id>/index.tsx — or leave a note for the agent, which is stored as a @doc-comment marker and processed by the apply-comments skill.open-doc export <id> --format pdf|html|png|docx produces the same output from a script, and open-doc check <id> reports layout faults. Both drive the real viewer in a headless browser, so what they produce is what the Download menu produces. A PDF exported this way also carries the outline as bookmarks and is tagged for screen readers — the same headings the sidebar and <TableOfContents /> list, so a heading marked data-od-outline="skip" stays out and data-od-heading sets the bookmark's text. (The Download menu prints through the browser's dialog, which writes no bookmarks.)open-doc diff <id> [--since <rev>] (MCP: diff_document) renders the document as it is and as it was at a git revision (default HEAD), pairs the pages by content, and lists each page as same, changed, added or removed, with the lines of text that moved. It also writes out/<id>-diff.html, a self-contained before/after report with the changed regions outlined — hand that to a reviewer. Run it before handing back an edit, so your summary of what changed is what actually changed on the page.<TableOfContents /> a TOC field, <Footnote> real footnotes, a flow() header and footer a Word header and footer with page-number fields, and the theme's CJK font the East Asian font. Write headings as real h1–h3 and tables as <table>/<DataTable> so they arrive as structure; anything drawn with boxes (a chart made of divs) arrives as a picture, and absolutely positioned layouts on fixed pages flow as plain paragraphs.design const — palette, fonts, type scale, margin, leading, radius — previewing on the real pages and writing the values back into docs/<id>/index.tsx on save.Inspect mode edits the literal text runs of an element, and nothing else:
<p style={p}>copy</p>) is editable in place.<p>對外端點為 <code>/mcp</code>,另外自訂 …</p>) is split into one field per run, with the markup shown as read-only chips. Each run is written back on its own, so the markup between them survives untouched.<Td>FastMCP</Td>) is editable: the inspector walks the React tree to the call site, which is where the words actually live. The helper's own definition stays untouched.{entry.text}, a map, a hook) is refused — there is nothing literal to rewrite. Edit whatever feeds it.<img />, <ImagePlaceholder />) cannot host one; the user has to click the wrapper.Practical consequence for authors: put text in its own element. <Td>{value}</Td> renders the same as <Td>text</Td> but only the latter can be edited from the page.
The panel rewrites the design object in place through an AST edit, so keep its initializer in the shape it can read:
export const design: DesignSystem = { … } (or const design = …) at module level, object literal only — string/number literals, nested objects. No spreads, no satisfies on the inner object, no computed keys, no values pulled from other constants.design const, saving from the panel creates one (and adds the DesignSystem type import). Anything the panel can't parse is reported in the panel instead of being silently overwritten.You cannot see the pages you just wrote. The framework can:
open-doc check <id> # every document if you omit the id; exits non-zero on errorsIt renders each sheet at true page size and reports what a reader would call a
mistake — content clipped by the page edge, a blank sheet, a heading stranded at
the foot of a page, type too small to print, an image that never loaded — each
with the line:column in your source. Agents driving the MCP server call
check_layout for the same report, and render_page for a PNG of one sheet.
Run it after writing a document and after any edit that changes how much text
is on a page. The checklist below is what you reason about; check is what
confirms it.
open-doc check <id> reports no errors.docs/<id>/index.tsx export defaults a non-empty DocEntry[], with body content in a flow() section rather than hand-split pages.100% × 100% and sets boxSizing: 'border-box' with the margin as padding.overflow: auto escape hatches.flow() section is taller than one page (a long table has to be split by hand — the framework never splits a block).h1/h2/h3 elements, so the outline and TOC pick them up.<TableOfContents />, not a hand-written list.useDocPageNumber() / useDocPageCount().export const design: DesignSystem and pages consume var(--od-*).fontVariantNumeric: 'tabular-nums'), and fit the text block width.<Ref> / <Figure> / <Footnote>, never typed in.docs/<id>/assets/, or root assets/ via @assets/...).<ImagePlaceholder> marks a real image the user must supply — not decorative filler.docs/<id>/ was edited.overflow: auto / scroll / hidden to "fit" more. The sheet doesn't scroll; you've hidden the bug.Figure 3 in the copy. Use <Ref> and <Figure>.<div> styled like a title) — they vanish from the outline.% widths that overflow the text block, or with more than ~7 columns on portrait A4.package.json / open-doc.config.ts / other documents.© simonliu-ai-product, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (references) in packages/core/skills/doc-authoring of simonliu-ai-product/open-doc.
Open the folder on GitHubat commit af6095d
Doc Authoring next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Doc Authoring this skillsimonliu-ai-product/open-doc | 108 | — | ~6.8k | Automated safety check: Pass | MIT | |
| Impeccablebestofjs/bestofjs | 3.1k | 26 repos | ~2.6k | Automated safety check: Pass | MIT | |
| Tailwindcss Developmentanonaddy/anonaddy | 4.9k | 10 repos | ~865 | Automated safety check: Pass | MIT | |
| Design SystemOhh-889/skyroc | 795 | 11 repos | ~1.7k | Automated safety check: Pass | MIT | |
| Make Interfaces Feel Bettersamuelclay/NewsBlur | 7.6k | 10 repos | ~1.5k | Automated safety check: Pass | MIT | |
| UI UX Pro Maxsaoudi-h/solar-icons | 190 | 18 repos | ~11k | Automated safety check: Notes | Custom licence |
bestofjs/bestofjs
A skill your agent uses when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a…
anonaddy/anonaddy
Always invoke when the user's message includes 'tailwind' in any form.
Ohh-889/skyroc
Token architecture, component specifications, and slide generation.
samuelclay/NewsBlur
Design engineering principles for making interfaces feel polished.
saoudi-h/solar-icons
UI/UX design intelligence for web and mobile. An agent skill from saoudi-h/solar-icons.
ibelick/ui-skills
Applies a fixed set of UI rules for stack, components, interaction, animation, typography and layout, or reviews a file against them with concrete fixes.
simonliu-ai-product/open-doc
A skill your agent uses when the user asks to apply, process, or clear the comments they left in the open-doc inspector — phrases like "apply the comments", "apply my edits", "I left notes on the…
simonliu-ai-product/open-doc
A skill your agent uses when the user wants to create, draft, author, or generate a new document, report, whitepaper, proposal, memo, or spec in this open-doc repo.
simonliu-ai-product/open-doc
Resolve which document, page, and (optionally) selected element the user is currently viewing in the open-doc dev server.
simonliu-ai-product/open-doc
Implementation patterns for the @open-doc/core runtime — the split between the viewer and the published bundle, virtual modules, the flow pipeline, the ops layer, dev-only plugins, and the…
simonliu-ai-product/open-doc
Reviews page layout, typography, and pagination code in open-doc against a print craft bar — the sheet is the deliverable, not the screen.
simonliu-ai-product/open-doc
Design and accessibility rules for the open-doc viewer chrome — the browser shell, sidebars, thumbnail rail, outline, assets and design panels, inspector overlay, and menus.
Categories
Technical reference for writing or editing open-doc pages — file contract, the A4/B4/A3 page canvas, print type scale, the vertical budget that decides where a page breaks, tables, charts, table of…. Doc Authoring is an agent skill from simonliu-ai-product/open-doc. Technical reference for writing or editing open-doc pages — file contract, the A4/B4/A3 page canvas, print type scale, the vertical budget that decides where a page breaks, tables, charts, table of contents, page numbers, running headers/footers, and assets.
Doc Authoring fits situations like: phrases like edit the report; change the margins; table of contents; how do documents work here.
Run `npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a claude-code`. Or copy the skill folder (packages/core/skills/doc-authoring in simonliu-ai-product/open-doc) into .claude/skills/doc-authoring in your project. Claude Code loads it when a task matches its description.
Run `npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a codex`. Or copy the skill folder (packages/core/skills/doc-authoring in simonliu-ai-product/open-doc) into .agents/skills/doc-authoring in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add simonliu-ai-product/open-doc --skill doc-authoring -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/doc-authoring, .gemini/skills/doc-authoring, .github/skills/doc-authoring and .opencode/skills/doc-authoring in your project.
Going by SKILL.md and its folder, Doc Authoring needs the command-line tools its instructions call (node).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Doc Authoring is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.8k tokens (SKILL.md is roughly 27k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 5.9k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Doc Authoring: Impeccable (bestofjs/bestofjs, 3.1k stars), Tailwindcss Development (anonaddy/anonaddy, 4.9k stars), Design System (Ohh-889/skyroc, 795 stars) and Make Interfaces Feel Better (samuelclay/NewsBlur, 7.6k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
simonliu-ai-product (a GitHub organization) maintains it in simonliu-ai-product/open-doc, which has 108 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on October 7, 2026.
Source: simonliu-ai-product/open-doc on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.