AI Cowork Lab
【実験ログ】1つのAstroテンプレートで4サイトを量産した設計戦略
実験ログ 約40分で読めます

【実験ログ】1つのAstroテンプレートで4サイトを量産した設計戦略

同じようなサイトを複数作るとき、毎回ゼロから作るのは大変ですよね。かといって、1つのサイトに全部詰め込むのも違う。ジャンルが違えば、デザインも読者層も異なります。

この実験ログでは、1つのAstro(Webサイトを作るための道具。表示が速いのが特徴)テンプレートを作って、それをコピーして4つの異なるサイトを立ち上げた全過程を書いていきます。何を共通にして、何をサイトごとに変えたのか。どこで迷って、どこで失敗したのか。そしてこのやり方の限界と、将来の改善案まで。

テンプレートの使い回しというと「かんたんそう」に聞こえますが、実際にやってみると設計上の判断ポイントが多いです。この記録が、同じことをやりたい誰かの参考になれば嬉しいです。


課題: サイトを作るたびに同じ作業を繰り返すのはツラい

最初にtrip-journal.netを作ったとき、約5時間かかりました。レイアウト、パーツ、CSS、公開設定…全部ゼロから作ったからです。

次のサイトも同じ5時間かかるとしたら、4サイトで20時間。これは個人の副業としてはキツいです。しかも4サイトの構造はほぼ同じ。ヘッダー、フッター、記事カード、カテゴリ一覧…共通する部分がめちゃくちゃ多いんです。

じゃあ、何が違うのか。冷静に分析してみました。

「変わるもの」と「変わらないもの」を分けよう

  • 変わらないもの(共通パーツ): ヘッダー、フッター、カード、Callout、ベースレイアウト、ビルド設定、Tailwind設定
  • 変わるもの(サイトごとに違う部分): サイト名、色、カテゴリ構成、ナビゲーション、トップページのメインビジュアル、記事コンテンツ

変わるものを1つのファイルにまとめれば、そのファイルだけ書き換えるだけで別サイトになる。

つまり、これがsite.tsアーキテクチャの出発点です。

時間の節約効果

ゼロから作る場合: 5時間 x サイト数

テンプレート方式: 5時間(初回だけ) + 1〜2時間 x 残りのサイト数

4サイトの場合、ゼロからなら20時間。テンプレート方式なら5 + 2 x 3 = 11時間。約45%の時間削減です。サイトが増えれば増えるほど、テンプレート方式の有利さは増していきます。


テンプレートの全体像

テンプレートの構造は、「共通パーツの層」と「サイトごとに違う層」の2層になっています。

共通パーツの層(全サイトで使い回す)
Header.astro
Footer.astro
Card.astro
Callout.astro
BaseLayout.astro
CategorySection.astro
Sidebar.astro
PostLayout.astro
↓ 参照している ↓
サイトごとに違う層(ここだけ書き換える)
site.ts
global.css
index.astro(トップ)
content/posts/*

共通パーツには、サイト名や色を直接書き込んでいません。サイト名はsite.tsから、色はCSS変数から取得するようにしています。だからコピーしても修正なしでそのまま動くんです。

サイトごとに違う層は、4つのファイル(または4つの領域)に限定されています。新しいサイトを作るとき、触るのはここだけです。


設計の中核: site.ts を詳しく見てみよう

すべての「サイトごとに違う情報」をsrc/config/site.tsというファイルに集約しました。かんたんに言うと、「このファイルがサイトの設定書」です。ここを書き換えるだけで、別のサイトに早変わりします。

site.tsの中身

// src/config/site.ts
export const siteConfig = {
  // ── 基本情報 ──
  name: "AI Cowork Lab",
  tagline: "AIと一緒に、仕事をもっと面白く。",
  description: "Claude Code・AI業務活用の実践ガイド。業務効率化からコード生成まで、AIとの協働を実験・検証する。",
  url: "https://ai-cowork-lab.com",

  // ── 色 ──
  colors: {
    primary: "#0d9488",     // teal-600(メインカラー)
    primaryDark: "#0f766e", // teal-700(メインカラーの暗い版)
    accent: "#f59e0b",      // amber-500(アクセントカラー)
    accentDark: "#d97706",  // amber-600(アクセントカラーの暗い版)
  },

  // ── ナビゲーション(メニューに何を並べるか) ──
  nav: [
    { label: "Claude Code", href: "/category/claude-code" },
    { label: "業務活用", href: "/category/業務活用" },
    { label: "実験ログ", href: "/category/実験ログ" },
  ],

  // ── カテゴリ設定 ──
  categories: {
    "claude-code": {
      title: "Claude Code",
      description: "基本操作から実践テクニックまで",
      layout: "steps",  // 学習系: 順番に読んでいくスタイル
      icon: "terminal",
    },
    "業務活用": {
      title: "業務活用",
      description: "日常業務でのAI活用事例",
      layout: "grid",   // メディア系: 好きなものから読むスタイル
      icon: "briefcase",
    },
    "実験ログ": {
      title: "実験ログ",
      description: "試したこと・学んだことの記録",
      layout: "grid",
      icon: "flask",
    },
  },

  // ── フッター ──
  footer: {
    copyright: "AI Cowork Lab",
    links: [
      { label: "プライバシーポリシー", href: "/privacy" },
      { label: "お問い合わせ", href: "/contact" },
    ],
  },
};

site.tsで何をコントロールしているか

サイトの名前まわり
  • サイト名・キャッチコピー
  • URL・SNSシェア設定
  • サイト説明文
見た目
  • メインカラー
  • アクセントカラー
  • 暗めバリアント
サイト構造
  • ナビゲーション項目
  • カテゴリ名・説明・アイコン
  • カテゴリの表示スタイル(グリッド/ステップ)
その他の情報
  • フッターのリンク
  • 著作権表示
  • SEO初期値

共通パーツからsite.tsをどう使っているか

具体例を見てみましょう。ヘッダーのパーツはこんな感じです。

---
// Header.astro
import { siteConfig } from '../config/site';
---

<header class="bg-primary text-white">
  <nav>
    <a href="/" class="font-bold text-xl">{siteConfig.name}</a>
    <ul>
      {siteConfig.nav.map(item => (
        <li><a href={item.href}>{item.label}</a></li>
      ))}
    </ul>
  </nav>
</header>

ここがポイントなんですが、Header.astroの中に「AI Cowork Lab」とか「Claude Code」といった文字列が一切書かれていません。全部site.tsから読み込んでいます。つまり、site.tsを書き換えるだけで、ヘッダーの表示内容が自動的に変わるということです。


CSS変数で色を管理する ── Tailwind CSS v4の活用

Tailwind CSS(デザインをかんたんに当てられるCSSの道具)v4では@themeという仕組みでCSS変数を定義できます。これを使って、site.tsの色をサイト全体に反映する仕組みを作りました。

global.cssの色の設定

@import "tailwindcss";

@theme {
  /* サイトごとに変更する部分(ここだけ変える) */
  --color-primary: #0d9488;    /* teal-600 */
  --color-primary-dark: #0f766e;
  --color-accent: #f59e0b;     /* amber-500 */
  --color-accent-dark: #d97706;

  /* 共通の色(変更不要) */
  --color-text: #1e293b;
  --color-text-light: #64748b;
  --color-bg: #ffffff;
  --color-bg-alt: #f8fafc;
  --color-border: #e2e8f0;
}

サイトごとに変えるのは--color-primary--color-accent4行だけです。Tailwind v4ではこのCSS変数がそのままクラス名として使えるので、bg-primarytext-accentborder-primaryといった書き方がそのまま動きます。かんたんに言うと、4行変えるだけでサイト全体の色が変わるということです。

4サイトのカラーパレット

trip-journal
Navy #1a365d
Red #e53e3e
vibe-code-lab
Purple #6b21a8
Green #16a34a
ai-cowork-lab
Teal #0d9488
Amber #f59e0b
ceo-tax
Blue #1e40af
Red #ef4444

色の選び方にもルールを作りました。メインカラーは「落ち着いた色(濃いめ)」、アクセントカラーは「目を引く色(明るめ)」を組み合わせるようにしています。メインカラーはヘッダーやリンクに使われて、アクセントカラーはボタンやハイライトに使われるので、この組み合わせが見やすさとバランスを取ってくれます。


カテゴリページの表示を切り替える ── サイトの性質で変える

全サイトで同じカテゴリページパーツ(CategorySection)を使っていますが、表示のしかたはサイトの性質に応じて切り替えています。ここがテンプレート設計で一番悩んだポイントの一つです。

パターン1: カードグリッド(ニュース・メディア系サイト向け)

trip-journal.net / ai-cowork-lab.com(実験ログ) / ceo-tax.com で使用

記事タイトル1

記事タイトル2

記事タイトル3

新着順に表示。読者は興味のある記事を好きなように選んで読むスタイル。

パターン2: ステップカード(学習・入門系サイト向け)

vibe-code-lab.com / ai-cowork-lab.com(Claude Code入門) で使用

1 Step 1: バイブコーディングとは?

2 Step 2: 環境構築

3 Step 3: 最初のプロジェクト

順番通りに並んでいて、上から順に読み進める設計。学習の流れに沿って表示されます。

どっちを使うかの判断基準

この2パターンの使い分けには、はっきりした基準があります。

  • グリッド表示: 記事同士に読む順番がない場合。どの記事から読んでも大丈夫なコンテンツ。ニュース、レビュー、事例紹介など
  • ステップ表示: 記事に学習順序がある場合。前の記事を読んでないとわかりにくいコンテンツ。チュートリアル、入門ガイド、ロードマップなど

切り替えはsite.tsのcategories設定でlayout: "steps"layout: "grid"を書くだけ。パーツ側が自動で判断してくれます。

// CategorySection.astro の切り替えロジック
const categoryConfig = siteConfig.categories[slug];
const layout = categoryConfig?.layout || "grid";

// 表示スタイルに応じて並び順も変わる
const sorted = layout === "steps"
  ? posts.sort((a, b) => (a.data.order ?? 99) - (b.data.order ?? 99))
  : posts.sort((a, b) => b.data.date.getTime() - a.data.date.getTime());

並び順が違う点に注目してください。ステップ表示ではorderで明示的に順番を決めて、グリッド表示では新しい日付が先に来ます。この小さな切り替えが、サイトの使い勝手に大きく影響するんです。

💡

同じサイトの中でもパターンを混ぜて使える

ai-cowork-lab.comでは「Claude Code」カテゴリはステップ表示(入門→応用の順序がある)、「実験ログ」カテゴリはグリッド表示(新着順で好きなものを読む)にしています。つまり、サイト単位じゃなくてカテゴリ単位で切り替えられるのが、この設計の強みです。


4サイトの構成比較

テンプレートから生まれた4サイトを一覧で比較してみましょう。

サイトテーマメインカラーアクセントカラーカテゴリ数表示スタイル記事数
trip-journal.net旅行・おでかけNavy #1a365dRed #e53e3e2(国内/海外)グリッド11本
vibe-code-lab.comバイブコーディング入門Purple #6b21a8Green #16a34a3(入門/ツール/実践)ステップ15本
ai-cowork-lab.comAI業務活用Teal #0d9488Amber #f59e0b3(Claude Code/業務活用/実験ログ)混在9本
ceo-tax.com経営者向け税金Blue #1e40afRed #ef44443(税金/節税/経理)グリッド15本

4サイトのジャンルはバラバラですが、技術的な仕組みは完全に同じです。Astro + Tailwind CSS v4 + Cloudflare Pages(GitHubと連携してサイトを無料で公開できるサービス)。この統一性が、運用をラクにしてくれています。


パーツの使い回しを検証する

そのまま使えたパーツ(修正ゼロ)

テンプレートをコピーしたとき、一行も直さずにそのまま動いたパーツたちです。

パーツ役割なぜ修正不要だったか
Callout.astro注意書きやポイントのボックスサイト固有の色を使ってないから
Card.astro記事カードの表示CSS変数でサイトの色が自動で変わるから
Footer.astroフッターsite.tsの設定を読んでいるから
Header.astroヘッダー・メニューsite.tsのメニュー設定を読んでいるから
CategorySection.astroカテゴリ別記事一覧site.tsのカテゴリ設定を見て動くから
BaseLayout.astro共通レイアウト(head, metaタグ)SEO設定もsite.tsから読むから
Sidebar.astroサイドバーsite.tsのカテゴリから動的に生成するから

7つのパーツが修正ゼロで動きました。これは、設計の段階で「site.tsかCSS変数からしか値を取らない」というルールを徹底した成果です。つまり、パーツの中にサイト名や色を直接書き込まなかったおかげで、コピーするだけで別サイトの顔になってくれたということです。

カスタマイズが必要だったパーツ

パーツ理由何をしたか
index.astro(トップページ)サイトのコンセプトごとにHTMLの構造自体が違うメインビジュアル、ボタン、セクション構成を全面書き換え
SpotCard.astro旅行サイト専用のお店紹介パーツ他サイトでは削除
Timeline.astro旅行サイト専用の行程表示パーツ他サイトでは削除
ℹ️

使い回しやすいパーツを作るコツ

パーツの中にサイト固有の文字列や色を直接書かないこと。必ずsite.tsかCSS変数を経由して取得するようにします。これだけで、コピー時の修正箇所が激減します。「このパーツを別のサイトにコピーしてもちゃんと動くかな?」と常に自分に問いかけるのが、良い設計につながります。


トップページの問題 ── 唯一の手動カスタマイズが必要な場所

ヘッダー、フッター、記事ページは全サイト共通のパーツで動きます。でもトップページだけは、サイトごとにがっつり書き換える必要がありました

旅行サイトのトップページ

  • 大きなメインビジュアル + 「旅の記録を、もっと身近に。」のコピー
  • 地域別のカード(国内/海外)
  • 最新記事一覧

学習サイトのトップページ

  • ロードマップ型のステップ表示
  • 「Step 1 → Step 2 → Step 3」の学習フロー
  • カテゴリ別の入り口(入門 / ツール / 実践)

AI活用サイトのトップページ

  • 「AIと一緒に、仕事をもっと面白く。」のコピー
  • 3カテゴリへの導線(Claude Code / 業務活用 / 実験ログ)
  • 最新の実験ログをハイライト表示

税金サイトのトップページ

  • 信頼性を重視したシンプルなデザイン
  • 「経営者のための税金ガイド」のコピー
  • 3カテゴリへの導線(税金 / 節税 / 経理)

トップページの構造はsite.tsだけでは対応しきれません。メインビジュアルのHTML構造自体がサイトごとに違うからです。旅行サイトは画面いっぱいの画像を使い、学習サイトはステップ型のUIを使い、税金サイトはテキスト中心のシンプルな構成。ここは毎回手で書き換える必要がありました。

改善案: トップページもパターン化する

// site.ts にトップページのタイプを追加する案
topPage: {
  type: "media" | "learning" | "blog",
  hero: {
    title: "AIと一緒に、仕事をもっと面白く。",
    subtitle: "Claude Code・AI業務活用の実践ガイド",
    image: "https://images.unsplash.com/...",
    cta: { label: "始める", href: "/category/claude-code" },
  },
}

こうすれば、トップページのパーツ内でtypeに応じて自動で表示を切り替えられます。media型はカードグリッド、learning型はステップフロー、blog型は最新記事一覧。かんたんに言うと、トップページも設定ファイルだけで変えられるようにしよう、という案です。次の改善で実装予定です。


コピー運用のリアルと限界

コピーでうまく回っている理由

今のところ4サイトなら、コピー運用で問題なく回せています。その理由は:

  1. サイト間でパーツの違いがほぼない ── 使い回しやすい設計ができているので、7割のパーツが修正不要
  2. バグ修正の頻度が低い ── 安定稼働に入れば、テンプレートの修正はまれ。週に1回あるかないか
  3. 4サイト程度なら手動コピーで十分 ── 10分で全サイトに修正を反映できる

コピーが厳しくなる条件

でも、以下のどれかに当てはまったら、コピー運用は限界を迎えます。

  1. サイト数が10以上になる ── 手動コピーの手間が無視できなくなる。1箇所の修正を10サイトにコピーするのは、ミスの温床
  2. 共通パーツの更新が頻繁になる ── 週3回以上の修正が入ると、コピー作業だけで毎週1時間消費する
  3. サイトごとの独自カスタマイズが増える ── パーツに「このサイトのときだけ」的な分岐が入り始めたら危険信号
  4. チームで開発する ── 「どのサイトが最新版か」がわからなくなる

「コピーの落とし穴」 ── 実際に起きた問題

Callout.astroの余白を調整したとき、4サイト全部に同じ修正を入れる必要がありました。trip-journalで修正 → vibe-code-labにコピー → ai-cowork-labにコピー → ceo-taxにコピー。この4回のコピーのうち、1回でもファイルを間違えると古いバージョンが残ります。

実際に、ceo-taxにコピーし忘れて、1日気づかなかったことがあります。見た目にはほぼ影響ないレベルの違いでしたが、「いつか大きなバグで同じことが起きたら」と思うと、もっとちゃんとした仕組みが必要だなと感じました。


将来の構想: モノレポ化

コピー運用の限界が見えてきたので、将来のやり方としてモノレポ(複数のプロジェクトを1つのフォルダで管理する方法)を検討しています。

project-root/
├── packages/
│   └── shared/              ← 共通パーツをまとめたフォルダ
│       ├── components/
│       │   ├── Callout.astro
│       │   ├── Card.astro
│       │   ├── Header.astro
│       │   ├── Footer.astro
│       │   ├── Sidebar.astro
│       │   └── CategorySection.astro
│       ├── layouts/
│       │   └── BaseLayout.astro
│       └── package.json

├── sites/
│   ├── trip-journal/        ← サイト固有: site.ts + 記事 + トップページ
│   │   ├── src/config/site.ts
│   │   ├── src/content/posts/
│   │   ├── src/pages/index.astro
│   │   └── astro.config.mjs
│   ├── vibe-code-lab/
│   ├── ai-cowork-lab/
│   └── ceo-tax/

├── package.json             ← 全体の設定
└── turbo.json               ← 並列ビルドの設定

モノレポにすると何が嬉しいのか

  • 共通パーツを1回直せば全サイトに反映される: コピー漏れが原理的に起きない。これが一番大きいメリット
  • 全サイトを一括ビルド: コマンド一発で全部まとめてビルドできる
  • パッケージの更新も一元管理: 1回の操作で全サイトの依存関係を更新
  • 何が共通で何が固有か一目瞭然: フォルダ構成を見るだけでわかる

モノレポの課題

ただし、モノレポにも課題はあります。

  • Astroのパーツをパッケージとして読み込めるか: 技術的に検証が必要
  • Cloudflare Pagesのビルド設定: サイトごとにルートフォルダを指定する必要がある
  • 移行作業のコスト: 今ある4サイトをモノレポに移す作業自体に半日〜1日かかる
ℹ️

今はコピーで十分

4サイト程度ならコピーで十分回せます。モノレポ化するのは、サイト数が8〜10を超えたときか、パーツの修正が頻繁に必要になったとき。つまり、「今は必要ないけど、将来必要になるかも」という段階です。必要になったときに作ればいいんです。


コピー時のよくあるハマりポイント

これから同じことをやる人のために、実際にハマったポイントを具体的に書いておきます。

ハマり1: node_modulesのコピーは壊れる

一番よく起きる問題です。フォルダをまるごとコピーすると、npm(プログラミングのパーツをインストールするための道具)でインストールしたファイルのリンクが壊れます。

# 必ずやること
rm -rf node_modules
rm -f package-lock.json
npm install

症状: 開発サーバーは起動するけど、特定のファイルの読み込みでエラーが出る。または、ファイルを変更しても自動反映されない、ビルドが途中で止まる、など。

⚠️

node_modulesのコピーは「静かに壊れる」のが厄介

完全に動かなくなるなら気づきやすいんですが、「80%動いて20%だけおかしい」という状態になりがちです。原因を探すのに時間がかかるので、コピー後は問答無用で削除→再インストールが正解です。

ハマり2: .gitフォルダの衝突

コピー元の.gitがそのまま残ると、GitHub(Gitのデータを保存するクラウドサービス)へのpush時に「もう存在するリポジトリ」としてエラーになります。あるいは、間違えて元のリポジトリにpushしてしまう危険もあります。

rm -rf .git
git init
git remote add origin https://github.com/username/new-site.git

ハマり3: package.jsonの名前を変え忘れる

package.jsonnameを変え忘れると、ビルドログで「どのサイトのビルドか」が判別しにくくなります。動作に支障はないですが、トラブル時に混乱の元になります。

ハマり4: faviconを変え忘れる

faviconを変更し忘れて、全サイトが同じアイコンになっていたことがあります。ブラウザのタブで見分けがつかない。地味ですが、実際の使い勝手に影響します。

ハマり5: SNSシェア画像のURLがコピー元のまま

レイアウトパーツ内のSNSシェア画像の初期URLを変え忘れると、SNSでシェアしたときにコピー元サイトの画像が表示されてしまいます。site.tsにSNSシェア設定を入れておくことで防げますが、見落としやすいポイントです。


コピー時のチェックリスト

上のハマりポイントをふまえて、コピー時に確認すべきことをまとめました。

  1. rm -rf node_modules .git package-lock.json
  2. npm install && git init
  3. site.ts: name, tagline, description, url, colors, nav, categories, footer を全て変更
  4. global.css: --color-primary--color-accent を変更
  5. package.json: name を変更
  6. index.astro: トップページのメインビジュアル、ボタン、セクション構成を変更
  7. public/favicon.svg: サイト固有のアイコンに差し替え
  8. src/content/posts/: コピー元の記事を削除
  9. npm run dev でローカル確認
  10. npm run build でビルドテスト
  11. GitHubに新しいリポジトリを作成 → push
  12. Cloudflare Pagesに接続 → カスタムドメイン設定

所要時間: 30分〜1時間(記事作成を除く)

このチェックリストに従えば、「動くけど何かおかしい」という状態を防げます。特に1と3は必須。これを飛ばすと確実にハマります。


まとめ: テンプレート設計で得た教訓

7つの設計教訓

  1. site.tsにまとめる: サイトごとに違う情報は1ファイルに集約する。バラバラにすると修正漏れが起きる
  2. CSS変数で色を管理: 色を直接書き込むとコピー時に全部直す必要がある。CSS変数なら2行変えるだけ
  3. パーツは汎用的に作る: site.tsかCSS変数から値を取るルールにする。直接書き込みは使い回しの敵
  4. トップページだけは例外: 完全にsite.tsで対応するのは難しい。パターンを決めて切り替えるのが現実的
  5. node_modulesは必ず削除: コピー時の一番よくあるハマりポイント。「動くけど不安定」を防ぐために必須
  6. コピー運用の限界を知っておく: 4サイトなら大丈夫だけど、10サイトになったらモノレポ化が必要
  7. 作りすぎない: モノレポは「必要になったとき」に作ればいい。今は動くもので十分

1つのテンプレートから4サイトを展開できたのは、site.tsの設計のおかげです。設計に1時間かけたことで、その後の3サイトそれぞれで3時間以上を節約できました。合計9時間以上の節約。つまり、最初に1時間の投資をしたら、9倍のリターンがあったということです。

テンプレート設計は「未来の自分への投資」です。最初の1つに時間をかけることをケチらないでほしい。そして、完璧を目指しすぎないでほしい。site.tsに全部入れなくても、トップページだけ手で直せばいい。大事なのは「80%を自動化して、20%だけ手を動かす」というバランスです。

他のカテゴリの記事