Next.js + Vercel でサイバーパンクなブログを作る
きっかけ
多言語対応のブログを作りたいと思い立ちました。ただ翻訳するだけでなく、翻訳の品質をAIで自動検証する仕組みも組み込みたかったのです。
具体的には「往復翻訳(Back-Translation)」という手法を使います。日本語で書いた記事を英語に翻訳し、その英語を更にもう一度日本語に翻訳します。元の日本語と戻ってきた日本語を比較すれば、翻訳の精度が数値でわかります。これを PostgreSQL の pgvector 拡張を使い cosine similarity で自動化します。
複数の翻訳モデル(Gemini, Llama, DeepSeek など)を同時に走らせて、どのモデルが一番うまく訳せるかをランキング化するのも面白そうです。
技術スタック
具体的に決まった構成はこちらです。完全無料で始められそうです。
- Next.js 16 (App Router) — フロントエンド
- Markdown — frontmatter 付きで Git 管理
- Vercel — GitHub push で自動ビルド・デプロイ
- Supabase — PostgreSQL + pgvector で翻訳データ管理
- Google Gemini API — 翻訳 + embedding(無料枠)
- Tailwind CSS — スタイリング
設計上の考慮
CMS を使うかどうか
当初は Payload CMS を使う予定でした。WordPress 風のUIで記事を書けるのが魅力だったので。
ただ、GitHub push → Vercel 自動デプロイという運用フローだと、CMS を通す意味が薄くなります。結局「Markdown で書いて push するだけ」が一番シンプルという結論になりました。
Payload CMS は、いずれヘッドレス CMS を使ってみたいというのもあるので、後のフェーズで導入予定です。Markdown ベースで動くものを先に作っているので、CMS との違いを体感しながら進められそうです。
コンテンツ管理のハイブリッド方式
翻訳結果の管理は、公開用・研究用をわけたハイブリッド設計になりました。
- Supabase(研究用) — 全モデルの翻訳結果とスコアを保存。ダッシュボードで比較・分析
- Git(公開用) — ベストな翻訳を
posts/en/に Markdown として自動 commit。ブログとして公開
読者が見るのは Git 上の「ベスト版」だけです。裏側では複数モデルの翻訳が蓄積されていて、品質の推移を追える設計です。
2リポジトリ構成
公開リポジトリ(dazy-blog)と非公開リポジトリ(dazy-blog-system)に分けました。
- 記事と Next.js フロントエンドは公開。どうせブログとして公開するので
- 翻訳パイプラインや設計ドキュメント、API キー設定は非公開
翻訳パイプラインは非公開リポジトリ側の GitHub Actions に置いて、公開リポジトリへの push を repository_dispatch で連携させる予定です。
日英切替の実装
URL に言語プレフィックスをつける方式を採用しました。
/ja/posts/hello-world → 日本語版
/en/posts/hello-world → 英語版
/ にアクセスすると /ja にリダイレクトされます。ヘッダー右上の [JA] [EN] ボタンで切り替えられます。
タグの多言語対応
タグは ID(英小文字)で管理して、表示名は tags.json で言語別にマッピングする方式にしました。
{
"tech": { "ja": "テック", "en": "Tech" },
"anime": { "ja": "アニメ", "en": "Anime" }
}
frontmatter には ID を書くだけです。表示時に言語に応じて自動変換されます。将来中国語を足すときも tags.json に "zh" を追加するだけです。
翻訳品質検証のコンセプト
このブログで色々試してみたい部分は、なんといっても翻訳品質の自動検証です。
基本フロー
- 原文(日本語)をAIの翻訳モデルで英訳
- 英訳を同じモデルで日本語に戻す(往復翻訳)
- 元の日本語と戻った日本語を embedding 化(Gemini Embedding)
- pgvector で cosine similarity を算出
- スコアが高い = 意味が保持された良い翻訳
ポイントは「正解訳がいらない」ことです。従来の翻訳評価(BLEU 等)は人間が作った正解訳との比較が必要でしたが、この方式は原文との往復で完結します。
複数モデル比較
同じ原文を Gemini、Llama(Groq)、DeepSeek などで翻訳して、スコアをランキング化します。日常系ブログの自由な文章では、モデルごとの得意・不得意が顕著に出るのではないかと予想しています。 完全無料で3モデル比較(Gemini + Llama + DeepSeek)ができるので、まずは色々と実験していきます。 数値化のための embedding モデルは Gemini に統一して、翻訳モデルだけを比較する想定です。(物差しが違うと公平な比較ができないため)