俺のBlogについて
Google Documentを本物のCMSにした。自作ブログの裏側を全部見せます
1分で公開できるブログ
記事は Google Document で書く。
書き終わったら、管理ダッシュボードに Docs の URL を貼って「保存」を押す。
それだけ。
数十秒後には公開サイトに反映され、全文検索のインデックスにも自動で乗ります。
これが、私が 3 つのプロジェクトを組み合わせて作ったブログシステムの基本動作です。
今、あなたが読んでいるこの記事も、まったく同じ流れで世に出ています。
なぜ自作したのか
WordPress は素晴らしいツールです。
でも、長く使ううちに気になる点が増えてきました。
プラグインの依存関係が雪だるま式に膨らむ
エディタが「自分が書きたい形」と微妙に合わない
画像をいちいちメディアライブラリに上げるのが面倒
一方、Google Document は世界で最も使いやすい文章エディタの一つです。
表も、コードも、画像も、リストも貼れる。
共同編集もオフライン執筆もバージョン履歴も全部標準装備。
「これがそのまま CMS(コンテンツ管理システム)になったら最高じゃないか?」
これがスタートでした。
システム構成(3つのプロジェクト)
このブログは 3 つのプロジェクトで動いています。
公開サイト(読者が見る画面)— Nuxt 4 の SSR、Cloud Run + Firebase Hosting
管理ダッシュボード(私が URL を登録する画面)— Nuxt 4 の SPA、Firebase Hosting
API サーバ(Google Docs を取りに行き、HTML に変換し、検索エンジンに投げる頭脳)— Python 3 + Flask 3、Cloud Run
ここからはエンジニアの方に向けて、中身を本気で見せます。
キモその1: Google Docs → HTML 変換、612行の自作コンバータ
Google Docs API は文書を JSON で返してくれます。これを HTML に変換するライブラリは世にいくつかありますが、どれも痒いところに手が届きませんでした。なので自作しました(612 行)。
このコンバータの自慢ポイント:
コードブロックの自動検出: 段落全体が等幅フォント(Courier New, Consolas, Source Code Pro 等)なら <pre><code> で自動的に囲む
インラインコード: 段落内の一部が等幅フォントなら <code> で囲む。Docs 上で「フォントを Courier に変えるだけ」でコードに化けます
ネストリストの完全再現: 入れ子の番号付き/箇条書きを状態マシン(list_stack)で正確に再構築
表のセル幅まで保持: <colgroup> を使って列幅、罫線色、背景色、padding を全部 CSS 化。Docs で見た見た目がブラウザでもそのまま出ます
ゼロ幅文字の除去: Docs にコピペすると紛れ込む U+200B(ゼロ幅スペース)や U+FEFF(BOM)などの不可視文字を、正規表現で一掃
これで「Docs で書いた見た目 = ブラウザでの見た目」が、ほぼ完全に一致します。
キモその2: 検索の即時インデックス(Algolia)
記事を保存した瞬間、Algolia という全文検索エンジンに本文が送られます。
管理画面で URL を登録 → Flask が Google Docs API でプレーンテキストを抜き出す → Algolia に送信
日本語と英語の両方でステミング(語幹解析)を有効化
フロント側に渡す API キーは 検索専用キー。書き込み権限はサーバ側だけ持つので、漏れても被害がない
全件再構築は replace_all_objects を使って、検索を止めずにインデックスごと丸ごと差し替え
検索結果には _highlightResult を仕込み、ヒットしたキーワードを公開サイト側でハイライト表示しています。
キモその3: アイコン生成は「旧型 Grok」で節約
全記事に固有のアイコン画像を持たせたいけれど、毎回手で作るのは面倒だしお金もかかる。そこで AI 画像生成を組み込みました。ただし、品質と費用を天秤にかけて、今はあえて旧バージョンの Grok モデルを使っています。最新モデルは綺麗だけど高い。フラットなアイコン用途なら旧モデルで十分。
コード上ではプロバイダを切り替え可能にしてあります。
icon_gen_provider: "grok" | "imagen"
imagen を選べば Google の Vertex AI Imagen に切り替わります。お金に余裕ができたら戻る、戻らない、を 1 行で選択できる構造です。
フローはこう:
タイトルとカテゴリーから自動でプロンプトを生成
Grok API(OpenAI SDK 互換の https://api.x.ai/v1 エンドポイント)に投げる
返ってきた画像を Pillow で 256×256 の PNG にリサイズ
Google Cloud Storage にアップロード
生成したアイコンを、元の Google Docs の先頭に自動挿入する
最後の 5 番が地味に効いています。Docs API の書き込みスコープを使って文書そのものを書き換えるので、「アイコン作って → Docs を開き直して貼って」という二度手間がゼロ。
キモその4: あえて Firebase Auth を使わない
Firebase 環境なら Firebase Authentication を使うのが定番です。でも私はあえて、Google Identity Services(GIS)のリダイレクトモードを直接組み込みました。
理由は 3 つ:
Firebase Auth SDK は意外と重い
権限レベル(admin / staff / guest)はクライアントに信頼させたくない、サーバ側で完結させたい
ブラウザに認可情報を残したくない
実際の流れ:
ユーザが Google ログインボタンを押す → accounts.google.com にリダイレクト
認証成功 → Flask の /api/google_callback にトークンが届く
Flask が JWT を発行、HttpOnly Cookie として返す
表示用のプロファイル(名前、写真)だけ非 HttpOnly Cookie で渡す(5分で自己消滅)
フロントは認可情報を Pinia メモリ上のみ に保持。localStorage は使わない
iOS Safari の bfcache(戻るボタンで古い画面が一瞬復元される現象)にも対応していて、layouts/default.vue で復元を検知したら _t クエリパラメータを付けて強制リロードしています。
キモその5: パフォーマンスの細工
SWR キャッシュ: Nitro のルートルールで、ブログ一覧は 60 秒、カテゴリーは 10 分の Stale-While-Revalidate。古いキャッシュを即返しつつ、裏で更新する。API の遅延がユーザに見えない
Brotli + Gzip 自作圧縮プラグイン: 1KB 以上のレスポンスを自動圧縮。実測で 364KB → 53KB、85.5% 削減
Cloud Run min=0: アクセスが無いときはインスタンスゼロでコストゼロ。個人ブログ規模ならコールドスタートも許容範囲
画像ドメインのホワイトリスト: @nuxt/image で storage.googleapis.com のみ許可、WebP 強制、品質 80
Secret Manager のプロセス内キャッシュ: 起動時に 1 回だけ全シークレットを取得し、以降はメモリ参照。Secret Manager は呼び出し回数で課金されるので、地味だが効く
キモその6: SEO は監査スコア 93/100
検索エンジン対策も手を抜いていません。
Schema.org JSON-LD(WebSite + SearchAction)
動的サイトマップ(記事追加と同時に反映、画像 URL も含む)
RSS フィード(毎リクエスト時に HTML からプレーンテキスト化して生成)
OGP / Twitter Card / PWA マニフェスト一式
WordPress じゃ無理なこと
最後に、このシステムが WordPress や他の CMS を超えていると思う点を並べます。
共同編集: Google Docs は最初から共同編集が標準。複数人で同時に同じ記事を書ける。WordPress のロック機構よりずっと自然
エディタの自由度: Docs でできることは全部 HTML 化されます。表、画像配置、コード、ネストリスト... プラグインゼロで全部
画像管理から解放: Docs に画像を貼れば、それがそのまま公開されます。メディアライブラリを開く必要なし
オフライン執筆: Docs はオフラインで書ける。WordPress エディタはネット必須
バージョン履歴が標準装備: Docs の編集履歴が、そのまま記事の改訂履歴になる
デバイスを選ばない: スマホでも iPad でも書ける。Docs アプリさえあれば、どこでも執筆できる
まとめ
WordPress のプラグイン地獄を一度経験して、私は自分専用の CMS が欲しくなりました。Google Document を中心に据え、Cloud Run + Firebase + Algolia という現代的なスタックで作ってみたら、想像以上に書きやすく、運用が楽で、エンジニア的にも面白い仕組みになりました。
「Docs で書いて、URL を貼るだけで公開」。
このシンプルな体験の裏では、612 行の HTML コンバータ、無停止インデックス入替、JWT + GIS のフルスクラッチ認証、Brotli 圧縮、SWR キャッシュ、AI 画像生成のプロバイダ切り替え… が静かに動いています。
自作ブログ、おすすめです。自分の理想がそのまま動くシステムを持てる楽しさは、一度味わうと戻れません。
下記の画像や表やコードもGoogle Docsに貼り付けているだけです!
施策・項目 |
具体的行動 |
期待される効果 |
生産性向上 |
始業前の軽度な運動の導入 |
集中力・モチベーション向上、業務効率改善 |
イノベーションの創出 |
異なる分野の情報への積極的な関心 |
新規アイデア発見、多角的な問題解決能力養成 |
従業員の定着 |
適切な休息とリフレッシュ環境の提供 |
メンタルヘルス維持、エンゲージメント・士気向上 |
予定表
項目 |
内容 |
タイトル |
会議 |
ゲスト |
田中、スズキ、大谷 |
開始時刻 |
2026年3月6日 12:00 |
終了時刻 |
2026年3月6日 13:00 |
場所 |
会議室 |
説明 |
WEBサイトについての会議です |
Pythonのコードを書いてみるテスト
import os
a=0
b=0
a=a+1
b=b+1
print(a)
print(b)