- ソフトウェア業界と既存のソーシャルメディアに疲れ、Mastodonも試したが、実際に必要だったのは人中心のタイムラインではなく、Web上の記事や通知をまとめて見られる個人用フィードリーダーだった
- 目標は、RSSリーダーのメール受信箱のような未読リストではなく、TwitterやMastodonのホームフィードのように、開くたびに興味深いコンテンツが流れてくるストリーム型インターフェースだった
- 設計基準はユーザー体験 > 運用のしやすさ > 開発のしやすさで、htmx・hyperscript、モノリシックなWebアプリ、SQLite、Python、geventとHuey拡張のように、シンプルに運用できる選択肢を優先した
- 実際に使う過程で、アプリ内で記事を読む、あとで読むためのpin、bookmark、ソースの発行頻度別ソート、スクロール時の自動「既読」処理といった機能が追加された
- 約3カ月のゆるやかな作業の末にfeediを作り、数カ月間「インターネットの最初の画面」として使うことで、消費する情報へのコントロール感を取り戻した
バーンアウト後に再び見つけたWebの使い方
- 連続した悪いプロジェクトとソフトウェア業界への幻滅から、キャリアのバーンアウトを経験した
- 仕事を減らし、退職し、治療を始め、食事・運動・瞑想といった習慣を見直した
- しばらくプログラミングやソフトウェア関連の読書から距離を置き、最後に使っていたソーシャルメディアであるTwitterからも離れた
- How to Do Nothingを読む過程で、代替的なオンラインコミュニティとしてMastodonを改めて見直すことになった
Mastodonで確認した限界
- Mastodonはアルゴリズムによる仲介なしに時系列フィードを提供し、フィードを再び自分で制御している感覚を与えてくれた
- ソフトウェア業界やWebに似た違和感を抱く人たちは、RSS、BBS、digital gardens、webringsのような過去のWeb要素を見直したり、よりオープンで独立したWebを想像したりしていた
- 実際の利用目的は、マイクロブログよりも情報ハブに近かった
- 人をフォローした理由は、その人たちがWebサイトに記事を投稿したときに通知を受け取るためだった
- botをフォローした理由は、リンクアグリゲーターのコンテンツを受け取るためだった
- IndieWebのsocial readersという概念に触れたあと、必要なツールはMastodonではなく、自分で調整できるフィードリーダーだという判断に至った
個人用リーダーのユーザー目標
- 一般的なRSSリーダーのメール受信箱のような未読リストではなく、アプリを開くたびに興味深いコンテンツが流れてくるストリームが欲しかった
- フィードには複数の出所が一緒に混ざっている必要があった
- ブログ、雑誌、ニュースサイト、リンクアグリゲーターの記事
- Mastodon、Goodreads、GitHubのような個人アカウントの通知
- 出所ごとにデータ形式が異なっていても、一貫した見た目と感触を作れるように、パースのカスタマイズが必要だった
- 完全なIndieWebリーダーのソーシャル機能は実装対象ではなかった
- コメントするために別タブを開くことは問題ではなかった
- コンテンツがサードパーティサイトに散らばっていても構わなかった
- 短期目標は、このツールが主な、ひいては唯一のWeb情報源になり得るかを素早く確認することだった。そうでなければ、プロジェクトはすぐに畳むつもりだった
開発原則と範囲
- 開発原則は
user > ops > devだった
- 作業の優先順位と設計上のトレードオフでは、開発のしやすさよりも運用のしやすさを選んだ
- そのさらに上にユーザー体験を置いた
- 個人用アプリなので、「ユーザー優先」とは、ドッグフーディングしながら自分の必要を先に満たすという方法だった
- 理想的なユーザーを想定するより、自分自身に人間工学的に合うツールを作るほうが有用である可能性が高いと考えた
- このプロジェクトは学習プロジェクトやポートフォリオプロジェクトであってはならなかった
- 目標は生産性ではなく、ソフトウェア開発の楽しさと再びつながることだった
- 楽しさは「何かを作ること」よりも「自分で作ったものを使うこと」から来るべきだった
- 単一のターゲットユーザーを仮定することで、いくつもの判断を先送りできた
- すぐには必要ないユーザー認証は後回しにした
- Kindleへ送るような非常に具体的な機能は初期に扱えた
- フィードパーサーのカスタマイズやMastodonログインのように、プログラミング知識を前提にできた
UIとアーキテクチャの選択
- ノートPCだけでなくスマートフォンからもアクセスするには、Webアプリケーションである必要があった
- 1つのインターフェースで2つのデバイスをサポートする、費用対効果の高い方法だった
- 慣れたHTMLとCSSを使えた
- 状態をサーバーに保存することで、デバイス間の同期を解決できた
- Web UIはある程度動的である必要があったが、別個のフロントエンドアプリケーションや新しいフレームワークの学習は望まなかった
- boring techとradical simplicityの助言に従い、サーバーサイドレンダリングのライブラリを探し、htmxとhyperscriptを併用した
- 運用しやすくするため、デプロイとローカル設定は簡単であるべきで、DockerやNixのようなインフラを前提にしたくなかった
- Aaron Pareckiが説明した正式なIndieWeb readerはMicropub、Microsub、Webmentionsなど複数のプロトコル別コンポーネントに分かれるが、個人利用では開発と運用を複雑にするだけで、大きな利点はなかった
- 結果としてモノリシックなWebアプリケーションを選び、データベースにはインストール・設定するコンポーネントを減らすためSQLiteを使った
言語とバックグラウンドジョブ
- Goはシンプルで汎用的で、ガベージコレクションがあり、十分に高速で、並行性モデルとデプロイしやすいバイナリが利点のため、このプロジェクトによく合っているように見えた
- しかしGoを一行も書いたことがなく、プロジェクトが学習プロジェクトに変わることは望まなかった
- すでに慣れている言語の中で最も速くプロトタイプを作れるPythonを選んだ
- Pythonは環境と依存関係、とくにホストOSのライブラリ依存が欠点として残った
- 定期的なfeed pollingのために別コンポーネントを増やしたくなく、調査の末、geventとHueyのmini-huey拡張を使って、アプリケーションプロセス内でバックグラウンドジョブを実行した
- 一方でPythonには、HTTP、feed parsing、scrapingに使える優れたライブラリがあった
テストを先送りした理由
- 初期にはテストを書かないことにした
- 機能を追加・削除・再配置しながら実験する予定だったため、ユニットテストの維持コストは価値より大きいと見た
- 小さなロジックバグは許容でき、自分で毎日使うアプリなので、重要なバグは時間とともに明らかになると期待した
- 信頼性を与えるには統合テストのほうが価値があると考えたが、このプロジェクトの多くのバグは外部ソース連携とUIから生じた
- 統合テストが一部のバグやリグレッションをより早く捕まえられた可能性はあったが、初期コストを払うほどの価値はないと判断した
実際の利用が機能を導いた過程
- 毎日エンドユーザーとして直接使うことで、アイデア、実験、優先順位が決まっていった
- 複数のUIレイアウトや機能を試したあと、利用パターンが定着した
- アプリを開く
- メインフィードをスクロールする
- あとで読む項目をpinする
- 今読む項目を開く
- あとで参照する項目をbookmarkする
- アプリを離れずに記事を読む機能が欲しかった。理由の1つは、paywallや同意ポップアップを避けることだった
- HTMLコンテンツ抽出のために複数のPythonライブラリを試したが、Firefoxが使うreadabilityほどうまく動作しなかった
- readabilityはJavaScriptパッケージだったため、オプション依存としてNode.jsを追加することになった
フィードのソートと「既読」処理
- 基本機能を備えたあとも、発行日順のソートだけでは興味深いコンテンツを見つけにくかった
- まれに更新されるブログ記事がMastodonのtootの後ろに埋もれる
- 雑誌の長文記事が日刊ニュース記事の後ろに埋もれる
- フォローしているソースはいずれも関心のある出所なので、発行頻度の低いソースのコンテンツを先に見たいと仮定した
- 月刊ニュースレターがここ数日のうちに出ていれば、マイクロブログや日刊ニュースより上に表示されるべきだった
- ソースを「frequency buckets」に分類し、頻度の低いbucketが先に見えるようフィードをソートした
- まれなコンテンツがアプリを開くたびにずっと上部に残り続ける問題を避けるため、下にスクロールすると項目を自動的に「already seen」として処理する機能を追加した
- この方法により、常に新しいコンテンツを見ながらも、まれな更新を見逃さないようになった
ローカルからVPSまで
- 最初はノートPCのターミナルタブでアプリを実行しながら、開発と利用を並行した
- フィードに表示されるコンテンツが気に入り始めると、ローカルネットワーク上のRaspberry Piサーバーに載せて、常にアクセスできるようにした
- Raspberry Piで常用するようになり、スマートフォンからのアクセスのためにモバイルレンダリングを改善した
- 外出中にもアプリを使いたくなる時点で、VPSへデプロイした
- VPSデプロイにより、先送りしていた認証とマルチユーザー対応を追加することになり、何人かの友人にベータテストのアクセス権を渡せるようになった
- VPS設定はドメインを買い、このWebサイトを作るきっかけにもなり、最初にインスピレーションを与えてくれたIndieWebの理想に近づく過程となった
feediの結果
- 約3カ月のゆるやかな作業の末に、個人用フィードリーダーfeediを作った
- feediは完成した製品というより、Emacs設定のように、いつも半分壊れているが身体になじむツールに近い
- 生産性の観点では正当化しにくいが、自分の条件に合わせて作ったツールなので満足感を与えてくれる
- 数カ月間、feediを「front page of the internet」として使った
- 個人用リーダーを使うことで、消費する情報を再びコントロールし、興味深いブログや雑誌を積極的に探し、発見と驚きにより出会いやすくなった
1件のコメント
Hacker News の意見
urlwatch(https://urlwatch.readthedocs.io/en/latest/)を設定しておくのはかなり楽しかった。特に Puppeteer のボイラープレートを乗り越えて、Chrome インスタンスで JavaScript サイトをスクレイピングできるようになると、Web を取りに行くのではなく、向こうから押し出されてくるように制御している感覚になる
Web サイトを気軽に監視しておいて、朝にざっと確認できる力は大きい。好きな会社の求人情報、現在の会社の採用/締め切り、セール・再入荷・整備済み品を待っている製品、COVID-19 の下水統計、アパートの物件、気になる GitHub リリース、重要な Web サイトの利用規約変更まで追跡できる
個人的には RSS リーダーと Telegram ボットもセルフホストしていて、実験用の小さな HTTP サイトもよく作るので DigitalOcean $5 Droplet を使っているが、毎日同じ時間に動く必要はないのでノート PC でも可能
個人用なので、関心のあるテーマの Twitter 更新の要約だけを受け取り、サイトそのものや激しい論争、うっとうしい広告は避けられる
今の IT の状態にはあまりに腹が立っていてうまく整理しにくいが、ときどき「自分の IT 担当者」という概念を想像する。近所の理髪師、かかりつけ医、仕立て屋、パン屋のように、デジタル生活の一部を担ってくれる人だ
小さなローカルインフラを持ち、パーソナライズされたフィードを作り、プライバシーとデジタル面の健全さを気にかけ、シンプルなインターフェースやオープンプロトコルを通じてフィードリーダーにつないでくれる、という形だ。映画、文章、ミーム、面白い動画まで扱うが、核心は収益最適化アルゴリズムではなく、話ができる人間がいることにある
地域コミュニティが運営するデータセンターを図書館のように置いたり、自宅インターネットでシンプルなコンテンツサービスを提供したりするアイデアも浮かぶ。だから Veilid(https://gitlab.com/veilid/veilid) のような発想が気に入った
Fediverse に移ってからより健全になったという話を聞くのも初めてではない。自分でも Puppeteer の上にスクリプトやミニアプリを載せ、ローカルの llamacpp で要約と推薦を回しており、今後さらに磨いて友人や家族に勧めてみたい
これらのスクリプトには「not a browser」という名前を付けた。HTML/CSS/JS をデータと一緒に配信する Web ではなく、データだけを提供し、どう表示するかはユーザーが決める Web が欲しい
ユーザーに敵対的なアルゴリズムも、広告ベースのシステムもなく、概してユーザーを優先し、オープンプロトコルを掲げるソフトウェアだ。IT 業界にいて自分でサーバーを運用できるなら可能だが、そうでない人たちはどうすればいいのかが問題だ
個人の「IT 担当者」というアイデアは興味深い。巨大テック企業やアルゴリズムから離れて、もっと個人的なものを使いたいが技術的手段を持たない人たちに、こうしたサービスを提供できるのか気になる
医療データも似ている。自分の医療記録が MyChart や複数の独自システムに保存され、コントロールできないのが嫌だ。ポケットの中にはスーパーコンピュータがあるのに、なぜ自分の記録のコピーを自分で保管し、診察時に医師へ選択的に共有できないのかわからない
いまだに病院同士がファックスをやり取りしなければならないのもおかしい。ボタン1つで自分のデータを共有できるべきだ。Apple Health が一部の機能では最も近いが、米国内での採用はほとんどなさそうで、しかも Apple ユーザーにだけ有利だ。健康データは、ローカルで動く Apple Health のような形であっても独自システムに閉じ込められてはならず、オープンプロトコルと実装のエコシステムが必要だ
マーケティングと強欲がインターネットを支配する前には、短いながらも良い時期があった。エンドユーザーに有益なアプリを備えた Synology NAS のような製品に、それを手助けする「自分の IT 担当者」が付く形なら、うまく機能するかもしれない
個人データとお金を吸い上げようとする構造でなければ、ユーザーにとってはユートピアに近いだろうが、経済性はおそらく低いマージンと大きなリスクを伴う事業になりそうだ。たとえばファイル消失に対する責任のような問題は大きい
コードを一度書けば、ほぼ追加コストなしに百万回実行できる構造だ。あらゆる構造的な力が逆方向に働いているように見える。AI が私たちの仕事をすべて置き換えた後なら、むしろもっと可能になるのかもしれない
Jenny Odell の How to Do Nothing は本当に素晴らしい本だ。Hacker News の一般的な読者層とは少し違うかもしれないが、アテンションエコノミーが強いる偽りの「生産性」の圧力を感じ始めている人には強く勧めたい
Jenny Odell の他のプロジェクトも見る価値がある。たとえば The Bureau of Suspended Objects(https://www.jennyodell.com/bso-cjm.html) がある
同じ文脈で Jenny Odell の Saving Time もおすすめする。静かだが非常にラディカルな本で、個人的には2冊のうちこちらのほうがよかった。語りの焦点がより絞られていた
単なる個人フィードを超えて、時間制限があり、気が散らないフィードがほしい
自分がフォローしているあらゆる文章コンテンツを集め、毎日約30分で読める分量になるよう項目の組み合わせを選んでくれるといい。ブログ記事、ニュース記事、ツイートなどすべて含めるべき
ChatGPTでも他のツールでも使って、最も「栄養価の高い」コンテンツをふるい分け、口論より価値のあるコンテンツを優先してほしい。その後 Kindle や reMarkable タブレットに送って、色や点滅、速いインターネットから離れて読みたい
次の段階としては、友人のフィードを購読して、ときどきそのフィードの「ゲスト」コンテンツも受け取ってみたい
GPT 要約を追加するアイデアは気に入っていて、他の人にも関心があるなら整理して共有できるかもしれない。今はローカルで使う単純な JavaScript アプリだが、このアイデアは当初考えていたよりずっと面白そうに見える
Douglas Engelbart だった気がするが、エージェント関連の資料が見つからない。別の技術専門家だったかもしれない
自動テストを最初はあえてやらない、という意識的な決断が目に留まり、共感した。テストを書かないと落ち着かない感覚を乗り越えるのにかなり時間がかかったが、個人用のおもちゃプロジェクトでは今では似たようなアプローチをしている
あまりにも多くのプロジェクトが最初の1日くらいで死んでしまった。本来なら勢いを得るべき時点なのに、テスト基盤や CI パイプラインを作っているうちにやる気を失ったからだ
今は、テスト不在が実際の問題になったらその時に追加する、という基準で作業している
開発者が多くコードベースの大きい成熟したプロジェクトで必須のものが、小さな一人プロジェクトでは煩わしいこともある
その後は問題が起きるたびに、その場しのぎでテストを追加することに集中する
数年前、個人プロジェクトで呼吸ガス分析器を作り、Bluetooth で接続してデータをリアルタイム表示するソフトウェアを書いた。科学計算を正確に行う必要がある関数には単体テストが非常に有用だったが、インターフェースの他の部分のテストは振り返るとほとんど時間の無駄だった
関数がもう変更されないと確信できた後は、テストをすべて削除した。一人で開発する場合は、手動テストだけでも十分なことがある
将来の話を率直にするために、新しい匿名アカウントを作った
この記事は未来の自分が書いたように見えて驚いた。著者との共通点があまりに多く、信じがたいほどだった
バーンアウトに気づき、来年初めに仕事を辞める計画を立てていた。匿名アカウントを作った理由もこれだ。おそらく似たように感じている人は多いだろう
さらに驚いたのは、著者がやったことが、自分が休んでいる間にやってみたいと空想していたこととほぼ同じだった点だ。オープンウェブ/IndieWeb にどう参加するかを考え、この領域で実験するアプリを作るつもりだった
まれに投稿されるものが洪水の中に埋もれないようにする問題や、どの言語と技術を使うかといった技術的な悩みまで似ていた。Web 開発は10年ほど遅れているが、モダンな Web 技術で何か作ってみようとも考えていた
一方では、最近の考えや感情が認められたようでうれしい。正しい道に進んでいる感じがする。もう一方では、著者が先にやり遂げたことが悔しく、嫉妬も残っている
当時、自分だけの RSS リーダーが欲しかった。既存のリーダーは嫌で、受信箱ではなく普通のブログのように見え、好きなようにデザインできるリーダーが欲しかった。そこで RSS フィードパーサーを作り、自分の普通のブログのように見えるようデザインした
その後、RSS フィードに要約しかなければ全文を取得するよう変更した。リーダーの外をクリックして全文を見に行きたくなかったし、すべてがフィードリーダーの中にあってほしかった。基本的なページスクレイパーができると、RSS のないサイトにも使い、ソーシャルメディアが流行したときには特に役立った
実際のソーシャルサイトに行かなくても、欲しいコンテンツだけを自分のフィードで見られた。20年ものなので PHP や XSLT のような古い技術でできており、今でもそのままだ
ともあれ、自分で作ることを強く勧める。楽しいプロジェクトだ。古くて荒削りで、スクレイピングも完璧ではなく欲しいコンテンツが出ないこともあるが、自分のもので、20年間毎日使っているリーダーなので気に入っている
似たような試みをしたからといって、効果がない理由はない。個人リーダーを実装した最初の人でもなかった
面白いのは、リンクしていた IndieWeb の記事を読み返してみると、その記事のアイデアをほとんどそのまま繰り返していたように感じたことだ。「みんなのためのソフトウェアを作ろうとせず、自分自身のために作れ」というような助言だ
汎用的に作り、他人が使いやすいようにしようとすると、自分にとっての使い勝手を損なう妥協をしたり、存在もしない想像上のユーザーのために設計したりすることになり得る。利己的に作って、自分にとってより有用にせよ、という意味だ
本当に新鮮だった。この1年、とても似たバーンアウト/回復の道をたどり、有用な個人用ソフトウェアを作ることで再び仕事を楽しめるようになった
もう一つの大きな利点は、使いたい「非正統的」な技術を思う存分試せることだ。最新式の単一バイナリ PHP 実行ファイルを作る、本番環境で SQLite を使う、Docker なしでデプロイする、といったことが楽しさを与えてくれる
こうした作業は本業にも波及効果があった。個人用リポジトリで新しい手法や最適化を見つけ、本業に持ち込むことがよくある
技術者がサイドであれこれ触ってみて、そこで学んだことを仕事に有用で、ときには価値ある形で持ち込むことが多いのは興味深い。ところが雇用主は時にそうした努力を軽んじたり、熱意を妨げたりもする
自分が間違った種類の組織で働いてきただけかもしれない。それでも、そうした波及効果の利益を得られたなら何よりだ
読む/消費するもののチェックリストより、フィードという考え方のほうが好き。数年のあいだにRSSリーダーをいくつか使ってみたが、長く定着はしなかった。
もう一つの受信箱を管理する必要があるのかと思っていた。それでも feedi(https://github.com/facundoolano/feedi)は試してみるつもり。
設定する前は、HNに何か新しい投稿があるかな、Reutersにはあるかな、と目的もなくあちこちクリックしていた。自分の経験は https://news.ycombinator.com/item?id=38642092 と一致している。
個人メール、メーリングリスト、RSSフィードが全部一か所に集まる。個別のスプールにフィルタリングし、muttのような強力なメールクライアントと組み合わせると、かなり快適な統合体験になる。
著者は、どこからでもアプリにアクセスするために認証を追加したように見える。
代わりにVPN上に置いて、そのVPNへどこからでもアクセスできるようにすることは可能なのか、あるいはそのほうが簡単なのか気になる。
個人用Webアプリに安全にアクセスしたいが、いちばん簡単なやり方を探している。認証を見るたびに、概念、プロトコル、ライブラリの迷路のように感じるし、それを保守したくない。
自宅のRaspberry PiでHome Assistantのようなアプリをいくつかホストし、そのPiとスマホにTailscaleを入れたところ、とてもよく動いている。必要な認証は「各デバイスでTailscaleにログインする」だけ。
自分のデバイスで安全なネットワークを構成する手軽さという点では、Tailscaleを本当に強くすすめる。
ほかのWebサイトからクリップしたテキスト片だけをホストしている自分のアプリケーションを「保護」するには十分。
方法はいろいろあるが、要点はVPNエンドポイントとWebアプリを同じ場所、たとえば同じマシンや同じネットワークに置き、それ以外の場所からのWebアプリへのアクセスを制限すること。
Caddyは内部ネットワークまたはVPNから来たリクエストだけをリバースプロキシし、それ以外には404を返すように構成している。なのでVPNか自宅ネットワーク上にいなければ何も見えない。
ゲストにネットワークを開放しているか、どんなサービスを動かしているかによっては、VLANや別のゲストネットワークが必要かもしれない。自宅で動かしている多くのサービスには独自のパスワード認証もあり、VPN制限と併用している。
この構成は自分が最初に思いついた方法なので、自分の専門外の理由で安全ではない可能性もある。利点は、同じcomposeファイルでPi-holeも動かしているので、スマホがVPNに接続するとリモート広告ブロックも「無料で」手に入ること。
Tailscaleは設定がより簡単でUIも良いが、iOSでバッテリーをかなり消費したのでやめた。「他人のサーバーを信頼」しなければならない点も問題だが、バッテリー問題がなければ利便性のために追加のリスクを受け入れていた可能性が高い。
WireGuardアプリには便利な機能もある。自宅にいるときのように特定のネットワークでは実行しないよう指定できるので、外に出ると自動でオンになり、家に戻るとオフになる。
これはクルージングヨットで必要だと思っていたものに驚くほど近い。特に外洋では接続が断続的なので、あと2つあればぴったり合いそう。
LTEが入る島のそばを通るときのように、短時間だけ接続できる瞬間に 今すぐ同期 を押せる必要がある。さらに基本的にReadability処理とローカルキャッシュを行い、画像まで含めたすべてのコンテンツをオフラインで読めるようにしてほしい。