MDX Writing Rules
Rules for writing articles in MDX. Covers headings, lists, code blocks, emphasis, MDX components, and product link patterns.
このドキュメントは、MDXで記事を執筆する際の構造的なルールとコンポーネントの使い方をまとめたものです。文体や言葉遣いについては 執筆スタイル を参照してください。
基本的なMarkdown書式ルール(ヘッダーの前後の空行、コードブロックの言語指定など)については、ルートの CLAUDE.md を参照してください。
コンポーネントの完全なリファレンスは src/mdx/notes/--modules.mdx を参照してください。
Headings and Emphasis
Never Use Bold as Section Headings
太字(**text**)やイタリック(*text*)は、文中のインライン強調にのみ使用する。セクションタイトルには必ず見出し(##、###、####)を使う。
<!-- ❌ Bad: 太字を見出しとして使用 -->
**セクションタイトル:**
- リスト項目
- リスト項目
<!-- ✅ Good: 適切な見出しを使用 -->
### セクションタイトル
- リスト項目
- リスト項目
Never Use Bold as List Item Headers
リスト項目の先頭で太字をヘッダー代わりに使わない。
<!-- ❌ Bad: 太字をリストヘッダーとして使用 -->
- **新規フィッティング実行**
- ユーザーが新しいフィッティングを実行したとき
- バッジの非表示状態がリセットされる
- **localStorageクリア**
- ブラウザキャッシュのクリア
- プライベートブラウジングモード
<!-- ✅ Good: プレーンテキストでリスト項目を記述 -->
- 新規フィッティング実行
- ユーザーが新しいフィッティングを実行したとき
- バッジの非表示状態がリセットされる
- localStorageクリア
- ブラウザキャッシュのクリア
- プライベートブラウジングモード
<!-- ✅ Good: インライン強調として太字を使用 -->
- ユーザーが**新規フィッティング**を実行すると、バッジの非表示状態がリセットされる
- ブラウザキャッシュのクリアや**プライベートブラウジングモード**ではlocalStorageがクリアされる
Never Use Bold in Specification Lists
製品仕様セクションでは、項目ラベルに太字を使用しない。太字は強調したい内容にのみ使用する。
<!-- ❌ Bad: 仕様リストで太字 -->
#### 基本仕様
- **フォーマット**: Eurorack
- **サイズ**: 26HP
- **奥行き**: 25mm
- **消費電力**: +12V 290mA(最大)
<!-- ✅ Good: プレーンテキストの仕様リスト -->
#### 基本仕様
- フォーマット: Eurorack
- サイズ: 26HP
- 奥行き: 25mm
- 消費電力: +12V 290mA(最大)
<!-- ✅ Good: 文中での強調 -->
本製品の**消費電力が非常に低い**ことが特徴です。
Bold in Japanese Text Requires Care
日本語文中で太字(**text**)を使用する際、太字の前後が日本語文字に直接隣接していると、MDXパーサーが正しく認識できずに**がそのまま表示されてしまうことがある。
<!-- ❌ Bad: 太字が日本語文字に直接隣接 -->
それが**構文解析**して**AST**という形式に変換し
<!-- ✅ Good: 鉤括弧を使用(技術用語の導入に適切) -->
それが「構文解析」して「AST」という形式に変換し
<!-- ✅ Good: 文の区切りで太字を使用 -->
これを**構文解析**と呼びます。**AST**という形式に変換します。
<!-- ✅ Good: 太字の前後に句読点や括弧がある -->
方法があります。それが**構文解析(パース)**です。
対処法:
- 技術用語の導入には鉤括弧「」を使用する(日本語として自然)
- 太字を使う場合は、文の先頭や末尾、または句読点の直後に配置する
- 太字の後ろに助詞(が、を、に、は等)が続く場合は特に注意
Avoid Deep Heading Nesting
記事は文字数に制限があり、ブログのようなスタイルで、超長編のストーリーは含まない。長くなる場合は2〜3本の記事に分割すべきである。そのため、深くネストした見出し構造は基本的に避ける。
基本ルール:
- 基本的にh2を使う
ただし、h3、h4、h5の使用を禁止するわけではない。
たとえば、以下のような見出し構造の記事があったとする。
## 大きなセクション
### サブセクション1
内容...
### サブセクション2
内容...
### サブセクション3
内容...
### サブセクション4
内容...
このh2セクションは長すぎる印象がある。このような場合、見出しレベルを調整することを検討する。
## 大きなセクション
内容...
## サブセクション1
内容...
## サブセクション2
内容...
## サブセクション3
内容...
## サブセクション4
内容...
文章が不自然でなければ、多くの場合このほうが読みやすい。
List Rules
Never Mix Ordered and Unordered Lists
同じコンテンツ構造内で、番号付きリスト(ol)と箇条書きリスト(ul)を混在させない。
<!-- ❌ Bad: リストタイプの混在 -->
1. **項目1**: 説明
- サブ項目1-1
- サブ項目1-2
2. **項目2**: 説明
- サブ項目2-1
<!-- ✅ Good: 一貫した箇条書きリスト -->
- 項目1: 説明
- サブ項目1-1
- サブ項目1-2
- 項目2: 説明
- サブ項目2-1
Never Put Code Blocks Inside Lists
リスト項目の中にコードブロックを配置しない。コードブロックはリストの外に、適切なコンテキストとともに配置する。
<!-- ❌ Bad: リスト内のコードブロック -->
- LayoutDivide: 2カラムレイアウトコンポーネント
```jsx
<LayoutDivide>
<LayoutDivideItem>左カラム</LayoutDivideItem>
<LayoutDivideItem>右カラム</LayoutDivideItem>
</LayoutDivide>
```
- LayoutDivide: 2カラムレイアウトコンポーネント
<LayoutDivide>
<LayoutDivideItem>左カラム</LayoutDivideItem>
<LayoutDivideItem>右カラム</LayoutDivideItem>
</LayoutDivide>
- Column: コンテンツ用の単一カラムラッパー
Use Hyphens for Unordered Lists
箇条書きはハイフン(-)を使用(*や+は使わない)。階層は2スペースでインデント。
- 第1階層の項目
- 第2階層の項目
- 第3階層の項目(3階層までに留める)
- 別の第2階層項目
- 次の第1階層項目
Numbered Lists vs Headings
コンテンツの複雑さに応じて、番号付きリストと見出しを使い分ける。
Simple Content → Numbered List
#### メリット
1. メンテナンス性の向上 - スタイルの差別化が容易
2. 効率的なレビュー - シンプルなバリデーション
3. 素早い問題解決 - 明確な防御策
Complex Content (Code Blocks, Multiple Paragraphs) → Headings
## 使用方法
### 1. HTMLマークアップ
```html
<div id="app"></div>
```
### 2. 初期化
```js
myLibrary.init({
/* ... */
});
```
Avoid Empty Consecutive Headings
見出しの間には必ず内容を入れる。内容がない場合は番号付きリストを使う。
<!-- ❌ Bad: 内容のない連続見出し -->
### 1. 条件を追加
### 2. 型をインポート
### 3. 設定を返す
<!-- ✅ Good: シンプルなリストに変換 -->
1. 条件を追加
2. 型をインポート
3. 設定を返す
Horizontal Rules (hr)
水平線(---)は、コンテンツの大きな区切りにのみ使用する。
When NOT to Use
- セクション(h2)の区切りとして使用しない
- h2やh3の見出しがある場合、それ自体がセクションの区切りを示すため、水平線は不要
<!-- ❌ Bad: h2の前に水平線は不要 -->
---
## セクション1
内容...
---
## セクション2
内容...
<!-- ✅ Good: h2だけでセクションは区切られる -->
## セクション1
内容...
## セクション2
内容...
When to Use
- 記事内で大きく話題が変わる場合(章をまたぐような区切り)
- 付録や補足情報を本文と明確に分離する場合
- 連載記事の「次回予告」などを本文と分ける場合
## 本文の最後のセクション
本文の内容...
---
## 次回予告
次回は〜について解説します。
Code Blocks
Always Specify Language
コードブロックには必ず言語を指定する。
| 言語/形式 | 識別子 | 使用場面 |
|---|---|---|
| TypeScript | typescript, ts | .ts, .tsx ファイル |
| JavaScript | javascript, js | .js, .jsx ファイル |
| JSON | json | 設定ファイル、データ |
| Markdown | markdown, md | ドキュメント例 |
| Bash | bash, sh | シェルコマンド |
| CSS | css | スタイルシート |
| YAML | yaml, yml | 設定ファイル |
| JSX | jsx | Reactコンポーネント例 |
Code Comments Should Be in Japanese
コードブロック内のコメントは日本語で記述する。
// ✅ 良い例: 適切なインデントとコメント
interface Product {
id: string; // 商品ID(UUID形式)
name: string; // 商品名
price: number; // 価格(税込)
// オプショナルフィールド
description?: string;
imageUrl?: string;
}
Image Alt Text
Use Numbered Format for Product Photos
商品写真などの複数画像を掲載する際、alt属性には番号付き形式を使用する。詳細な説明文を作成するのは労力がかかるため、シンプルな番号付け形式を採用する。
<!-- ❌ Bad: 詳細すぎる -->
<ImgsGrid
srcs={['product-photo-01', 'product-photo-02', 'product-photo-03']}
alts={['製品フロントパネル', '製品接続端子', '製品サイド']}
/>
<!-- ❌ Bad: すべて同じ -->
<ImgsGrid
srcs={['product-photo-01', 'product-photo-02', 'product-photo-03']}
alts={['商品写真', '商品写真', '商品写真']}
/>
<!-- ✅ Good: 番号付き -->
<ImgsGrid
srcs={['product-photo-01', 'product-photo-02', 'product-photo-03']}
alts={['商品写真1', '商品写真2', '商品写真3']}
/>
理由:
- コンテンツ作成の効率化(詳細な説明文を考える時間を削減)
- 一貫性の維持(すべての画像で同じパターンを使用)
- 最低限のアクセシビリティ確保(完全に同じテキストよりは識別可能)
URLs in Japanese Text
日本語文中にURLを含める際、GitHubが誤ってオートリンクしてしまうインラインURLは避ける。
Pattern 1: Separate URL in List
URLが補足情報の場合:
<!-- ✅ Good: 箇条書きで分離 -->
サイト名において、問題が発生していました。
- サイト名
- https://example.com/path/to/page
Pattern 2: Markdown Link Format
URLが文の流れに組み込まれる場合:
<!-- ✅ Good: Markdownリンク形式 -->
[サイト名](https://example.com/path/to/page)において、問題が発生していました。
Avoid This Pattern
<!-- ❌ Bad: 括弧内の生URL(GitHubが誤ってオートリンクする) -->
サイト名(https://example.com/path/to/page)において、問題が発生していました。
Link Text Best Practices
Good Examples
✅ 良い例:
- 詳細は[インストールガイド](./install-guide.md)を参照してください。
- [OXI ONE MKII 商品詳細ページ](oxi-one-mk2-black)で仕様を確認できます。
- GitHubの[コントリビューションガイドライン](https://github.com/...)をお読みください。
Bad Examples
❌ 悪い例:
- 詳細は[こちら](./install-guide.md)。
- [クリック](oxi-one-mk2-black)して商品を見る。
- ガイドラインは[https://github.com/example/repo/...](https://github.com/...)を参照。
Why These Rules Matter
これらの構造的ルールは、単なるスタイルの好みではなく、セマンティックHTMLとアクセシビリティに基づいている。
- 太字・イタリックはインライン強調用: HTMLでは
<strong>と<em>タグに変換される。これらは文中の強調用であり、見出しとして使うとセマンティック構造が壊れる - 適切な見出しはドキュメント階層を作る: 見出し(
##、###、####)は目次生成やスクリーンリーダーのナビゲーションに使用される。太字を見出し代わりに使うと、これらの機能が正しく動作しない - リストタイプの混在は視覚的階層を乱す: 番号付きリストと箇条書きリストを混在させると、読者にとって情報の優先度や関係性が不明確になる
- アクセシビリティへの配慮: スクリーンリーダーは見出しやリストの構造に依存してドキュメントをナビゲートする。正しい構造は視覚障害を持つ読者にとって特に重要
MDX Components
記事(src/mdx/notes/)で使用できるMDXコンポーネントの使い方。
Image Components
ImgsGrid - Multiple Images in Grid Layout
複数の画像をグリッドレイアウトで表示する。
<ImgsGrid
srcs={[
'/images/p/oxi-one-mk2/600w.webp',
'/images/p/oxi-one-mk2/900w.webp',
]}
alts={['商品写真1', '商品写真2']}
divide={2} // 2列表示
extraWide={true} // 幅広表示
captions={['前面パネル', '背面接続部']}
/>
Props:
srcs: 画像URLの配列alts: alt属性の配列(番号付き形式推奨:「商品写真1」「商品写真2」)divide: 列数(2, 3など)extraWide: 幅広表示フラグcaptions: キャプションの配列(オプション)
ExImg - Single Image with Positioning
単体画像を配置オプション付きで表示する。
// 右寄せフロート画像
<ExImg
src="/images/p/module-example/900w.webp"
alt="モジュールの接続例"
floatRight={true}
className="mb-4"
/>
// 幅広画像
<ExImg
src="/images/p/system-overview/1600w.webp"
alt="システム全体図"
extraWide={true}
overFlowed={true}
/>
Props:
src: 画像URLalt: alt属性floatRight: 右寄せフロートfloatLeft: 左寄せフロートextraWide: 幅広表示overFlowed: コンテナからはみ出す表示className: 追加CSSクラス
Image Path Convention
画像は /images/p/[slug]/ ディレクトリから配信される。各製品やコンテンツごとに以下のバリアントが用意されている:
| ファイル名 | 用途 | サイズ |
|---|---|---|
600w.webp | モバイル表示 | 幅600px |
900w.webp | タブレット表示 | 幅900px |
1200w.webp | デスクトップ表示 | 幅1200px |
1600w.webp | 大画面表示 | 幅1600px |
2000w.webp | 高解像度表示 | 幅2000px |
ogp.jpg | OGP画像 | 1200x630 |
mercari.png | メルカリ用 | 幅1600px |
画像はビルド時に自動的に最適化され、レスポンシブ表示に対応する。MDXコンポーネントが適切なサイズを自動選択する。
Layout Components
LayoutDivide - Two-Column Layout
2カラムレイアウトでコンテンツを配置する。
<LayoutDivide>
<LayoutDivideItem>
### 左カラム
左側のコンテンツをここに記述。
Markdownも使用可能です。
</LayoutDivideItem>
<LayoutDivideItem>
### 右カラム
右側のコンテンツをここに記述。
画像やコードブロックも配置できます。
</LayoutDivideItem>
</LayoutDivide>
Column - Content Wrapper
コンテンツをラップする単一カラムコンポーネント。
<Column>
<h3>セクションタイトル</h3>
<p>段落のコンテンツ...</p>
<ul>
<li>リスト項目1</li>
<li>リスト項目2</li>
</ul>
</Column>
Content Components
YouTube Embed
YouTube動画を埋め込む。
<Youtube url="https://www.youtube.com/watch?v=VIDEO_ID" />
// プレイリストの場合
<Youtube url="https://www.youtube.com/playlist?list=PLAYLIST_ID" />
InfoBox - Information Callout
重要な情報やお知らせを目立たせる。
<InfoBox>
⚠️ **重要なお知らせ**
この製品は限定生産です。在庫状況は[商品ページ](product-slug)でご確認ください。
</InfoBox>
Outro - Article Conclusion
記事の締めくくりに使用する。
<Outro>
本記事で紹介した製品の詳細は、各商品詳細ページをご覧ください。
ご質問がございましたら、お気軽にお問い合わせください。
</Outro>
MercariNav - Product Navigation
商品ナビゲーションを表示する。
<MercariNav
items={[
{
imgSrc: 'https://example.com/product1.jpg',
title: 'OXI ONE MKII',
href: 'oxi-one-mk2-black',
cropMode: 'center'
},
{
imgSrc: 'https://example.com/product2.jpg',
title: 'OXI Pipe MKII',
href: 'oxi-pipe-mk2',
cropMode: 'top'
}
]}
/>
Product Link Patterns
Always Use Product Slugs
製品詳細ページへのリンクは、フルパスではなく製品slugを使用する。システムがビルド時に自動的に正しいURLに変換する。
// パターン1: フルネーム + 説明
[OXI ONE MKII 商品詳細ページ](oxi-one-mk2-black)
// パターン2: 短縮形
[OXI ONE MKII](oxi-one-mk2-black)の詳細はこちら
// パターン3: 文中での使用
シーケンサーの[OXI ONE MKII](oxi-one-mk2-black)は、64ステップの...
Why use slugs:
- Future-proof: Product page paths may change, but slugs remain constant
- Build-time resolution: System automatically finds correct path from master data
- Consistency: All product links follow the same pattern
- Maintainability: If URL structure changes, only build system needs updating
Common Patterns
Product Introduction
<LayoutDivide>
<LayoutDivideItem>
## 製品概要
OXI ONE MKIIは革新的なシーケンサーです。
### 主な特徴
- 64ステップシーケンス
- 4トラック同時再生
- CV/Gate出力
</LayoutDivideItem>
<LayoutDivideItem>
<ExImg
src="/images/p/oxi-one-mkii/900w.webp"
alt="OXI ONE MKII"
/>
</LayoutDivideItem>
</LayoutDivide>
<InfoBox>
詳細は[OXI ONE MKII 商品詳細ページ](oxi-one-mk2-black)をご覧ください。
</InfoBox>
Tutorial with Video and Images
## セットアップ手順
<Youtube url="https://youtube.com/watch?v=TUTORIAL_ID" />
### 1. 接続
<ImgsGrid
srcs={[
'/images/p/setup-step1/1200w.webp',
'/images/p/setup-step2/1200w.webp',
]}
alts={['商品写真1', '商品写真2']}
captions={['電源を接続', 'パッチケーブルを接続']}
divide={2}
/>
<Outro>
セットアップが完了したら、[クイックスタートガイド](./quick-start)に進んでください。
</Outro>
Related Articles
<InfoBox>
### 関連記事
- [モジュラーシンセの基礎](./modular-basics)
- [パッチングガイド](./patching-guide)
- [メンテナンス方法](./maintenance)
</InfoBox>