zudo-doc
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

zudo-doc-writing-rules

Doc-writing rules for zudo-doc content (mdx files under src/content/docs/ and src/content/docs-ja/). Consult before writing or editing doc content. Covers: no h1 in content, sidebar_position is mandat...

zudo-doc Doc-Writing Rules

IMPORTANT: Consult these rules before writing or editing any mdx content under src/content/docs/ or src/content/docs-ja/. These rules exist to prevent common AI mistakes that silently break layout, navigation, or i18n.

Reference

For navigation structure rules (which category, filesystem layout), see the companion skill zudo-doc-navigation-design. This skill covers content-level mistakes, not structural ones.

Hard Rules (never violate)

No h1 in content

  • Frontmatter title is the page h1. It is rendered automatically by the doc layout.

  • Content MUST start with ## h2, not # h1.

  • Writing # Something inside the body produces a duplicate h1 and breaks heading hierarchy / TOC / a11y.

---
title: Installation
sidebar_position: 1
---

## Prerequisites      ← start here, NOT with a "# Installation" heading

...

Do not use horizontal rules as section separators

  • Headings and whitespace already express document structure; do not add body-level --- merely to divide sections.

  • Use a horizontal rule only when the rule itself has semantic meaning, such as documentation that demonstrates horizontal-rule syntax.

Always set sidebar_position

  • Without it, pages sort alphabetically within their category — almost never what you want.

  • Set it in the frontmatter of every page, including category index.mdx files (which control the category's position in the parent sidebar).

  • Small integers are fine; leaving gaps (1, 2, 3, 10) makes later insertion easier.

Kebab-case file names

  • my-article.mdx

  • myArticle.mdx ✗ — breaks on case-sensitive filesystems

  • my_article.mdx ✗ — inconsistent with the rest of the site

The URL slug is derived from the filename, so kebab-case also keeps URLs clean.

Bilingual rule

  • When creating or updating any doc page, update both EN (src/content/docs/) and JA (src/content/docs-ja/) versions.

  • Keep code blocks identical — only translate prose.

  • Keep <HtmlPreview> and other JSX blocks identical.

  • The JA directory should mirror the EN directory tree exactly.

  • Exception: files with generated: true in frontmatter are generator-owned; do not hand-edit or translate them.

  • Exception: the Claude/Codex resource generators own their overview and category index.mdx targets in the default content directory and every configured locale directory. They generate localized indexes from resource.* translations, so do not create hand-written locale stubs. If an authored file already occupies a target path, the generator refuses to overwrite it; remove or rename the file and express its title, description, and labels through ZudoDocConfig.translations.

  • Exception: Claude/Codex resource detail files stay in the default content directory and use body fallback at other locale routes. Do not copy those generated detail files into locale directories.

  • Exception: pages whose paths are explicitly listed under settings.defaultLocaleOnlyPrefixes are default-locale-only by design — do not create a JA mirror for them. The source of truth is settings.defaultLocaleOnlyPrefixes in src/config/settings.ts; this repository currently configures no such prefixes.

Frontmatter Schema

The schema is package-owned (@takazudo/zudo-doc/docs-schema, source packages/zudo-doc/src/docs-schema/index.ts — the default buildDocsSchema, wired in via zudoDoc(); there is no more host src/content.config.ts). Zod validation. Required and key optional fields:

FieldTypeRequired?Notes
titlestringyesRenders as page h1
sidebar_positionnumberrecommendedWithout it, pages sort alphabetically
descriptionstringnoSubtitle below the h1
sidebar_labelstringnoOverrides title in the sidebar only
category_shape"note-tray"noDeclares a top-level, flat note-tray category on its index.mdx
note_tray_datedbooleannoRequires date on every tray item, including unlisted items
note_tray_sidebar"index" | "year" | "month"noTray sidebar style; grouped styles require a dated tray
category_sort_order"asc" | "desc"noCategory or tray display direction; defaults to "asc"
date"YYYY-MM-DD"noRequired on every item in a dated tray; quoting is optional because zfb keeps scalar values as strings
updated"YYYY-MM-DD"noOptional update date on any doc; quoting is optional because zfb keeps scalar values as strings
tagsstring[]noCross-category grouping
draftbooleannoExcludes the page from the build entirely
unlistedbooleannoBuilt but hidden from sidebar/nav
generatedbooleannoBuild-time generated; skip JA translation
hide_sidebarbooleannoHide the left sidebar on this page
hide_tocbooleannoHide the right-side table of contents

The schema ends with .passthrough(), so custom keys (e.g. author, status) are preserved rather than rejected — they simply carry no built-in behavior. Consequence: a typo in a framework field name (sidebar_postion) does NOT error at build time; double-check spellings against the table above.

Linking Between Docs

Use relative paths with the .mdx extension. The framework's link resolver rewrites them to the correct URLs at build time and validates them.

[Link text](./sibling-page.mdx)
[Link text](../other-category/page.mdx#anchor)
  • Do NOT use absolute paths like /docs/foo/bar in prose — the resolver cannot verify them.

  • Do NOT omit the .mdx extension — the resolver needs it to find the target.

For the companion skill that audits links: /check-docs.

Admonitions

Admonitions are available globally — no imports needed.

Directive syntax (preferred in prose-heavy content):

:::note[Optional Title]
Body content.
:::

JSX syntax (preferred when nesting other JSX):

<Note title="Optional Title">Body content.</Note>
<Tip>...</Tip>
<Info>...</Info>
<Warning>...</Warning>
<Danger>...</Danger>
<Caution>...</Caution>

All admonition components accept an optional title prop. (caution is danger-adjacent, used by GitHub-style [!CAUTION] alerts; JSX additionally registers <Important> for [!IMPORTANT].)

Common Mistakes (Do Not Do)

  • Starting content with # Foo — duplicates the h1. Start with ## Foo.

  • Adding --- between headed sections — headings and whitespace already provide the separation.

  • Forgetting sidebar_position — produces alphabetical chaos in the sidebar.

  • camelCase or PascalCase file names — breaks on some filesystems.

  • Updating only the EN or only the JA version — breaks the bilingual mirror (except for generator-owned content and pages explicitly covered by defaultLocaleOnlyPrefixes).

  • Absolute /docs/... links in prose — the resolver cannot verify them; use relative ./page.mdx instead.

  • Omitting the .mdx extension in links — the resolver requires it.

  • Misspelling framework frontmatter fields — the schema passes unknown keys through, so a typo'd sidebar_position silently does nothing instead of erroring.

  • Translating code inside code blocks — the bilingual rule says code stays identical.

  1. Decide where the page belongs (see zudo-doc-navigation-design for the category decision).

  2. Create the EN file under src/content/docs/<category>/<page>.mdx with title and sidebar_position.

  3. Write content starting with ## h2 headings only.

  4. Use ./ relative links with .mdx extension for cross-refs.

  5. Create the matching JA file under src/content/docs-ja/<category>/<page>.mdx — same code blocks, translated prose.

  6. Run pnpm format then pnpm build to verify — the build will catch missing required fields, broken links, and unknown frontmatter.

Revision History

作成更新

AI Assistant

Ask a question about the documentation.

Preview theme

Loading theme previews…