何を作ったか
ふた晩で「個人発行の Web 雑誌」を一通り組んだ。月に一号、5 部門(Engineering / Design / AI / Process / Essay)、Claude が自動入稿、人間が校正して公開する、という運用前提のサイトだ。
技術スタックは Rails 8.1 (API-only) と Next.js 16 (Pages Router)。ベースは数週間前から手元にあったが、デザインが気に食わなかった。気に食わない、ということは、書きたい記事が書けないことを意味する。雑誌の誌面は、書き手の机の上の散らかり方とほぼ同義だからだ。
そこで Claude Code に「全面リデザインしたい」と投げたところから始まった。
デザイン採択は 1 ターンで決めた
「エディトリアル × モダン」とだけ伝えた。Claude は 3 案を出してきた。
- Ledger(元帳) — 文芸誌の活版風。Fraunces + Shippori Mincho、Drop Cap、ローマ数字章番号。
- Atlas(観測図) — MIT Tech Review のような観測誌風。Bricolage Grotesque、12 col グリッド可視化、データチップ。
- Kage(影) — 和文ミニマル。墨と余白、漢数字、和の伝統色。
3 案分の HTML プレビューが doc/redesign/previews/ に出力されてきたので、そのまま開いて並べて見た。3 つとも別物のサイトに見える のが面白かった。比較できるように作られた提案は、選択を確信に変える。
私は B + A のハイブリッドを選んだ。Atlas を主軸に、Ledger の編集ツール(連番 / Drop Cap / フォリオライン)を 記事ページにだけ重ねる。Admin は Atlas のまま、業務 UI に文芸的装飾を持ち込まない。
決めたら、トークン体系と全ページのリデザインに 1 日かけた。
SEO/LLMO は最初から組む
雑誌として「読まれる」前に、機械に正確に読まれる構造を用意したかった。
具体的には:
- JSON-LD 5 種(BlogPosting / BreadcrumbList / Organization / WebPage / FAQPage)を記事詳細に埋め込む
llms.txt/llms-full.txtを生成して、LLM ボットが構造的に内容を取りに来られるようにするAccept: text/markdownで公開 API が YAML frontmatter + 本文 Markdown を返す- OGP は部門別の画像(
/og/og-engineering.png等)を切り替える
これらは「あとから足す」と互換性で苦労する。最初から <Head> に組み込んで、フィードと sitemap を同時に整えた。
# 公開 API の controller。Accept ヘッダで分岐
def show
respond_to do |format|
format.json { render json: serializer }
format.markdown { render plain: post.to_markdown_with_frontmatter }
end
end
Accept: text/markdown で叩いたら frontmatter 付きで返ってくるサイトは、AI クローラに対して ドキュメント化された API を提供している ことになる。これは検索 SEO とは別の信頼関係を作る。
5 PR に分けた理由
公開準備の作業は 5 つに分割した。
- 法務ページ —
/privacy/terms/contact/commerceの 4 ページ - GA4 + Cookie 同意 — opt-in でしか計測しない
- 広告枠の構造予約 — 後から AdSense ins タグを paste するだけにする
- アフィ表記システム —
posts.contains_affiliateカラム + 自動バッジ +rel="sponsored" - コンテンツ計画書 — 30 本の執筆ロードマップ
順番が大事だった。法務ページが無いと AdSense は審査に出せないし、GA4 を入れるにも Cookie 同意の前提に法務ページが要る。P0 → P1 → P2 の依存関係をそのまま PR の順番にした。
順序を守ると、各 PR は 1〜3 時間で書けて、レビューも単独で完結する。
Skills + Bot API + 人間校正
雑誌の運用は二段階パイプラインにした。
Claude (自動) → POST /api/v1/bot/posts (status: draft) →
人間 (Admin) → 校正 + 著者を sora-endo に変更 + published →
読者
Claude Bot は claude-bot という著者で投稿する。published にせず draft で受ける。これは E-E-A-T の観点で重要で、「自動生成された記事が直接公開される」状態を作らないためだ。
人間(私)は admin で記事を開き、自分の経験を 1〜2 段落足し、author を sora-endo に書き換えてから publish する。AI は調査と起草、人間は責任と一次情報の追加、という分業になる。
Skills は 4 本ある:
/post-outline— テーマ→ 構成案/post-draft— 構成案 → Markdown + SEO/OG/FAQ/post-image—__IMAGE_N__プレースホルダ → 実 URL/post-publish— Bot API に POST
これは Substack で AI 利用が一般的になったいまの個人ブログ運用としては、むしろ標準形に近づきつつあると思う。
詰まったところ
正直に書いておくと、いくつか嫌な瞬間があった。
- Tailwind v4 の
@themeで--color-paper-altのような複合トークン名は問題なく動くが、max-w-proseだけは built-in の65chに上書きされなかった。max-w-[42.5rem]で逃げた。 - next/font の Fraunces を SOFT/WONK 軸込みでロードすると、CJK ページの初回ビルドで
@vercel/turbopack-next/internal/font/google/fontが一度 resolve できない事象に遭遇した。.next/を消して再起動すると解消した。Turbopack のキャッシュ問題っぽい。 <title>を{post.seo.title || post.title} — AetherEchoesのような JSX 式 + 文字列リテラルで書くと、Next.js 16 が空文字を出力する。template literal で 1 つの string にしたら直った。
3 つとも 30 分以内で見つかったが、誰かのために書いておく。
次にやること
公開 → AdSense 申請までの距離は、まだ少しある。
- オリジナル記事 30 本(seed の改稿 + 完全新規)
- GitHub Actions CI / Sentry / DB 自動バックアップ
- Lighthouse 計測 + Core Web Vitals 観測
- Newsletter backend(個人雑誌の収益化として AdSense より親和性が高い)
48 時間で終わったのは「箱」の方で、「中身」はこれから書いていく。書きたい題材はいまのところ 30 本。1 本目は、この記事だ。