l-convert-to-article
Convert Draft to Blog Article
Convert a Docusaurus draft article from doc/docs/articles/ to a blog-compatible MDX file in blog/src/articles/.
Steps
1. Identify the draft article
Determine which draft to convert:
- Check
git diff --name-onlyfor uncommitted changes indoc/docs/articles/ - Check
git log --oneline -10 --diff-filter=AM -- doc/docs/articles/for recently added or modified articles - If the user specified an article name or path, use that
- If multiple candidates exist or the target is unclear, ask the user which article to convert
2. Read the draft
Read the full content of the target Markdown file from doc/docs/articles/.
3. Read the writing rules
Before converting, read the following rule documents to ensure the output follows the project's conventions:
doc/docs/overview/writing-style.mddoc/docs/overview/markdown-writing-rule.mddoc/docs/overview/vocabulary-rule.md
4. Determine the output filename
The output file goes to blog/src/articles/{slug}.mdx.
- If the draft filename is suitable as a slug (kebab-case, descriptive), use it
- Otherwise, derive a slug from the article title (lowercase, hyphens, ASCII only, max 50 chars)
- If a file with the same slug already exists, ask the user before overwriting
5. Build the frontmatter
The blog MDX requires this frontmatter format:
---
title: "記事のタイトル"
description: "記事の概要説明(1-2文)"
author: Takazudo
tags: []
createdAt: "YYYY-MM-DD"
---
- title: Use the draft's
titlefrontmatter, or the first# headingif no frontmatter title exists. If neither exists, ask the user. - description: Use the draft's
descriptionfrontmatter if available. Otherwise, generate a concise summary (1-2 sentences) based on the article content. - author: Always
Takazudo - tags: Leave as empty array
[]for now (tags will be attached via/l-tag-attach-to-articlein the next step) - createdAt: Today's date in
"YYYY-MM-DD"format
Do not include Docusaurus-specific frontmatter fields (sidebar_position, sidebar_label, pagination_next, pagination_prev).
6. Convert Docusaurus admonitions to MDX components
Convert Docusaurus admonition blocks to the corresponding blog MDX components:
:::note → <Note>
<!-- Docusaurus input -->
:::note[注記]
Content here.
Multiple lines supported.
:::
<!-- Blog MDX output -->
<Note>
Content here.
Multiple lines supported.
</Note>
:::info → <Info>
<!-- Docusaurus input -->
:::info[備考]
Content here.
:::
<!-- Blog MDX output -->
<Info>
Content here.
</Info>
Custom titles
If the admonition has a custom title (other than the standard 注記/備考):
:::note[カスタムタイトル]
Content here.
:::
<Note title="カスタムタイトル">
Content here.
</Note>
The standard titles are:
:::note 注記→<Note>(no title prop needed, defaults to 注記):::info 備考→<Info>(no title prop needed, defaults to 備考)
Other admonition types
If :::tip, :::warning, :::danger, or :::caution are found (they shouldn't be per writing rules, but just in case):
:::tip→<Info>:::warning→<Note>:::danger→<Note>:::caution→<Note>
7. Handle other Docusaurus-specific syntax
- Internal doc links: Convert Docusaurus relative links (
[text](./other-doc.md)) that point to other docs to appropriate form. If the link target is another article, convert to the blog URL format (/articles/slug). If it's a reference doc, remove the link and keep the text. - Import statements: Remove any Docusaurus-specific import statements (e.g.,
import CategoryNav from ...) - Docusaurus components: Remove Docusaurus-specific JSX components (e.g.,
<CategoryNav />) - Image paths: See step 7a below.
- Fix internal links in the doc draft: See step 7b below.
7a. Copy and rewrite image paths
Docusaurus serves static files from doc/static/, so images in drafts use paths like /img/articles/.... The blog (Next.js) serves static files from blog/public/ with basePath: '/pj/zpaper', so images must be both copied and path-rewritten.
For each image reference found in the article (markdown  or JSX <Img src="/img/..." />):
- Copy the image file from
doc/static/{path}toblog/public/{path}
- Example:
doc/static/img/articles/20260217-foo/bar.png→blog/public/img/articles/20260217-foo/bar.png - Create intermediate directories as needed (
mkdir -p)
- Rewrite the path in the MDX to include the blog basePath prefix
/pj/zpaper/
- Example:
/img/articles/20260217-foo/bar.png→/pj/zpaper/img/articles/20260217-foo/bar.png
This is necessary because:
- The blog uses
basePath: '/pj/zpaper'innext.config.mjs - Raw
<img>tags (from markdown images) are NOT automatically prefixed by Next.js — onlynext/imagegets basePath prefixing - The blog's
Imgcomponent renders a plain<img>tag without basePath handling
If the draft article has no images, skip this step.
7b. Fix internal links in the doc draft
The doc draft (doc/docs/articles/) and the blog output (blog/src/articles/) use different link formats for internal article references. A link that works in the blog may break the Docusaurus build, and vice versa. This step ensures both files have correct links.
Scan all markdown links in the article and identify internal links — links pointing to other articles or pages within the site (not external URLs like https://...).
Fix the doc draft source file (edit in place):
- Links to other articles must use Docusaurus-relative paths:
./other-article-slug(no/articles/prefix, no.mdextension needed) - Blog-style absolute paths like
/articles/slugwill cause Docusaurus broken link errors — convert them to./slug - Verify the link target actually exists in
doc/docs/articles/by checking for a matching.mdfile
Fix the blog output:
- Links to other articles should use the blog URL format:
/articles/slug - Docusaurus-relative paths like
./other-article-slugshould be converted to/articles/other-article-slug - Verify the link target actually exists in
blog/src/articles/by checking for a matching.mdxfile
If a link target doesn't exist in either location, warn the user and ask how to handle it (remove the link, keep as-is, or fix the path).
8. Write the output file
Write the converted MDX to blog/src/articles/{slug}.mdx.
9. Verify the output
After writing, read the output file and verify:
- Frontmatter has all required fields (
title,description,author,tags,createdAt) - No Docusaurus-specific syntax remains (
:::, Docusaurus imports, Docusaurus components) - Admonitions are properly converted to
<Note>/<Info>components - The markdown structure is intact
10. Generate thumbnail and OGP image
Generate the kumiko-pattern thumbnail SVG and OGP PNG for the article:
pnpm kumiko-gen {slug}
pnpm svg-to-png {slug}
The root script already includes --color-scheme random --zoom 5, so no extra flags are needed.
This creates:
blog/public/thumbnails/{slug}.svg— Thumbnail displayed in article headerblog/public/thumbnails/{slug}.png— OGP image for social media (1200x630px)
No frontmatter changes are needed — the blog resolves thumbnails automatically by slug.
11. Tag the article
After successful conversion, run the tag attachment workflow:
- Use
/l-tag-attach-to-articleto suggest and attach tags - Use
/l-tag-update-listif new tags are needed
12. Report
Tell the user:
- The output file path
- A summary of conversions performed (number of admonitions converted, etc.)
- Remind them to review the article and commit when ready
Available Blog MDX Components
For reference, these are the custom MDX components available in the blog:
| Component | Purpose | Props |
|---|---|---|
<Note> | Supplementary note (注記) | title?: string (default: "注記") |
<Info> | Additional info/aside (備考) | title?: string (default: "備考") |
<InfoBox> | Highlighted info box | (children only) |
<Column> | Bordered column block | (children only) |
<Outro> | End-of-article section | (children only) |
<Youtube> | YouTube embed | (see component) |
<Img> | Image with caption | (see component) |
<ExImg> | Extended image | (see component) |
<ImgsGrid> | Image grid layout | (see component) |
<FlowRoot> | Float clearing container | (children only) |
<LayoutDivide> | Multi-column layout | (children only) |
<LayoutDivideItem> | Column item | (children only) |