Thu Jul 03
Astro + Tailwind CSS + TypeScript で作られた多言語対応スターターテンプレートの使い方、プロジェクト構成、コマンドの解説です。
このテンプレートは、Astro 6 + Tailwind CSS v4 + TypeScript をベースに、ブログ・全文検索・UIコンポーネント集・多言語化(i18n)までひととおり揃ったスターターキットです。
デモ → https://dev-astro-three.vercel.app/ ↗
含まれているもの
| カテゴリ | 内容 |
|---|---|
| フレームワーク | Astro 6(output: 'static') |
| スタイル | Tailwind CSS v4(@import "tailwindcss" 方式) |
| 型 | TypeScript 6(strict 設定) |
| 多言語化 | ja / en の2言語対応(拡張可能) |
| コンテンツ | Markdown / MDX ブログ、locale別フォルダ管理 |
| 検索 | Pagefind による静的全文検索 |
| スライダー | Embla Carousel(AutoScroll プラグイン同梱) |
| 画像 | Astro Image + sharp による最適化 |
| UIコンポーネント | Tabs、Accordion、Modal、Lightbox、Dropdown、Hamburger等 |
| SEO | OGP、Twitter Card、hreflang、ロケール別 sitemap |
| AIガイドライン | CLAUDE.md、.cursor/rules/ を同梱 |
クイックスタート
# 1. 依存パッケージのインストール
npm install
# 2. 開発サーバー起動(http://localhost:4321)
npm run dev
# 3. プロダクションビルド
npm run build
# 4. ビルド成果物のプレビュー
npm run preview
注意: 検索機能(Pagefind)は dev mode では動作しません。
npm run build後に試してください。
プロジェクト構成
src/
├── assets/ # 画像等の静的アセット(Astroが最適化)
├── components/ # 再利用するUIコンポーネント
├── content/blog/ # ブログ記事 ({locale}/{slug}.{md,mdx})
│ ├── en/ # デフォルトロケール(英語)のコンテンツ
│ └── ja/ # 日本語訳
├── i18n/ # 多言語化(設定・辞書・ヘルパー)
├── icons/ # astro-icon ローカルアセット
├── layouts/ # レイアウト
├── pages/ # ルーティング(ファイルベース)
│ ├── ja/ # 日本語の静的ページ(about, index, library, search 等)
│ └── [lang]/ # 日本語以外のロケール用 動的ルート(blog, tags 等)
├── scripts/ # クライアント側JS
├── styles/ # Tailwind v4 と global CSS
├── types/ # 共有型定義
└── env.ts # BASE_URL の定義
本番URLの設定(site)
astro.config.mjs の site には本番環境のURLを必ず設定してください:
export default defineConfig({
site: 'https://your-production-domain.com', // ← 本番URLに変更
// ...
});
この値は以下で使われます:
@astrojs/sitemap→sitemap-0.xmlの絶対URLMetaTags.astro→ OGP / Twitter Card のog:url、og:image、canonical、hreflang<link rel="alternate">Breadcrumbs.astro→ JSON-LD のitemフィールド
設定を忘れると、デモのURL(https://dev-astro-three.vercel.app)が本番HTMLに残ってしまい、SEOやSNSシェアで意図しない挙動になります。
なお
BASE_URL(サブディレクトリ配下にデプロイする場合の prefix)とは別の設定です。BASE_URLは後述の「環境別 BASE_URL」を参照してください。
多言語化(i18n)の使い方
文字列を表示する
---
import { getLocaleFromUrl, useTranslations } from '../i18n/utils';
const locale = getLocaleFromUrl(Astro.url);
const t = useTranslations(locale);
---
<h1>{t('nav.home')}</h1>
新しい翻訳キーは src/i18n/ui.ts の 全 locale ブロックに追加してください。TypeScript が漏れを検出します。
locale 対応の URL を作る
import { BASE_URL } from '../env';
import { localizePath } from '../i18n/utils';
const href = `${BASE_URL}${localizePath('/blog/post-1/', locale).slice(1)}`;
// en: "/blog/post-1/" ja: "/ja/blog/post-1/"
新しい言語を追加する
src/i18n/config.tsのlocales、localeLabels、localeHtmlLangに追加src/i18n/ui.tsに新 locale の辞書を追加(全キー必須、型で強制)src/pages/{locale}/フォルダを作成し、index.astro、about.astro、library.astro、search.astroを翻訳した状態で配置(既存のsrc/pages/ja/を参考に)src/content/blog/{locale}/フォルダを作り、必要な記事を配置(任意)astro.config.mjsのi18n.localesとsitemap()のi18n.localesに追加
静的ページ(step 3)は 公式 Astro 推奨の locale 別フォルダパターンで、各言語ごとに翻訳した内容を配置します。 それ以外は自動対応されます:
[lang]/配下の動的ルート(blog、tags)- Language Switcher への新言語の追加
- hreflang
<link>と sitemap の locale alternates - 検索結果の locale 絞り込み(Pagefind フィルタ)
- 各ページの
<html lang>属性
翻訳がないページの扱い
ブログ記事は 任意のページだけ翻訳すればOK。例えば en/post-1.md だけあって ja/post-1.md が無い場合、/blog/post-1/ ではLanguage Switcherで 日本語 がクリック不可で表示されます。
検索もlocale単位
検索結果は現在のlocale内のページのみを対象にします。/search/?q=astro は英語ページから、/ja/search/?q=astro は日本語ページから検索します。
仕組み:
Layout.astroの<main>にdata-pagefind-filter="locale:en"(orja)を付与- 検索ページ側で
pagefind.search(query, { filters: { locale } })を呼ぶ - SearchForm の action も
localizePath('/search/', locale)でlocale対応
新しいlocaleを追加したときも、自動でこの仕組みが動作します。
カスタマイズの起点
| 何を変えたいか | 編集するファイル |
|---|---|
| サイト名・OGP | src/i18n/ui.ts、astro.config.mjs(site) |
| カラー・フォント | src/styles/global.css(Tailwind v4 @theme) |
| メニュー項目 | src/components/Navigation.astro |
| ヘッダー・フッター | src/components/Header.astro / Footer.astro |
| トップページ | src/pages/index.astro(EN)、src/pages/ja/index.astro(JA) |
| ブログ記事 | src/content/blog/{locale}/*.md |
| 追加コンポーネント | src/components/ 配下 |
環境別 BASE_URL
サブディレクトリ配下にデプロイする場合、ビルド時に ASTRO_BASE を指定できます:
ASTRO_BASE=/subdir/ npm run build
src/env.ts で BASE_URL 定数として export されているので、内部リンクにはこれを使ってください:
<a href={`${BASE_URL}${localizePath('/about/', locale).slice(1)}`}>About</a>
AI アシスタント向け規約
リポジトリルートに CLAUDE.md、.cursor/rules/ を同梱しています。Claude Code や Cursor を使うとき、命名規則・i18n の使い方・避けるべきパターンを自動で参照してくれます。詳細は CLAUDE.md を参照してください。
デプロイ
Vercel、Netlify、GitHub Pages、Cloudflare Pages 等の静的ホスティングサービスに dist/ フォルダを上げるだけでデプロイできます。Node ランタイムは不要です(完全な静的サイト)。
ライセンス
MIT ライセンス。ただし、修正の有無に関わらず競合商品としての再配布・販売は作者の許可なく行えません。
Created by: mooonycat ✨