メインコンテンツへスキップ
#Web制作 約8分で読めます

Astro Studio で CMS なしのヘッドレスサイトを構築する方法【2026年新機能】

Astro Studio の新しいデータベース機能で、従来の CMS を使わずに動的コンテンツを管理するヘッドレスサイトを構築する実践ガイド。

Astro Studio が変えるヘッドレスサイト開発の常識

従来のヘッドレスサイト構築では、Contentful や Sanity などの CMS を導入し、API 経由でコンテンツを取得するのが一般的でした。しかし、小規模プロジェクトでは CMS の月額費用や管理コストが負担になることも少なくありません。

2026年に入り、Astro Studio が提供するデータベース機能が実用レベルに達したことで、CMS を使わずに TypeScript でコンテンツを管理する新しいアプローチが現実的になりました。この記事では、Astro Studio を活用した CMS レスなヘッドレスサイトの構築方法を、実際のコード例とともに解説します。

Astro Studio のデータベース機能とは

Astro Studio は、Astro プロジェクトに統合されたデータ管理基盤です。以下の特徴があります:

  • TypeScript ネイティブなスキーマ定義: コードでデータ構造を管理
  • ローカル開発用の SQLite: 開発環境でデータベースをシミュレート
  • Astro との深い統合: astro:db モジュールで直接クエリ可能
  • ビルド時データ取得: SSG として完全に静的化可能

Astro Studio を使うことで、以下のようなユースケースが CMS なしで実現できます:

  • ブログ記事の管理(マークダウン + メタデータ)
  • 製品カタログ・ポートフォリオサイト
  • FAQ・ドキュメントサイト
  • 多言語コンテンツの管理
graph LR
    A[TypeScript スキーマ定義] --> B[ローカル SQLite DB]
    B --> C[Astro コンポーネント]
    C --> D[ビルド時クエリ実行]
    D --> E[静的 HTML 出力]
    
    style A fill:#4F46E5
    style E fill:#10B981

図: Astro Studio のデータフローとビルドプロセス

セットアップと初期設定

まず、Astro プロジェクトに Astro Studio のデータベース機能を追加します。

1. プロジェクトの初期化

# Astro プロジェクトを新規作成
npm create astro@latest my-headless-site
cd my-headless-site

# Astro DB パッケージをインストール
npx astro add db

2. スキーマの定義

db/config.ts でデータベーススキーマを定義します。以下は、ブログ記事を管理するスキーマの例です:

import { defineDb, defineTable, column } from 'astro:db';

const BlogPost = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    slug: column.text({ unique: true }),
    title: column.text(),
    description: column.text(),
    content: column.text(),
    publishedAt: column.date(),
    tags: column.json(),
    featured: column.boolean({ default: false }),
  },
});

export default defineDb({
  tables: { BlogPost },
});

3. シードデータの投入

開発環境で使用する初期データを db/seed.ts で定義します:

import { db, BlogPost } from 'astro:db';

export default async function seed() {
  await db.insert(BlogPost).values([
    {
      id: 1,
      slug: 'astro-studio-intro',
      title: 'Astro Studio 入門',
      description: 'Astro Studio の基本機能を解説',
      content: '# Astro Studio とは...',
      publishedAt: new Date('2026-04-01'),
      tags: ['Astro', 'データベース'],
      featured: true,
    },
    {
      id: 2,
      slug: 'cms-less-workflow',
      title: 'CMS なしのコンテンツ管理',
      description: 'TypeScript でコンテンツを管理する方法',
      content: '# CMS レスなワークフロー...',
      publishedAt: new Date('2026-04-10'),
      tags: ['Astro', 'ワークフロー'],
      featured: false,
    },
  ]);
}

コンテンツの取得と表示

Astro コンポーネント内で astro:db を使ってデータを取得し、ページをレンダリングします。

ブログ一覧ページの実装

src/pages/blog/index.astro:

---
import { db, BlogPost, desc } from 'astro:db';

const posts = await db
  .select()
  .from(BlogPost)
  .orderBy(desc(BlogPost.publishedAt));
---

<html lang="ja">
  <head>
    <title>ブログ一覧</title>
  </head>
  <body>
    <h1>記事一覧</h1>
    <ul>
      {posts.map((post) => (
        <li>
          <a href={`/blog/${post.slug}`}>
            <h2>{post.title}</h2>
            <p>{post.description}</p>
            <time>{post.publishedAt.toLocaleDateString('ja-JP')}</time>
          </a>
        </li>
      ))}
    </ul>
  </body>
</html>

動的ルートによる記事詳細ページ

src/pages/blog/[slug].astro:

---
import { db, BlogPost, eq } from 'astro:db';

export async function getStaticPaths() {
  const posts = await db.select().from(BlogPost);
  return posts.map((post) => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
---

<html lang="ja">
  <head>
    <title>{post.title}</title>
    <meta name="description" content={post.description} />
  </head>
  <body>
    <article>
      <h1>{post.title}</h1>
      <time>{post.publishedAt.toLocaleDateString('ja-JP')}</time>
      <div set:html={post.content} />
      <ul>
        {post.tags.map((tag) => (
          <li>{tag}</li>
        ))}
      </ul>
    </article>
  </body>
</html>
sequenceDiagram
    participant User as ユーザー
    participant Astro as Astro ビルドプロセス
    participant DB as Astro DB (SQLite)
    participant HTML as 静的 HTML

    User->>Astro: npm run build 実行
    Astro->>DB: getStaticPaths() でデータ取得
    DB-->>Astro: 全記事データを返却
    Astro->>HTML: 各ページを静的生成
    HTML-->>User: ビルド完了・デプロイ可能

図: Astro Studio のビルド時データ取得フロー

コンテンツ管理のワークフロー

CMS を使わない場合、コンテンツの追加・更新は以下のフローで行います:

1. TypeScript でコンテンツを追加

新しい記事を追加する際は、db/seed.ts または専用の管理スクリプトでデータを挿入します:

// scripts/add-post.ts
import { db, BlogPost } from 'astro:db';

async function addPost() {
  await db.insert(BlogPost).values({
    id: 3,
    slug: 'new-article',
    title: '新しい記事',
    description: '新しい記事の説明',
    content: '# 本文...',
    publishedAt: new Date(),
    tags: ['Astro'],
    featured: false,
  });
  console.log('記事を追加しました');
}

addPost();

2. ローカルで確認

# 開発サーバーを起動
npm run dev

# ブラウザで http://localhost:4321/blog を確認

3. ビルド・デプロイ

# 静的サイトをビルド
npm run build

# Vercel / Netlify / Cloudflare Pages などにデプロイ

Markdown ファイルとの併用パターン

実際のプロジェクトでは、長文コンテンツは Markdown ファイルで管理し、メタデータのみを Astro DB で管理するハイブリッド方式も有効です。

フォルダ構成

src/
├── content/
│   └── blog/
│       ├── astro-studio-intro.md
│       └── cms-less-workflow.md
└── pages/
    └── blog/
        └── [slug].astro
db/
└── config.ts  # メタデータのみ管理

スキーマの変更

const BlogPost = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    slug: column.text({ unique: true }),
    title: column.text(),
    description: column.text(),
    publishedAt: column.date(),
    tags: column.json(),
    featured: column.boolean({ default: false }),
    // content フィールドは削除し、Markdown で管理
  },
});

ページコンポーネントでの読み込み

---
import { db, BlogPost, eq } from 'astro:db';
import { getEntry } from 'astro:content';

export async function getStaticPaths() {
  const posts = await db.select().from(BlogPost);
  return posts.map((post) => ({
    params: { slug: post.slug },
  }));
}

const { slug } = Astro.params;

// メタデータは DB から取得
const [meta] = await db.select().from(BlogPost).where(eq(BlogPost.slug, slug));

// 本文は Markdown から取得
const entry = await getEntry('blog', slug);
const { Content } = await entry.render();
---

<html lang="ja">
  <head>
    <title>{meta.title}</title>
    <meta name="description" content={meta.description} />
  </head>
  <body>
    <article>
      <h1>{meta.title}</h1>
      <time>{meta.publishedAt.toLocaleDateString('ja-JP')}</time>
      <Content />
    </article>
  </body>
</html>

従来の CMS との比較

項目Astro StudioContentful / Sanity
初期コスト無料無料プランあり(制限あり)
月額費用無料$0〜$500+(プランによる)
学習コスト低(TypeScript のみ)中〜高(API・管理画面の習得)
データ管理コードベースWeb 管理画面
非エンジニア向け不向き向いている
型安全性完全(TypeScript)部分的(SDK による)
ビルド速度高速(ローカル DB)中(API 呼び出しが必要)
バージョン管理Git で完全管理CMS 側の履歴機能に依存

Astro Studio は、以下のケースで特に有効です:

  • 小規模プロジェクト: 記事数が100件以下のブログ
  • エンジニア中心のチーム: コードでコンテンツを管理できるメンバーのみ
  • コスト重視: 月額費用を削減したい
  • 完全な静的化: SSG で CDN 配信し、サーバーコストをゼロにしたい

まとめ

Astro Studio のデータベース機能を活用することで、以下のメリットが得られます:

  • CMS の月額費用が不要: 小規模プロジェクトのコストを大幅削減
  • TypeScript で型安全にコンテンツ管理: エディタの補完が効き、ミスを防げる
  • Git でバージョン管理: コンテンツの変更履歴を完全に追跡可能
  • 完全な静的化: ビルド時にすべてのデータを取得し、高速な静的サイトを生成

一方で、非エンジニアがコンテンツを編集する必要がある場合や、大規模なコンテンツ管理が必要な場合は、従来の CMS との併用や、別途管理画面の構築を検討する必要があります。

Astro Studio は、「エンジニア主導のコンテンツ管理」という新しいワークフローを可能にするツールとして、2026年のヘッドレスサイト開発において有力な選択肢となっています。

参考リンク

#Astro #Astro Studio #ヘッドレスCMS #データベース #SSG
シェア