Astro の src/ をどう分けたか

置き場所を決めないまま記事が増えて、公開した覚えのないページが本番に出ました。読み終えると、src/ をどう分けるか・部品を呼ぶ向きをどちらに固定するか・CSS の値をどこに書くかを、自分のサイトでも決められるようになります。

原因は、置き場所と、記事が公開されるまでの通り道を決めていなかったことです。

決めたのは 3 つです。置き場所と、部品を呼ぶ向きと、CSS の値を書く場所。どれも、事故か手戻りのあとに決めています。

src/ に何を置いているか

作ったファイルを置くフォルダは src/ ひとつで、その中を 7 つに分けています。

src/
  pages/       URL になる。ここにあるファイルの位置がそのままアドレス
  layouts/     ページの土台。ヘッダー・フッター・meta
  components/  画面の部品。題材ごと + どこでも使う shared/
  content/     記事とガイドの中身(テキストファイル)
  lib/         データの取得と計算。画面を持たない
  styles/      色と間隔の定義
  plugins/     文章を書き換える処理(この章では触りません)

Astro から借りているのは、pages / components / layouts / styles というよくある並びです。 URL になるのは src/pages だけで、ほかのフォルダ名は自分で決められます。

分け方の基準は 1 つだけ——同じ名前の組が、消す・持ち出す単位になることです。 たとえば pages/vspo、components/vspo、lib/vspo を同じ名前でそろえます。sf6 と lol も同じ形です。 そろわないものが 2 つあります。このガイドは URL の都合でページ側が pages/ai/ にあり、 components/shared/ は題材を持たない置き場なので組になりません。 Astro の慣習を借りた上で、この対応をそろえることは自分で決めました。

記事を 1 本足すと、何が動くか

冒頭の作りかけのページは、SF6 のものでした。本番に送ったのは別の記事で、それに巻き込まれて一緒に出ています。 下の関門は、そのあとに作ったものです。形の検査に使う content.config.ts は src/ の直下に 1 枚だけ置いてあります。

記事の .md content/articles/ 形を検査 content.config.ts 公開段階で絞る lib/visibility URL を作る pages/[category]/ HTML ができる dist/ 読み込む 形が合っていたら 出してよければ 書き出す
最後まで通って HTML になる
記事の .md content/articles/ 形を検査 content.config.ts 公開段階で絞る lib/visibility URL を作る pages/[category]/ HTML ができる dist/ 読み込む 形が合っていたら
ここで止まる。書きかけを置いたままでも本番は壊れない

いまは記事の先頭に書く visibility(local / staging / prod)で、本番に出してよいページだけを生成します。 出さないページは本番では 404 になり、検索エンジンに渡す一覧(sitemap)にも載りません。 入れたあと、作りかけの SF6 ページは確認用のサイト(staging)にだけ残り、本番からは消えました。

1 枚のページは、5 つの場所でできている

さきほどは、記事 1 本が公開されるまでの通り道でした。ここは、その先で 1 枚の画面が何から組み上がるかです。 書いたマークダウンから始めて、段を押しながら組み上げてみてください。

ページができるまで

段を押すと、右のページがその段階の姿になります

並べた順は「できあがる順」で、呼ぶ向きはその逆です。 pages が layouts を呼び、 layouts が components を呼び、components が lib からデータを取ります。入口はいつも pages の側です。

向きは 1 方向だけにしてあります。lib が components を呼び始めると、 どこから使われているか追えなくなるからです。まだ起きていません——起きてから直すと広い範囲を触ることになるので、 先に向きだけ決めました。通すだけの段は挟みません。pages が lib を直接呼ぶのは問題ありません。

この向きは機械的に確かめられて、2026 年 9 月時点で違反は 0 です。ただし自動では走りません。 検査するツールはサイトの外(.claude/skills/audit/arch-graph/)にあり、思い出したときに手で回しています。

色と余白は 1 か所で決めている

構造ではなく対比なので、ここは図ではなく表で足ります。並べたのは強さの順ではなく、効く範囲の広い順です。

どこに書くか何を持つか触るとどこまで効くか
値の置き場(トークン)色・間隔・文字サイズの値サイト全体
土台見出し・本文の既定サイト全体
ユーティリティ「余白 16px」のような、その場所だけに効く細かい指定使った場所だけ
部品ごとの CSSその部品にしか無い形その部品だけ

値を書いていいのは一番上だけにしてあります。そうしないと、同じ余白をどこで決めたのか分からなくなります。

ここは実際に踏みました。Tailwind を入れたとき、既存の CSS を全部レイヤー(優先順位のあるグループ)に入れ直すことになり、包み忘れた要素だけ、ページに書いた指定が効かなくなりました。 p-4(余白 16px を付ける指定)を書いても、その要素の <style> に padding: 20px が素のまま 1 行残っていると、 p-4 は永久に効きません。グループに入れ忘れた指定は、入っている指定に必ず勝ちます—— どちらが細かく書かれているか(詳細度)でも、書いた順でもなく、仕様としてそうなので、 ブラウザの開発者ツールを見ても理由が出てきません。

全ページの先頭に置いてある、たった 1 行 src/layouts/BaseLayout.astro
<style is:inline>@layer properties, theme, base, components, utilities;</style>

レイヤーの強さは「名前が最初に出てきた順」で決まります。 この 1 行が無いと、部品の CSS が先に名前を登録し、 あとから読み込まれる Tailwind 側が強くなって、サイト全体の見た目が崩れます。 1 行足りないだけで、原因の分からない崩れ方をする——だから先頭に固定しました。

包み忘れは scripts/check-layer-order.py で止めています。こちらは CI に載せてあるので、勝手に止まります。 このときの記録はTailwind CSS v4 に移行するまでに遠回りした話に書きました。

置き場所は「消す・持ち出す単位」で決める

持ち帰りは 1 つです。置き場所を「消す・持ち出す単位」で決めておけば、増えても追える。 名前をそろえるのは、そのための手段でしかありません。

いまの規模は、記事 16 本・ガイド 10 本・部品 58 個です(2026 年 9 月 12 日時点)。この大きさなら、Astro の慣習どおりの大枠と、同名の組でそろえる決めごとで持ちこたえています。ページ・部品・データの置き場所は追えます。

怪しくなっているのは、ページ・部品・レイアウトをまたぐ CSS です。部品ごとの <style> に、 その部品にしか無い形と、他とも共有している見た目が混ざったままのものが残っています。 どちらに寄せるかを 1 つずつ判断している途中で、形を増やす前にここをほどいていく必要があります。

置き場所が決まったあと、公開したものをどう見張っているかは公開したサイトを動かし続けるに書きました。