最小機能ブログ(Minimum viable blog)
(ostwilkens.se)- 個人ブログを既存の所有ドメイン上に静的ページとして構成し、コンテンツ追加と基本的なSEOを同時に満たす最小実装を目指す
- 実装は小さな
template.html、markdown2、O1に依頼して作ったrender.py、そしてMarkdownで記事を書くことへとシンプルにつながる - テンプレートは
system-ui、最大幅70ch、color-scheme: light dark、viewport、UTF-8のような基本的なHTML/CSSだけを使う render.pyは./posts/{post}/eng.mdをHTMLに変換し、画像パスを調整したあと./blog/{post}.htmlとindex.htmlを生成する- Jekyll、Ghost、WordPressがなくても、静的レンダリングとホスティングだけで運用可能なブログを作れることを示す
最小ブログの要件と実際の構成
- 出発点は4つの要件だった
- すでに所有しているドメインを使うこと
- 現代のWeb標準に従い、十分なSEOを持つこと
- 新しいコンテンツの追加が非常に簡単であること
- すべてのページが静的にビルドされること
- 実際の実装フローはシンプル
- 小さな
template.htmlを書く pip install markdown2を実行する- O1に
render.pyスクリプトを依頼する - 記事を書いたあとレンダリングしてホスティングする
- 小さな
- Jekyll、Ghost、WordPressのような既存のブログエンジンは使わない
テンプレートとレンダリングスクリプト
template.htmlは基本的なHTML文書構造と最小限のCSSだけを含むcolor-scheme: light darkでライト/ダークのカラースキームを指定する- 本文スタイルは
system-ui、sans-serif、最大幅70ch、行の高さ1.5、文字サイズ1.25emに設定する id="head-link"が付いたホームリンクと{{ content }}プレースホルダーを使う
render.pyはmarkdown2でMarkdown記事をHTMLに変換する- 入力ディレクトリは
./posts、出力ディレクトリは./blog - 各記事は
./posts/{post_directory}/eng.mdから読み込む - 最初の
#ヘッダーを記事タイトルとして使う fenced-code-blocks、header-idsオプションでMarkdownを変換する- 画像パスの
<img src="を/posts/{post_code}/基準に書き換える - テンプレートの
{{ content }}を変換済みHTMLに置き換え、タイトル文字列も記事タイトルに変更する
- 入力ディレクトリは
- インデックスページも同じスクリプトで生成する
greetings.mdを先にHTMLへ変換する- 各記事タイトルを読み取り、
/blog/{post_code}.htmlへのリンク一覧を追加する - 最終結果を
index.htmlとして保存する
- 記事は2025-03-31に手動で作成された
5件のコメント
私も現在、自分のブログをちょうど上のように運営しています。個人的な要件を満たすSSGを作って使っているんですよ。サムネイル画像、カテゴリー、タグ機能を活用するために個別のカスタム機能を入れているというわけです。添付する画像は自動でwebpに変換して参照するようにしていて、そのおかげでレンダリング速度にもとても満足しています。
おお、そういうカスタム機能は直接コードを書きながら追加していかれるんですか? 私もいつもDIYでやろうと思いつつ、以前から使っていたSSGブログフレームワークが提供する拡張機能やプラグイン機能のせいで、ためらってしまうんですよね。
欲を手放し、欲さえ手放せば、あとはそれほど難しくありません。ssgもAIに頼めばコードは全部書いてくれるし、機能を追加してほしいと頼めば実際に全部追加してくれます(笑)
フォントさえきれいなものを選べば、かなり見られるものになりますね。
Hacker News の意見
このブログ記事のチャートを思い出した: https://molodtsov.me/2023/02/how-to-start-your-blog-in-2023/
静的サイトジェネレーター(SSG)の沼にはまると、本来書きたかった文章ややろうとしていたことの代わりに、SSGそのものについて書いたりいじったりする時間が大半になってしまった
結局 SSG を捨てて WordPress をインストールし、気にしないことにしたら、かなり解放感があった
目的がいじることで、その過程を書くことなら問題ないし、いじることが執筆の邪魔にならない人も問題ないが、自分はそうではなかった
文章を書こうとする瞬間に最後に必要なのは、先延ばしにする言い訳だ
WordPress とすべてのプラグインは最新状態を保たないと侵害される可能性があり、BDFL は些細な個人的理由でセキュリティアップデートの配信や受信へのアクセスを遮断できる人物でもある
静的サイトにはパッチを当てるべきセキュリティ脆弱性がないので、SSG プロジェクトが管理者の問題で完全に崩壊しても大きな問題ではないが、WordPress では非常に重要になる
訪問者がコメントを残す方法が必要だったので Disqus を追加し、結局いくつものサービスと大量の JavaScript が混ざったごった煮になった
数年前、あらためて自分のデータを直接所有し、外部サービスに依存しないようにしようとして、Disqus のコメントをエクスポートしたあと Serendipity をいじり、最終的に WordPress に落ち着いた
コメントと Markdown ページを取り込めたし、Fediverse にすべて公開してくれるプラグインもあった
SQLite で動くようにして自動更新をオンにしておくと、実質的にメンテナンス不要になった
必要ない可能性が高い機能のために、あまりにも多くのメンテナンスが必要になる。最新状態を保たないとボットネットの一部になりかねない
たいていのブログには静的サイトジェネレーターで十分で、メンテナンスが必要だとしても自分の望むタイミングで行えばよい
本当に欲しかったのは、公開のためのコマンド1つと、記事に画像を簡単にドラッグ&ドロップする方法だった。前者はうまく機能し、後者は Jupyter Notebook の公開機能で可能だ
絶対に望んでいなかったのは、「HTML をクライアントに送る」ためにデータベースのような負担が発生する方式だった
良いが、ブログと呼ぶには小さな機能があと2つ必要だと感じる
第一に、記事を日付順に並べ、最新記事が先に来るようにし、日付をどこかに表示する必要がある。最小構成を保つなら、記事ファイルのメタデータ、たとえば作成時刻を使えばよい
第二に、当然 RSS フィード が必要だ。既存のスクリプトと最小限の RSS テンプレートだけで、リンクとタイトルだけを含む簡単なフィードは容易に作れそうだ
「フォロー」されることが常に良いわけではなく、読者に合わせようとするプレッシャーを生むことがある。ソーシャルメディアを悪くしているまさにその要因だ
1番については、TOML のような形式でメタデータを含むファイルを自動生成する方向に傾いている
2番の RSS は確実に追加する予定だが、1番に依存している :-)
独立したウェブサイトが昔から好きで、自分のウェブサイトも約25年前に似たような形で始めた。
当時、自分が知っていた適切な技術は Classic ASP だけだったので、最小構成でシンプルに ASP だけで作った。
今は Common Lisp で静的生成されるサイトとして動いており、この構成が長期的な設定になりそうだ: https://github.com/susam/susam.net/blob/main/site.lisp
単純なページのまとまりとして始めるのは、最小限の実用的なウェブサイトを作る良い方法だったが、時間がたつにつれて RSS フィード、日付順のブログ一覧、タグ別インデックス、ツール・ゲーム・デモのようなブログ以外のコンテンツ対応、サードパーティなしのコメントといった機能が必要になった。
要件が増えるたびにソースも大きくなり、数百行だったコードが今では約 1300行の Common Lisp になっている。
それでもコード全体を一度に頭の中に収められ、バグが出たら10分以内に推論して直せる程度には保ちたい。
最近は、好きなブロガーたちの記事一覧を提供する ブログロール を追加したい誘惑がある。フィードリーダーの代わりにもなるかもしれないが、メールまで読むものに肥大化しないよう注意したい。
ソースコードはここにある: https://github.com/brilee/modern-descartes-v2/blob/master/ma...
RSS フィード、日付順のブログ一覧、タグ付けシステム、ファイル監視による再コンパイル付きのローカル開発サーバーが含まれている。
現在のバージョンは 1000行未満の Python スクリプト として維持している: https://github.com/llimllib/obsidian_notes/blob/c93b9b5c46fe...
記事のまとまり、インデックス、スライドショーのような派生ページを作り、人やビデオゲーム向けのタグのバリエーションも作った。
サムネイルギャラリーや引用ボックスのような一般的なウィジェットの見た目や感触も完全に制御できる。
高レベルの参考資料として使えるかもしれない。
今後、シェーダーやウェブゲームも埋め込みたくなるかもしれないが、複雑さが大きくなりすぎないことを願っている。
ブラウザが text/markdown と text/gemini をネイティブ対応してくれるとよい。
ブラウザが PDF をレンダリングできるなら、Markdown/Gemini コンテンツ用の簡単なフォーマッターと、ユーザーが指定できるスタイルシート程度を入れるのは、そこまで難しくないように思う。
今でも text/plain のブログを書くことはできるが、実際のハイパーテキストではないので SEO で不利になる。link ヘッダーで何か魔法を起こせるかもしれないが。
別の形式をサポートすれば、きれいに公開するためのハードルが下がり、制御権がユーザーに戻る。
まず、どの Markdown 方言と拡張を使うかについてブラウザ各社が合意しなければならない。Markdown はほとんどテキスト形式界の CSV のようなもので、誰もがそれぞれのやり方で使っているからだ。
最小限にしすぎると役に立たないという不満が出るし、拡張を選ぶと肥大化しているという不満が出るだろう。
長期・短期の長所と短所について慎重に議論しようとしても、「完璧を善の敵にしてはならない」という言葉で遮られるかもしれない。
特定の機能セットに合意できたとしても、実際にそれだけの価値があるのかも疑問だ。
PDF をブラウザで直接読むことは十分に一般的だが、Markdown を直接読むメリットは、世界中のソフトウェア開発者の一部と、変わり者が5人くらいにしか及ばない可能性が高い。
だから、生きている間にブラウザのネイティブ Markdown レンダリングを見られなくても驚かないと思う。
ブラウザのネイティブ対応より新しいバージョンが必要なときに使える XSLT 用ライブラリもあるし、jpegxl などさまざまな形式向けのライブラリもある。
html_content = html_content.replace('Minimum viable blog', title)だと、記事中にMinimum viable blogという文字列が出るたびに現在の記事タイトルへ置き換わるのか? バグではないのか?記事にあるコードは O1 が作った最初の草案で、この文字列は
{{ title }}に置き換えられた。約15年にわたって ミニマルブログ を試してきて、いくつか学んだコツがある。
const title = lines.match(/# (.+)/)[1]くらいでも十分なので、frontmatter を避けられる。自分のブログは記事が多くなりすぎて、ページネーション、タグ、カテゴリー、ソートが必要になったことはない。
JSX は https://immaculata.dev/guides/enabling-jsx.html のような怪しげなハックを使うと、純粋なサーバー側の文字列ビルダーとしてかなり良い。
今では GitHub Pages も https://immaculata.dev/guides/using-gh-pages.html のようなもので、Jekyll の代わりに任意のビルド手順を使いやすくなっている。
highlight.js は、HTML に3行追加するだけで済む、とても簡単なコード構文ハイライトの王様に近く、shiki は素晴らしいが遅い。
Hugo/Zola + Cloudflare Pages のような標準的な静的ブログフレームワークを使えば簡単
自分のブログも 100KB 未満の最小構成で、原文の著者が挙げた基準をすべて満たしている
Hugo Blog Awesome テーマを使い、512kb のガイドラインに従ってページサイズを確認し、画像と不要な JS を削除した。もともと多くはなかった
参考: https://512kb.club, https://radar.cloudflare.com/scan
しばらく「MVB」を運営していたが、自分のものはもっとシンプルだった
HTML ページを 1 つ置き、記事は
.txtファイルで書いて、ホームページを手動で更新していたかなり冗長ではあったが、それでも現代の Webを相手にするよりは簡単だったと思う
その後、より洗練された方向に移り、今は個人サイトとブログに Astro を使っているが、本当に素晴らしい
Astro はランディングページで「コンテンツ中心のサイト」に最適なプラットフォームだと主張しているが、6か月使ってみて同意するようになった
ブログを作るのに必要なほぼすべてについて、明確で追いやすい慣例を提供し、余計な部分をそぎ落としている
いくつかのサイトで Bun JS と JavaScript 文字列内の HTML を使う方式を試してみた
Bun には変更時に静的 HTML を再生成する
—hotフラグがあるIntelliJ IDE は文字列の上にある
// language=htmlコメントを検出して、内部の HTML をフォーマットし、構文ハイライトもしてくれるテンプレート言語の代わりに純粋な JavaScript 関数を使えば、テンプレート言語でどうやるかを調べずに、必要なロジックを直接書ける
肥大化しすぎて読み込みに時間がかかる Web サイトにうんざりして、自分のブログにもかなり似たアプローチを使っている: https://blog.borrego.dev
ソース: https://github.com/agubelu/blog