このページの本文へ

FIXER Tech Blog - Development

技術ニュースを毎朝スマホで流し読みしたい、だから自分専用サイトを開発した話

2026年04月24日 15時00分更新

文● Kanei Nakashima/FIXER

  • この記事をはてなブックマークに追加
  • 本文印刷

 本記事はFIXERが提供する「cloud.config Tech Blog」に掲載された「技術ニュースを毎朝スマホで流し読みできる自分専用サイトを作った話」を再編集したものです。

こんにちは、中島です。

こちらの記事(Claude Codeで自分好みの朝刊が届く仕組みを作った) で Claude Code + Pythonを使って毎朝の技術ニュースを自動収集する仕組みが紹介されていて、めちゃくちゃ良かったので自分でも作りました。

元記事はMarkdownテーブルに出力する形でしたが、僕は朝の電車でスマホで読みたかったのでWebアプリにして、さらにスコアリングやUIの設計書を書いてガチ作り込んだりもしました。

今回作ったもの

TOPページ

システム構成

技術 役割
収集 Python 3標準ライブラリのみ 7ソースからRSS / HTMLを取得しパース
保存 git コミット済み static JSON 日付単位 data/YYYY-MM-DD.json
配信 Vite 5 + React 18 + TypeScript + Tailwind 3 SPA、`vite build` が 441 ms
スケジュール GitHub Actions の schedule cron 毎朝6時JSTに収集
ホスト Vercel無料枠 git pushで自動デプロイ


Python側は外部ライブラリゼロでurllibxml.etree.ElementTreeだけです。

SPA側もfetch 1本で動くので、ルーティングも状態管理ライブラリも導入していません。

元記事をベースとした部分、変更点

元記事の「ソースをGroup A/B/Cに分けてブロック対策する」構造や、Reddit / YouTube は Python スクリプトに逃がすアイデアはそのまま使わせてもらっています。

変えたのはこの辺です。

元記事 自分の実装 理由
Markdown 出力  JSON → React SPA  スマホで読みたかった
launchd で毎朝実行 GitHub Actions cron マシン起動に依存したくなかった
Claude Code の WebFetch で取得 Python 標準ライブラリのみ GHA で Claude Code は実行できない
6 ソース ソース + Top 10 + あとで読む7 Google News 追加、スコアリングで Top 抽出

Next.jsは使っていません。更新は1日1回で動的コンテンツもないので、Viteのbuildで十分です。

テストは先に書いて、実装と分けた

Claude Codeに実装を任せるときに怖いのは、テストを通すためだけの嘘実装ができてしまうことです。

ダミーデータで埋めたり、assertを弱めたり、skipを入れたりするパターン。
 
対策として、テスト設計と実装担当を物理的に分けて、最後にクロスレビューするフローにしています。

1. テスト設計担当がテストとスケルトンを先に書く
2. 僕がテスト観点をレビュー
3. 実装担当がテスト全 PASS するまで書く。テストファイルには触らない
4. テスト設計担当がクロスレビュー。テストファイルのmtimeが自分の作業時刻で止まっているかを確認する

Python側99テスト、Web側 35テスト、合計134テストで固めました。

mtimeベースの検証は地味ですが、テスト詐欺の検出にはこれで十分です。

業務でレビューが形式的になりやすい体制でも、テストを書く人と実装する人を分けるだけで品質が変わると思います。

つまずいた箇所 3 点

1つ目:YouTubeのchannel IDが本番で404

元記事にもあった YouTube RSSフィードの収集で、ハードコードしたchannel IDが404を返してきました。

最初は1 channel 失敗でソース全体が死ぬ構造だったので、channel単位でtry/exceptを貼って、失敗したらstderrにログ吐いて次へ進む形に直しました。

外部APIや外部feedは単品で死ぬ前提で設計するのが鉄則です。

2つ目:JSTの日付が1日ずれた

getTimezoneOffset()で日付を組み立てたところJSTブラウザで1日ずれました。

Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Tokyo' }) に差し替えて解消しました。

toISOString().slice(0, 10) はUTC基準なので23時台に前日を拾ってしまいます。

業務コードでも「今日の YYYY-MM-DD が欲しい」ときはIntl.DateTimeFormatを第一候補にしておくと安全です。

3つ目:Vercelのモノレポ対応

リポジトリルートにPython、web/ にViteプロジェクトという構成だとVercelのデフォルト検出でbuildが落ちます。

vercel.jsoninstallCommandbuildCommandcd web && ...にして、outputDirectoryweb/distに指定するだけで直りました。

ここから拡張:スコアリングとUIをガチで作り込んでみた

毎朝使い始めて、7ソース200件超の記事が並ぶと『全部見る気にならないこと』に気づきました。

「自分に関係ある記事だけ見たい」ので拡張を入れました。

作り込みポイント①:スコアリング + Top 10

各ソースのスコア(Qiita の likes_count、HN の points、はてブの bookmark 数)をソースごとにmin-max正規化して0-100に揃え、全ソース横断でTop 10を抽出。

UI には Top タブとスコアバッジを追加しました。

作り込みポイント②:興味キーワードブースト

自分の興味あるキーワード(Claude Code, React, AI, LLM, TypeScriptなど18語)にマッチしたらスコアに +15。

Top 10のうち6件が自分の興味にマッチするようになりました。

作り込みポイント③:設計書を書いてからリデザイン

800行のdocs/design.mdを書いて、Google News / Zenn / Daily.dev / Hacker News の4サイトを分析してからリデザインしました。

カラーシステム・タイポグラフィ・a11y・ダークモード方針を決めてから実装に入る形です。

設計書を書くのは楽しかったんですが、「書いた通りになっているか」を Puppeteer で検証するのが一番しんどかったです。

作り込みポイント④:「あとで読む」

朝の電車で気になる記事をlocalStorageにマークしておく機能。全ソース横断で「あとで」タブに集約されます。

業務でも使えそうなポイント

1. 動的コンテンツが不要なら、静的JSON + SPAで十分か検討する
2. 収集層と配信層を分離しておくと差し替えやすい
3. テスト設計と実装担当を分けるだけでテスト詐欺対策になる
4. 外部API / feedは単品で死ぬ前提でtry/exceptを入れる
5. デプロイが「git push で1発」になる構成を選ぶ

まとめ

元記事の「自分好みの朝刊」というコンセプトをもらって、スマホで読めるWebアプリにして、スコアリングで情報量を絞って、設計書書いてUIをちゃんと作りました。

200件の記事を全部並べても誰も読まないので、Top 10 + 興味ブーストで「自分に関係ある10件」に絞って、それをスマホで気持ちよく読めるUIにする。ここまでやって初めて毎朝開くサイトになった感覚があります。

テストは最終的に85件まで増えて全PASS。Claude Codeにテスト設計と実装を分けて書かせるフローは、業務のプロトタイピングでも使えると思います。

参考サイト:
Claude Codeで自分好みの朝刊が届く仕組みを作った

Kanei Nakashima/FIXER

2024年入社です。中嶋ではなく中島。医療DXやってますん。

カテゴリートップへ

本記事はアフィリエイトプログラムによる収益を得ている場合があります

この連載の記事