---
title: なぜ AI 全盛の時代に、技術ブログをリニューアルしたのか
tags: [Web, プログラミング]
imageUrl: ./cover.webp
publishedOn: 2026-08-14
lastModifiedOn: 2026-08-14
---

技術の使い方を調べるとき、筆者は Web 検索より先に AI で当たりをつけています。
手順や API の仕様なら、たいていそれで済んでしまいます。
原典に当たりたいときでさえ、Web 検索から始めることはずいぶん減りました。

筆者が最後にこのサイトへ記事を書いたのは、2017 年 12 月 25 日でした。
修士 2 年の冬から 9 年近く、ブログには何も書いていません。
技術ネタは全部、職場の times に流していました。

そもそも AI が手順を教えてくれて、情報発信にしても times なら数分で同僚からの反応が返る時代です。
記事を配信するためだけに、わざわざ個人サイトを作り直す理由はありません。
それでも作り直したのは、答えだけでなく、そこへ至るまでの思考も記録して、伝えてみたくなったからです。
ついでに、読み終わった人が気軽に反応を返せるようにしてみました。

この記事では、times から離れて個人サイトへ戻った理由と、読者に記事を最後まで読んでもらうために、サイトにどんな機能を持たせたかをまとめました。

## times は居心地がよすぎた

筆者の職場には times 文化があります。
各自が自分のチャンネルを持ち、作業ログでも技術メモでも独り言でも好きに流します。
筆者もそこに、調べたことや詰まったことを書いていました。

書いてから「書いてよかった」と思えるまでが、とにかく短いんですよね。
誰かが読んで、質問や絵文字のリアクションを返します。
「それ自分もハマりました」の一言が返ってくることもあります。
書いてよかった、とすぐ思えます。

ただし、times に書いたものは社外に出ません。
読む人は同僚に限られます。
この 9 年近く、対外的な発信はほとんどありませんでした。
届く範囲が社内に閉じると分かっていても、times は居心地がよすぎました。

## 読みたくなる記事には思考が書かれている

筆者自身が AI で先に調べるようになっても、個人のブログには最後まで読んでしまう記事があります。
調べたかったことは最初の数行で済んだのに、そのまま惹き込まれて気がついたら読み終えてしまいます。

そういう記事には、答えだけでなく、思考の過程が書かれています。
なぜその設計にしたのか、何を試して駄目だったのか、どこで詰まったのか。
「A を採用した」という結論だけでは、ほかの案を退けた理由も、何を守るための選択だったのかも分かりません。
答えは残っても、条件が変わったときに考え直す材料は残りません。

AI が手順を教える時代なら、人間が書く記事にはナラティブを意識した思考の過程を残したい。
それを読んでもらう場所として、個人サイトをもう一度選びました。

## 情報発信だけのサイトをやめる

旧サイトは Jekyll と GitHub Pages でした。
Markdown を書いて push すると静的な HTML が生成されて配信される、よくある構成です。
2010 年から 2017 年までの記事が 27 本あって、高校生のときに書いたものも混ざっています。
読み返すとなかなか恥ずかしいのですが、消さずに全部移しました。
昔の URL も 308 リダイレクトで生かしています。

静的サイトのままでも記事は配信できます。
でも今回ほしかったのは、ファイルの置き場だけではありません。
times のように、いろいろな emoji でリアクションできる機能がほしい。
どうすれば人間に最後まで読んでもらえるのか、サイトを使って試してみたい気持ちもありました。

そこで、サイトを Cloudflare Workers の上に作り直しました。
記事のメタデータは D1、本文と画像は R2、読者ごとの状態は KV に置いています。
モダンな技術スタックで、いわば "対外的 times" を作ったわけです。

実装そのものは公開しているので、細かいところはリポジトリを読むか、AI に聞いたほうが早いはずです。
よかったら覗いてみてください。

https://github.com/yantene/yantene.net

## モダン Web の当たり前をそろえる

まず、モダン Web として求められる機能には一通り対応しました。

- PWA: ホーム画面にインストールでき、一度読んだページは Service Worker によってオフラインでも開けます
- レスポンシブ対応: スマートフォンから大きな画面まで、同じ記事を無理なく読めます
- 画像: 遅延読み込みに対応し、同期時に取得した寸法を HTML に埋めてレイアウトシフトを防ぎます
- アクセシビリティ: 操作部品に ARIA 属性を付け、端末の設定に応じてアニメーションを抑えます
- メタデータ: OGP、構造化データ、Atom フィード、sitemap を出します
- セキュリティ: スクリプトは nonce を使った Content Security Policy で縛ります

ここまでは、記事の中身以前の話です。

## 記事の原文を、そのまま渡す

読んだものを読者がどう扱うかは、読者が決めることです。
手元に保存する、引用する、AI に要約させる。
どれも書き手が口を出す話ではありません。

記事の URL の末尾に `.md` を付けると、原文の Markdown がそのまま返ります。
`.md` を付けなくても、`Accept: text/markdown` で名指しすれば同じものが返ります。
もらったリンクをそのまま AI に渡すときに、URL をいじらずに済みます。

名指ししたときだけ、というのが要点です。
ブラウザの Accept には必ず `*/*` が入っているので、これを Markdown と数えると、記事を開いた全員に原文が配られます。
ワイルドカードは HTML に倒し、Markdown は名指しでしか取れないようにしました。

返すのは、GitHub に置いた Markdown そのものです。
フロントマターも含みますし、画像の相対パスも書き換えません。
加工した Markdown を原文と呼びたくなかったからです。

## 「よく読まれている」を、どう決めるか

トップページには、よく読まれている記事のランキングを出しています。
ナイーブに実装するなら、アクセス数の多い順に並べるでしょう。
ただ、それでは新着記事に不利で、古い記事がいつまでも上位に居座ります。
そこでアクセスカウンタの重みに半減期を設け、最近のアクセスほど優遇することにしました。

ところが、重みを時間とともに減らすには、全記事のスコアを定期的に計算し直すバッチが要ります。
そこで発想を裏返しました。
古い重みを減らすのではなく、新しいアクセスの重みを増やします。
基準日から半減期 1 つぶん進むごとに、そのとき起きたアクセスの重みを 2 倍にします。
こうすると、一度記録した値には二度と触らなくて済みます。
バッチが丸ごと消えました！

ここからは記事の本筋を少し外れるので、急ぎの人は次の節まで飛ばし読みして OK です。
とはいえ、趣味のサイト作りで一番楽しいのは、こういう寄り道ですよねｗ

重みは経過に対して指数的に膨らみます。
基準日を $t_0$、半減期を $H$ 日とすると、$t$ 日目に起きたアクセスの重みはこうなります。

$$
w(t) = 2^{(t - t_0)/H}
$$

半減期を 30 日にすると、素の値はやがて倍精度に収まらなくなります。
基準日を 2000 年 1 月 1 日に置いているので、ざっと計算すると限界は 2080 年代のどこかでしょうか。
そのころ 90 歳近いやんてね翁は、きっとこの制約を忘れて記事を量産していることでしょう。
そんな中、全記事のスコアが $\infty$ になってランキングが壊れたら大変です。

そこで、スコアは対数で持つことにしました。

$$
\ln w(t) = \frac{t - t_0}{H} \ln 2
$$

指数が消えて、経過に対して線形にしか増えません。
100 万年でも $8.4 \times 10^6$ にしかならない計算です。

しかも、対数で持つと嬉しい副産物があります。
対数は単調なので、順序は素の値のときと変わりません。
保存した列をそのまま降順に並べれば人気順になります。
読み出すときに計算を挟まずに済みます。

足し算にはいわゆる log-sum-exp を使います。
素の値に戻すと溢れるので、対数のまま和を求めるやつです。
$\ln a$ と $\ln b$ の大きいほうを $m$、小さいほうを $n$ とすると、和の対数はこう書けます。

$$
\ln(a + b) = m + \ln\left(1 + e^{\,n - m}\right)
$$

大きいほうを括り出してから足すので、指数関数の引数が 0 以下に収まり、途中の計算でも溢れません。
リアクションもこの足し算に乗せていて、1 つを閲覧 5 回ぶんとして数えています。

……と、ここまでは順調でしたが、最後にひとつ詰まりました。
まだ読まれていない記事のスコアを 0 にすると、対数が $-\infty$ になります。
下限を「投稿日に 1 回読まれた」ぶんに引き上げて解決しました。
おかげで初回かどうかで場合分けする必要がなくなり、まだ読まれていない記事同士も新しい順に並ぶようになりました。

この仕組みだと、古い記事が上位に来ることがあります。
それは昔の記事がいまも読まれているということなので、正しい順位です。

## リアクションは作り、コメント欄は作らない

冒頭に戻ります。
times で得ていたのは、速さと絵文字のリアクションでした。

リアクションは作りました。
記事の上と末尾に置いたハートを押すと「いいね」になり、パレットから別の絵文字も選べます。
押せるのは 1 記事につき 1 つです。

D1 が持つのは、どの絵文字が何回押されたかだけです。
誰が押したかは残しません。
その代わり、読者が何を押したかは、読者ごとのセッションに置いています。
だから押し直しも取り消しもできますし、誰が何を押したかの一覧はどこにも残りません。

一方でコメント欄は作りません。
感想も議論も、Bluesky や X に逃がします。

自前でコメント欄を持てば、悪口を書かれても非表示にできます。
それでも、会話の場は読者が普段いる場所に置きます。

読者は筆者にコメントしたいというより、自分の意見を書いて他人とやりとりしたいことが多いはずです。
会話の場は読者のホームであるべきで、筆者のサイトに呼びつけるのは筋が違います。
閉じこもるより記事の宣伝にもなります。

リアクションを自分で持ちながらコメントを外に出すのは、ちょっとちぐはぐに見えますよね。
リアクションは、記事が読まれた手応えを筆者が受け取るためのものです。
コメントは、書き手も加わる会話です。
前者だけ自分で持ちます。

会話を外に置いても、外で交わされた会話との接点までなくしたわけではありません。
このサイトは Webmention に対応しています。
他所のサイトからリンクされたことを、リンク元がこちらに通知する仕組みです。
会話は外、参照は内。

速さのほうは諦めました。

times に書けば、数分で反応が返ります。
ただし、読むのは同僚だけです。
ここに書けば、反応は何日か経ってから来ます。
届かないまま終わるかもしれません。

その代わり、読む人を同僚に限定しません。
学生のころの記事も、筆者が放置していた 9 年近くのあいだ、そこに残っていました。

## あとは面白い記事を書くだけ

今回、思い切って個人サイトを作り直しました。
読むのを邪魔するものを減らし、原文をそのまま渡し、読み終わった人が反応を返せる場所にしました。
まだ試したいアイデアはたくさんあります。

ただし、人に読まれる仕組みだけでは、人に読まれる記事になりません。
面白い題材を見つけ、それを面白く伝える文章力が要ります。
ここだけは Cloudflare Workers に載せても動きません。
困ったもんですねｗ

ともあれ、サイトも文章もチューニングしながら、また書いていきます。
これからよろしくお願いします！
