ついにこの日が来ました。Part 1 で claude --version を叩き、Part 2 でスキル化を覚え、Part 3-17 で 15 種類のチャートを Claude Code に作らせ、Part 18 で R2 キャッシュを噛ませ、Part 19 でテストを書いた——その総決算が今回の Part 20、「世に出す」 です。
ローカルで npm run dev して綺麗に描画されるチャートを見て満足するのは、エンジニアの自己満足です。チャートは URL を持って、検索結果に出て、SNS でシェアされて、初めて社会的な価値 を持ちます。本記事では、これまで連載で作ってきたチャート群を Next.js App Router + Cloudflare Pages に乗せ、OG 画像を自動生成し、Google Search Console と Analytics で計測まで仕込んで「公開完了」と言える状態に持っていきます。
所要時間 2 時間。Claude Code に頼めば、Next.js のページコンポーネント・OG 画像ジェネレーター・robots.ts / sitemap.ts の SEO 制御・Cloudflare Pages のビルド設定までを 1 セッションで 書き上げてくれます。連載 20 本の長旅、最後まで一緒に走り抜けましょう。
なぜ Cloudflare Pages なのか
Next.js のデプロイ先候補は Vercel・Netlify・AWS Amplify・Cloudflare Pages など複数ありますが、stats47.jp は Cloudflare Pages を選んでいます。理由は 3 つ。
| 観点 | Vercel | Cloudflare Pages |
|---|---|---|
| 月額コスト(中小規模) | Hobby 無料 / Pro $20 | 無料枠が広い(Workers 100K req/day) |
| エッジ実行 | Edge Functions 限定 | Workers ですべて Edge |
| 帯域課金 | あり(100GB/月超) | 無制限・無料 |
| D1 / R2 連携 | 別契約 | 同一ダッシュボード |
| ビルド時間 | 速い | やや遅い(5-10 分) |
決定打は 「帯域が無料」 と 「D1 / R2 がそのまま使える」 の 2 点。Part 18 で R2 にキャッシュした e-Stat JSON を、同じ Cloudflare アカウント内で読みに行けるので、認証も IAM もいりません。env.STATS_DATA_BUCKET を wrangler.toml に書くだけ。
ビルドがやや遅いのは唯一の弱点ですが、CI 完走で 5-7 分なら許容範囲。連載のゴールは「個人の趣味で 47 都道府県データを公開する」レベルなので、Cloudflare 一択で問題ありません。
Next.js App Router のページ構成
連載では Pages Router ではなく App Router を使ってきました。理由は (a) Server Components で R2 fetch を サーバー側に閉じ込められる、(b) opengraph-image.tsx で OG 画像が宣言的に作れる、(c) metadata export で SEO 設定が型安全、の 3 点です。
ディレクトリ構造はこんな感じ。
apps/web/src/app/
├── layout.tsx # ルート layout(Header/Footer)
├── page.tsx # トップページ
├── robots.ts # robots.txt 自動生成
├── sitemap.ts # sitemap.xml 自動生成
├── opengraph-image.tsx # サイト全体の OG 画像
└── charts/
├── page.tsx # チャート一覧
└── [slug]/
├── page.tsx # 個別チャートページ
├── opengraph-image.tsx # チャート別 OG 画像
└── loading.tsx # Suspense fallback
[slug] 部分が動的ルーティング。/charts/population-bar、/charts/aging-heatmap のように、Part 3-17 で作った 15 種類のチャートがそれぞれ URL を持ちます。
Claude Code に頼むときはこの構造を最初に伝えておくと、迷子になりません。
あなた → claude:
apps/web/src/app/charts/[slug]/page.tsx を作って。
R2 の app/charts/[slug]/data.json を fetch して、
packages/visualization の BarChart に流す。
generateStaticParams で 15 個の slug を静的生成。
generateMetadata で title/description を frontmatter から拾う。
Step 1: 静的生成 vs ISR vs CSR の選択
ページを書く前に、レンダリング戦略 を決めます。Next.js App Router では (a) Static(ビルド時生成)、(b) ISR(Incremental Static Regeneration)、(c) Dynamic(リクエスト時 SSR)、(d) Client-only の 4 つから選べます。
| 戦略 | 適する用途 | TTFB | 更新頻度 | Cloudflare Pages 対応 |
|---|---|---|---|---|
| Static (SSG) | 統計データ・ブログ記事 | 最速 | ビルド時のみ | フル対応 |
| ISR | 頻繁に更新される一覧 | 速い | revalidate 秒数で再生成 | 一部制約あり |
| Dynamic (SSR) | ユーザー固有データ | 中 | リクエストごと | Workers 経由 |
| Client (CSR) | インタラクティブ UI | 遅い(JS 待ち) | リアルタイム | 制約なし |
連載のチャートは e-Stat の年次データ なので、データ更新は年 1-2 回程度。SSG 一択 です。generateStaticParams で 15 個の slug を返し、ビルド時に静的 HTML + JSON を生成します。
// apps/web/src/app/charts/[slug]/page.tsx
import { notFound } from "next/navigation";
import { fetchChartData } from "@/lib/r2";
import { ChartRenderer } from "@/components/ChartRenderer";
const CHART_SLUGS = [
"population-bar",
"aging-heatmap",
"medical-cost-choropleth",
"income-scatter",
"birthrate-line",
"bar-chart-race",
"radar-prefecture",
"wage-box-plot",
"tourism-stacked",
"energy-area-chart",
"crime-small-multiple",
"commerce-bubble",
"edu-slope-graph",
// ...
] as const;
export async function generateStaticParams() {
return CHART_SLUGS.map((slug) => ({ slug }));
}
export const dynamicParams = false; // CHART_SLUGS 以外は 404
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const data = await fetchChartData(slug);
if (!data) return {};
return {
title: `${data.title}|stats47`,
description: data.description,
openGraph: {
images: [`/charts/${slug}/opengraph-image`],
},
};
}
export default async function ChartPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const data = await fetchChartData(slug);
if (!data) notFound();
return (
<article className="mx-auto max-w-3xl px-4 py-8">
<h1 className="text-2xl font-bold">{data.title}</h1>
<p className="mt-2 text-slate-600">{data.description}</p>
<ChartRenderer type={data.chartType} data={data.values} />
</article>
);
}
ポイントは 3 つ。
generateStaticParamsで 15 個の slug を返し、dynamicParams = falseで範囲外を 404 にparamsが Promise(Next.js 15 以降の仕様変更)。await paramsを忘れると runtime errorgenerateMetadataで OG 画像 URL を/charts/[slug]/opengraph-imageに向ける(次の Step で自動生成される)
Claude Code に「Next.js 15 の App Router でチャートページを書いて」と頼むと、Next.js 14 流の params: { slug: string } を返してくることがあります。「Next.js 15 系を使うので params は Promise」 と明示するのが事故防止のコツ。
Step 2: チャート JSON を R2 から fetch(Part 18 と連携)
fetchChartData の中身は Part 18 で作った R2 reader を呼び出すだけです。
// apps/web/src/lib/r2.ts
import { getCloudflareContext } from "@opennextjs/cloudflare";
export type ChartData = {
title: string;
description: string;
chartType: "bar" | "line" | "scatter" | "choropleth" | "heatmap";
values: unknown;
};
export async function fetchChartData(
slug: string,
): Promise<ChartData | null> {
const { env } = getCloudflareContext();
const key = `app/charts/${slug}/data.json`;
const obj = await env.STATS_DATA_BUCKET.get(key);
if (!obj) return null;
const json = await obj.json<ChartData>();
return json;
}
R2 のキーパス規約(.claude/rules/r2-storage-design.md)に従って app/charts/[slug]/data.json に統一しています。all.json モノリスを作らず、URL 1 個 = JSON 1 個 の原則で並べておくと、(a) Cloudflare のエッジキャッシュが効きやすい、(b) 1 ページの fetch が小さい(典型 5-50 KB)、(c) snapshot 更新時の差分が読みやすい——というメリットがあります。
ビルド時に R2 を読みに行く処理は Cloudflare Pages のビルドコンテナから直接 可能。@opennextjs/cloudflare の getCloudflareContext が、build / dev / prod すべての環境で同じインターフェースを提供してくれます。
Step 3: OG 画像を Next.js の opengraph-image.tsx で自動生成
SNS でシェアされたときのカード画像、いわゆる OG 画像。Twitter / Facebook / Slack で URL を貼ったときに出るあれです。
これを チャート 1 個ずつ手動で作る のは現実的じゃない。15 種類 × 47 都道府県 = 705 枚の OG 画像を Photoshop で作るなんて発狂します。
Next.js App Router には opengraph-image.tsx という規約があり、ファイルを置くだけで OG 画像エンドポイントが生える 仕組みがあります。中身は ImageResponse(Vercel/Edge の Satori ベース)で JSX を SVG → PNG に変換します。
// apps/web/src/app/charts/[slug]/opengraph-image.tsx
import { ImageResponse } from "next/og";
import { fetchChartData } from "@/lib/r2";
export const runtime = "edge";
export const alt = "stats47 チャート";
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export default async function OgImage({
params,
}: {
params: { slug: string };
}) {
const data = await fetchChartData(params.slug);
const title = data?.title ?? "stats47";
const subtitle = data?.description ?? "47 都道府県の統計データ";
return new ImageResponse(
(
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
width: "100%",
height: "100%",
padding: "64px",
background:
"linear-gradient(135deg, #0f172a 0%, #1e3a8a 100%)",
color: "#fff",
fontFamily: "sans-serif",
}}
>
<div style={{ fontSize: 32, opacity: 0.7 }}>stats47.jp</div>
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div style={{ fontSize: 64, fontWeight: 700, lineHeight: 1.2 }}>
{title}
</div>
<div style={{ fontSize: 28, opacity: 0.85 }}>{subtitle}</div>
</div>
<div style={{ fontSize: 24, opacity: 0.6 }}>
47 都道府県統計データの可視化
</div>
</div>
),
size,
);
}
これだけで /charts/population-bar/opengraph-image という URL が立ち上がり、1200×630 の PNG が返ってきます。Twitter Card Validator に URL を投げて検証すれば、Claude Code に作らせた OG 画像が綺麗に出ます。
注意点 3 つ。
export const runtime = "edge"が必須。Cloudflare Pages では Edge Runtime のみ動く- 絶対パスのフォントファイルは読めない。日本語フォントを使うときは
fetchで取得してImageResponseのfontsオプションに渡す(後述) - emoji は別途処理 が要る。Satori は emoji を CSS background-image でしか扱えない
日本語フォントを使いたい場合は、Google Fonts の Noto Sans JP の subset を R2 に置き、ビルド時に fetch する設計が安定します。
const font = await fetch(
`${process.env.NEXT_PUBLIC_BASE_URL}/fonts/NotoSansJP-Bold-subset.woff`,
).then((r) => r.arrayBuffer());
return new ImageResponse(/* ... */, {
...size,
fonts: [{ name: "Noto Sans JP", data: font, weight: 700, style: "normal" }],
});
Step 4: robots.ts と sitemap.ts の noindex 制御
新規ページを追加するときに 絶対に忘れてはいけない のがインデックス制御。stats47 は過去にここで大事故を起こしました(後述「つまずきポイント」参照)。
App Router では robots.ts と sitemap.ts をルート直下に置けば、それぞれ /robots.txt と /sitemap.xml が自動生成されます。
// apps/web/src/app/robots.ts
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{
userAgent: "*",
allow: "/",
disallow: [
"/api/",
"/admin/",
"/*/opengraph-image", // ← 重要: OG 画像 URL は noindex
"/_next/",
],
},
],
sitemap: "https://stats47.jp/sitemap.xml",
};
}
/*/opengraph-image の Disallow を入れ忘れると、Google が OG 画像 URL を「ページ」として認識し、GSC に大量の 「クロール済み - インデックス未登録」 が積み上がります。stats47 では 2026 年に 1,453 件発生して気付きました(CLAUDE.md にも警告として書いてあります)。
// apps/web/src/app/sitemap.ts
import type { MetadataRoute } from "next";
const CHART_SLUGS = [
"population-bar",
"aging-heatmap",
"medical-cost-choropleth",
// ...
];
export default function sitemap(): MetadataRoute.Sitemap {
const now = new Date();
return [
{
url: "https://stats47.jp/",
lastModified: now,
changeFrequency: "weekly",
priority: 1.0,
},
...CHART_SLUGS.map((slug) => ({
url: `https://stats47.jp/charts/${slug}`,
lastModified: now,
changeFrequency: "monthly" as const,
priority: 0.8,
})),
];
}
サイトマップに OG 画像 URL を含めない(Disallow と矛盾するため)。新規ページを追加するときは 必ず sitemap.ts にも追記 する。これを忘れると Google にいつまでも発見されません。
Claude Code に「apps/web/src/app/charts/[slug]/page.tsx を新規作成」と頼むときは、プロンプトに「同時に sitemap.ts に追記して」と書く のがチェックリスト化のコツ。
Step 5: Cloudflare Pages デプロイ
ビルドとデプロイは @opennextjs/cloudflare 経由でやります。next build の出力を Cloudflare Workers 用にトランスパイルしてくれるアダプタです。
# package.json の scripts
{
"scripts": {
"build": "next build",
"build:cf": "next build && opennextjs-cloudflare build",
"preview:cf": "opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare deploy"
}
}
ローカルで本番ビルドを確認するなら npm run preview:cf。これは Cloudflare の wrangler pages dev を内部で叩き、本番に限りなく近い環境でブラウザ確認できます。
デプロイ自体はこの 1 行。
npx wrangler pages deploy .open-next/assets \
--project-name stats47 \
--branch main
CI でやるなら .github/workflows/deploy.yml を組みます。
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build:cf
working-directory: apps/web
env:
STATS_DATA_BUCKET: ${{ secrets.STATS_DATA_BUCKET }}
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy apps/web/.open-next/assets --project-name=stats47 --branch=main
CLOUDFLARE_API_TOKEN は Cloudflare ダッシュボード → My Profile → API Tokens で発行。「D1 Edit + R2 Storage Edit + Pages Edit + Account Settings Read」 の 4 つで足ります(stats47 では「stats47」という 1 個のトークンに集約しています)。
初回デプロイのチェックリストはこちら。
| # | 項目 | 確認方法 |
|---|---|---|
| 1 | wrangler.toml の name がプロジェクト名と一致 | wrangler whoami |
| 2 | R2 バケットが Cloudflare 上に作成済み | ダッシュボード → R2 |
| 3 | _routes.json で Workers と静的ファイルが正しく振り分け | .open-next/_routes.json を grep |
| 4 | 環境変数(NEXT_PUBLIC_BASE_URL 等)が Cloudflare Pages 側にも登録 | ダッシュボード → Pages → Settings → Environment variables |
| 5 | カスタムドメインの DNS が Cloudflare に向いている | dig stats47.jp で Cloudflare の IP が返る |
| 6 | デプロイ後の URL で /robots.txt /sitemap.xml が 200 を返す | curl -I https://stats47.jp/robots.txt |
ここまで通れば、本番に出ています。https://stats47.jp/charts/population-bar を開いてチャートが描画されたら、シリーズ累計 20 本の集大成が世に出た瞬間 です。
Step 6: Analytics と Search Console 設定
公開 = 完了ではない。どれだけ見られているかを計測 する仕組みを入れて初めて運用が始まります。
Google Analytics 4
GA4 は Next.js の next/script で afterInteractive で読み込むだけ。Cloudflare Pages でも普通に動きます。
// apps/web/src/app/layout.tsx
import Script from "next/script";
const GA_ID = process.env.NEXT_PUBLIC_GA_ID;
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ja">
<body>
{children}
{GA_ID && (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}
strategy="afterInteractive"
/>
<Script id="ga-init" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_ID}', { send_page_view: true });
`}
</Script>
</>
)}
</body>
</html>
);
}
Consent Mode を使うなら gtag('consent', 'default', ...) を先に。stats47 では Consent Mode v2 を入れていますが、今回は割愛します。
Google Search Console
GSC への登録は 2 ステップ。
- ドメイン所有権の確認: DNS TXT レコードで認証。Cloudflare DNS なら 1 分で完了
- サイトマップの送信: GSC の「サイトマップ」メニューに
https://stats47.jp/sitemap.xmlを貼り付ける
サイトマップ送信から 2-7 日で初期インデックス が走ります。GSC の「ページ」レポートに「インデックスに登録済み」が増えてくれば成功。
/charts/[slug] が GSC で 「クロール済み - インデックス未登録」 になっている場合は、(a) コンテンツが薄い、(b) noindex が誤って付いている、(c) 内部リンクが少ない、のいずれか。Part 1-19 までの記事から該当チャートへ内部リンクを張れば、ほとんどは解消します。
つまずきポイント
連載 20 本の中で stats47 が実際に踏んだ地雷を 4 つ。
1. cookies() / headers() in layout で SSG 崩壊
最大の地雷。apps/web/src/app/layout.tsx または layout 配下の Server Component で cookies() や headers() を呼ぶと、全ページが SSG から外れて Dynamic Rendering になります。Cloudflare Pages では Edge Worker が毎リクエスト発火するので、(a) TTFB が劇的に悪化、(b) Workers 無料枠を圧迫、(c) Lighthouse スコアが 90 → 50 に転落、という三重苦が起きます。
stats47 では Experiment EXP-004 / EXP-005 で 2 回踏んだので、.claude/rules/nextjs-ssg-preservation.md に「Server Component で cookies/headers を呼ぶな」と明文化してあります。Cookie が必要なら Client Component に閉じ込めて document.cookie を読む、もしくは Route Handler 経由で取る、の 2 択。
Claude Code に「ヘッダーに今日の日付を表示して」と頼んだら勝手に headers() を呼んできた——ということもあるので、生成されたコードを必ず grep:
grep -rn "from \"next/headers\"" apps/web/src/app/layout.tsx \
apps/web/src/components/ -l
2. Edge Runtime の制約
Cloudflare Pages では Node.js 標準ライブラリの大半が動きません。fs path crypto(一部)stream(一部)が NG。opengraph-image.tsx で runtime = "edge" を指定するのは、これに合わせる必要があるからです。
@opennextjs/cloudflare がいくつかの Node API を polyfill してくれますが、ビルド時 fetch でデータを取り込む か、Edge 互換のライブラリだけ使う のが安全です。p-limit zod date-fns あたりは Edge OK。sharp(画像処理)puppeteer は NG。
3. Image 最適化と Cloudflare の罠
Next.js の <Image> コンポーネントは Vercel の Image Optimization 前提で設計されています。Cloudflare Pages では next.config.ts で images.unoptimized: true にするか、Cloudflare Images(有料)を使う必要があります。
stats47 では、(a) OG 画像 → opengraph-image.tsx で都度生成、(b) サムネイル → 事前に WebP 化して R2 配置、(c) 通常の <img> → 直接配信、の 3 段構えで next/image を一切使っていません。Edge 環境で画像最適化を頑張るより、事前に最適化済みアセットを R2 に置く ほうが運用が楽。
4. SSG 時の fetch エラーがビルドを止める
generateStaticParams 中の R2 fetch が失敗すると、ビルド全体がコケます。snapshot がまだ生成されていない slug を返してしまうと、generateMetadata の fetchChartData が null を返し、ビルドエラーに。
対策:
export async function generateStaticParams() {
const slugs = await listAvailableSlugs(); // R2 にデータが存在するものだけ
return slugs.map((slug) => ({ slug }));
}
async function listAvailableSlugs(): Promise<string[]> {
const { env } = getCloudflareContext();
const list = await env.STATS_DATA_BUCKET.list({
prefix: "app/charts/",
delimiter: "/",
});
return list.delimitedPrefixes
.map((p) => p.replace("app/charts/", "").replace("/", ""))
.filter(Boolean);
}
R2 をビルド時に list して 存在するものだけ静的生成 する。これで「データが揃わないとビルドできない」というフラジリティが消えます。
デプロイ図
連載のチャートが本番に出るまでの流れを図にすると、こうなります。
URL 構造も明示しておくと、Claude Code に追加ページを頼むときに迷子になりません。
シリーズまとめ — 何が変わるか
連載 20 本を貫いて主張してきたのは 「Claude Code は試行錯誤の速度を 1 桁変える」 という 1 点に尽きます。
| 工程 | 手書きスクリプト時代 | Claude Code 時代 |
|---|---|---|
| e-Stat 統計表の探索 | ブラウザ + メモ 30 分 | /search-estat で 1 分 |
| データ取得スクリプト | 1-2 時間 | プロンプト 30 秒 + 実行 1 分 |
| チャート設計 | D3 ドキュメント 2 時間 | 「散布図にして」で 5 分 |
| エラー対応 | スタックトレース読解 | エラー貼り付けて自動修正 |
| キャッシュ実装 | 半日 | Part 18 のレシピで 30 分 |
| テスト | 1 日 | Part 19 で 1 時間 |
| デプロイ | 2-3 日 | 本記事の手順で 2 時間 |
| 合計(チャート 1 本) | 約 1 ヶ月 | 約 1 日 |
「1 ヶ月 → 1 日」が単なる時短ではなく、「やる気が続いている間に完結する」 という意味で本質的です。エンジニアの個人開発で頓挫する最大の理由は「途中で飽きる」「土日が潰れて気力が削られる」。Claude Code はこれを 「思いついたその日に公開まで持っていける」 スピード感にします。
20 本を通して見てきた Claude Code 活用の 5 つの原則 を最後にまとめます。
- 頻出処理はスキル化 — Part 2 の
/search-estatのように、何度も使うものは.claude/skills/に固定 - データ取得とチャート描画を分離 — Part 18 の R2 キャッシュで取得層を独立させる
- Server Component で fetch、Client Component で描画 — Next.js App Router の原則
- SEO 制御は最初から仕込む — robots.ts / sitemap.ts / OG 画像はページ作成と同時に
- ビルドエラーで止まらない設計 — R2 list で存在するものだけ静的生成
これさえ守れば、Claude Code は 「47 都道府県の任意の統計指標を、思いついたその日に Web 公開できるパートナー」 になります。stats47.jp 自体が、その実証実験の 1 年分の成果です。
連載完走バッジ — Part 1 〜 Part 19 まとめ
ここまで読み切ってくれた方、本当にお疲れさまでした。シリーズ全 20 本のリンクをまとめて置いておきます。途中の Part を飛ばしている人は、興味のあるところから戻ってもらえれば。
環境・基盤編
- Part 1 環境構築と API キー取得 — Claude Code インストール + e-Stat API キー
- Part 2 検索スキル化(/search-estat) — 統計表検索を 1 コマンド化
チャート作成編(15 本)
- Part 3 人口バーチャート
- Part 4 高齢化率ヒートマップ
- Part 5 医療費コロプレスマップ
- Part 6 県民所得スキャッタープロット
- Part 7 出生率折れ線グラフ
- Part 8 人口推移バーチャートレース
- Part 9 県民性レーダーチャート
- Part 10 賃金格差ボックスプロット
- Part 11 観光客スタックドエリア
- Part 14 エネルギー消費エリアチャート
- Part 15 犯罪率 Small Multiple
- Part 16 商業バブルチャート
- Part 17 大学進学率スロープグラフ
運用・最適化編
- Part 18 R2 キャッシュ設計 — e-Stat API レスポンスを R2 に永続化
- Part 19: 20本の図を毎週自動更新|Skill チェーンと GitHub Actions Claude Code — 連載で作ったチャートを cron で再生成
公開編(本記事)
- Part 20 Next.js + Cloudflare Pages デプロイ ← いまここ
関連ランキング・記事
連載完走後にチェックして欲しい stats47 内のページもどうぞ。
- 人口ランキング — Part 3 のチャートが置かれている本番ページ
- 情報通信業ランキング — Claude Code 系の記事が並ぶカテゴリ
- テーマ別ダッシュボード一覧 — Part 3-17 のチャート群が組み合わさった集大成
- Claude Code で47都道府県分析を自動化|公務員のための AI × 統計 7 ステップ — エンジニア以外向けの入門記事。本連載と相互補完
- stats47 about ページ — 本サイトを Claude Code でどう作っているかの全体像
連載シリーズはここで一旦完結します。次のテーマは未定ですが、(a) Cloudflare D1 と Drizzle ORM で 47 都道府県のリレーショナル分析、(b) Remotion で統計データを動画化して YouTube に上げる、(c) Claude Code で SEO 改善を回す あたりを検討中。リクエストがあれば stats47 の問い合わせフォームからどうぞ。
20 本完走、お疲れさまでした。Claude Code と e-Stat の組み合わせで、あなたの「気になる 47 都道府県データ」もぜひ公開してみてください。claude と打って、開発の楽しさを思い出す——それが本連載で一番伝えたかったことです。
それでは、また次の連載で。