Skip to content

Repository files navigation

tech-antenna

技術情報を自動で収集し、記事・ニュース・論文・イベント・書籍を1つの導線にまとめて届けるWebアプリ。

「今このトピックが伸びている → 関連する勉強会が近くである → 深掘りするならこの本・この論文」

ホーム画面。収集した記事・ニュース・論文から LLM がまとめた「今日のサマリー」と、話題のトピックが並ぶ

構成

領域 採用
ランタイム .NET 10 (LTS)
Web ASP.NET Core + Blazor
収集ジョブ BackgroundService
DB PostgreSQL + EF Core
要約 Chiezo 経由(相手を画面で選ぶ)/ Claude Code(CLI を同梱)/ Anthropic API

データソース

  • 記事 — Qiita・Zenn・はてなブックマーク テクノロジー等の RSS / Atom
  • ニュース — Publickey・ITmedia NEWS・InfoQ Japan・CodeZine の RSS
  • 論文 — arXiv(英語。タイトルは LLM で和訳)/ J-STAGE(日本語)。どちらもトピックで検索する
  • 話題の論文 — Hugging Face Daily Papers(トピックの選択に関係なく、投稿と upvote で 選ばれた論文。中身は arXiv 投稿なので英語のみ)
  • 出版トレンド — 国立国会図書館サーチ(直近に出た本・ムックのタイトルからテーマを数える。 キーも申請も検索語も要らない)
  • 書籍 — Google Books API(検索・書影)/ openBD(書誌)/ Qiita(「読むべき技術書」を挙げた記事から薦められている本と、 選んだトピックの記事が本文で挙げている本)
  • イベント — connpass API(API キーが必要)/ Doorkeeper API(アクセストークンが必要)/ TECH PLAY の RSS

どこにキーが要るのか、設定できているのかは画面の「設定 → 外部連携」(/settings/integrations)で 一覧できる。「トレンドで使う」「興味トピックで使う」「定番で使う」の3節に分かれ、その中は用途ごとに 並ぶ(両方で使う連携は両方の節に出る。キーの値そのものは表示しない。有無だけを見る —— 秘匿値でない ntfy のベース URL・トピック名だけは値を出し、「コピー」で写せる。 トピック名は「生成」でランダムに作れる)。 キーの設定も同じ画面から行う(暗号化して DB に保存・再起動なしで反映)。 環境変数や .env ではキーを渡せない。

トピックの整備

一覧は画面の「設定 → トピック」(/settings/topics)。ツリー(配下込みの話題度で「どの領域が 熱いか」)とランキング(単体の話題度で「どの用語が熱いか」)をタブで切り替える。 新規トピックの候補は記事・イベント・書籍の収集で自然に溜まる(集めたデータのタグから見つける。 溜まった語は「設定 → トピック → タグ」(/settings/tags)の「仕分け待ち」で見える)。 整備のボタンは設定画面にあり、2つに分かれている:

ボタン やること LLM 仕分け待ちの語
話題度を取り直す 外部トレンドを引いて鮮度を更新し、一覧を作り直す 使わない 増える
タグを仕分けなおす 溜まった語を LLM で分類してツリーへ組み込む 使う 増えない(押すぶんだけ減る)
  • 一覧の左のチェックボックスが収集対象の選択押した瞬間に保存される (JavaScript を切っている環境では、一覧の下の「選択を保存」でまとめて保存できる)。 イベント・書籍・論文は選んだトピックを検索語にして問い合わせるので、 何も選んでいないと 1 件も集まらない
  • 外部へ検索しに行くのは選んだトピックだけ(配下へは広げない)。イベント・書籍・論文は トピック 1 つごとに外部へ問い合わせるため、配下まで検索すると大きな親を選んだだけで リクエスト数が跳ねる。配下も検索したいときは、その子を自分でチェックする
  • 興味トピックの並びは自分で決められる。「興味トピック → 書籍」でトピックの見出しを 長押ししてドラッグすると並べ替えられ、離した時点でサーバーに保存される (JavaScript を切っている環境では、各見出しの ▲▼ で 1 つずつ動かせる)。 冊数や話題度で並べていた頃は収集のたびに順番が入れ替わり、毎日見る一覧なのに 「いつもの場所」が無かった
  • 親を選ぶと、配下のトピックは「興味の範囲」に入る —— 興味トピックの下の一覧 (書籍・イベント・論文)は選んだトピック+配下のものだけを出し、記事一覧の強調(★)も 配下込みで判定する
  • 記事だけは選択で絞らない。 RSS は検索ではなく巡回なので、絞っても収集先への負荷は 変わらず、捨てると「選んだトピックの外で何が起きているか」が見えなくなる。 流れてきた記事はすべて保存し、選んだトピックのものはタイトルの前に黄色い★を付けて タグの色を変える(カード全体を染める強調は話題度専用)。選択が空でも記事は集まる
  • 選択したトピックは一覧の先頭に固定する。 再収集でそのトピックが見つからなくなっても 一覧からは消えない(話題度が 0 になるだけ)。押し出されて画面から消えると、選択の保存は 一覧に出ている分で置き換えるため、選択そのものが外れて収集が止まってしまう
  • 話題度の材料は Qiita の新着記事(いいね数)はてなブックマークの人気エントリー (ブックマーク数)。どちらも収集ボタンを押した時点でその場から取得し、トレンドの収集状況には 依存しない。材料ごとのシェアに直してから合算する —— 桁の違う値をそのまま足すと、 桁の大きい材料が常に勝ってしまうため。算出方法は設定画面のボタンの「?」にも書いてある
  • 仕分けの対象はタグの画面(/settings/tags)で見える —— 「仕分け待ち」の一覧が そのまま LLM へ流れる(件数での足切りはしない)ので、押す前に何が流れるか分かる。 目立つ順に1 回 300 語までで、超えた分は次の回へ。押すのは設定画面で、 溜まっていればそのボタンの上に「未仕分けのタグが N 語あります」と出る
  • カタログに無い語は LLM が分類してツリーへ入れる(要約と同じ方式・同じ設定。未設定なら 分類なしで動く)。既存トピックの同義語なら寄せ、粒度が違う語なら親付きの新トピックにする。 「トピックでない」と確定した語(ニュース・開発 のような一般語)は一覧から取り除く (記事などのタグとしては残る)。一覧は親子のツリー順で、子は親の下に1段下がる。 分類を人手で直したいときは「設定 → トピック → タグ」の画面で直す(手直しは LLM より優先される)
  • 話題度は外部トレンドだけで測る。 手元に集めた記事・イベント・書籍の件数は 順位に足さない —— 混ぜると「外でどれだけ話されているか」と「自分がどれだけ集めたか」が 1 つの数字に潰れ、収集を押した回数で順位が動いてしまう(件数は行のかっこ書きで別に出す)
  • トピック名を押すと詳細(/settings/topics/<タグ>)。その語の一言説明同義語 (どの表記を寄せているか。LLM が分類した分は印を付ける)と親子ツリー上の位置、 続けて紐づいた記事・イベント・書籍が出る
  • タブの下の検索ボックスでトピックを探せる(別名でも当たる —— 人工知能AI に当たる)。 一致した枝が開いて先頭にカーソルが合う。一覧に無い語は用語集の側を案内する
  • 一覧に出るのは語彙(ツリー)に入っている語と、収集対象に選んだ語。話題度 0 でも消えない。 行に並ぶのはトピック名・紐づくアイテム数(記事・ニュース・論文・イベント・書籍の合算。 ラベルを付けずかっこ書きで、内訳はツールチップ。0 のときは出さない)・用語の一言説明 (PC はかっこ書き、スマホは「?」を押すと出るチップ)
  • 語彙に入っていない語は「設定 → トピック → タグ」(/settings/tags)で状態ごとに見られる (仕分け待ち / 保留 / 除外 / 別名 / トピック(語彙))。保留は「期限が来たら聞き直す」と「自動では聞き直さない (紐づくデータなし)」に分けて出る —— 判断できず、しかも記事・イベント・書籍のどれにも 付いていない語は聞き直しても答えが変わらないので、自動の対象から外している (データが付けば戻る。手で仕分けるのはどちらの一覧からでもできる)。そこで仕分けを手で直せる —— トピックにする・別名に寄せる・除外する・仕分け待ちに戻す。手直しは LLM の判定より優先される。 チェックボックスで選んでまとめて除外できるので、誤記や一過性のゴミは LLM に聞かせる前に落とせる
  • 同義のトピックは仕分けが寄せる(AI人工知能 が別々にできてしまった場合)。 寄せると配下の親も付け替わる。収集対象に選んでいるトピックは寄せない
  • 見慣れない用語には一言説明が付く(PC はトピック名の後ろのかっこ書き、 スマホは ? を押すとチップで出る)。新しく見つかった語の 説明は分類の応答に相乗りしていて追加の呼び出しは無く、以前からある語は仕分けのたびに 300 語まで埋める(1 語につき 1 回だけ聞いて保存する)。topic-seed.jsondescription を書けば、そちらが優先される
  • 語彙は JSON ファイルで持ち出せる(「ファイルで持ち出す / 取り込む」)。 LLM の仕分けは呼ぶたびに枠を使うので、本番で仕分けた語彙を開発サーバーへ運べるように してある(バックアップにもなる)。運ぶのは語彙とタグの仕分けだけで、件数と話題度は 入らない(取り込んだ先で整備が集め直す)。取り込みは足し込みで消さず、画面から 人が直した仕分けは上書きしない。収集対象の選択はチェックを入れたときだけ反映する
  • ホームの「話題のトピック」には、話題度の高い順に 10 件が並ぶ(話題度 0 は出さない。 興味として選んでいるかどうかは効かせない —— 選んだトピックは「興味トピック」の担当)
  • 話題度を取りに行くのは「話題度を取り直す」を押したときだけ(候補集めは外部に依存しない)

記事・ニュース・論文

画面は3つの軸に分かれている。 「トレンド」は外で何が話題かを トピックの選択に関係なく見る場所(ニュース / 記事 / 書籍 / 論文)、 「興味トピック」は選んだトピックを深掘る場所(イベント / 書籍 / 論文 —— 一覧に出るのも選んだトピック+配下のものだけ)、 「定番」は時間が経っても薦められ続けるものを集める場所(イベント / 書籍 —— 書籍は「読むべき技術書」を挙げた記事から名指しされた本を拾い、イベントは集めたものの中から 注目度の高いものを出す。どちらの軸とも独立で、トピックの選択に依存しない)。

収集のボタンはすべて設定画面にある(一覧を読む画面には置かず、集めなおす操作は 設定に集めてある)。ボタンは軸ごとに分かれていて、「トレンドの収集」は RSS のフィードと 話題の論文を 1 巡する。「論文の収集」「イベントの収集」「書籍の収集」は検索なので、 収集対象に選んだトピックが無いと 1 件も集まらない (イベントだけは例外で、購読しているグループがあればトピックの選択に関わらず集まる)。トレンドは興味のあるトピックに限らず直近 7 日の話題を 話題度の高い順(ニュース・記事ははてなブックマーク数、論文は upvote)に 5 件ずつ 一望する場所(メニューの「トレンド → まとめ」)で、種別ごとの全量は子ページ (ニュース / 記事 / 書籍 / 論文)が受け持つ。 子ページは新着順が既定で、上のタブから話題度順(直近 100 件の中で)にも切り替えられる。 まとめの最後には「本になっているテーマ」が上位だけ並ぶ —— 直近 6 か月に出た本・ムックの タイトルから数えたもので(出典は国立国会図書館サーチ。キーも検索語も要らない)、 反応の速さではなく出版側が時間をかけて寄せている先が出る。テーマごとの全冊は 「トレンド → 書籍」(/recent/books)にあり、テーマ名の横に何冊でそのテーマに なっているかが出る(中身は「興味トピック → 書籍」と同じ 1 冊 1 行の並び)。

  • 子ページでは話題度は目立ち方に出す。バッジが件数で 3 段階に変わり、カードの面にも 段階が出る。並び順は新着のまま —— 人気順に並べ替えると「今日なにが出たか」を追えなくなる。 件数は収集のたびに、はてブの件数 API(キー不要)で直近分をまとめて引き直す

  • 興味のあるトピックに当たる記事はタイトルの前に黄色い★が付く(トピックは設定で選ぶ)

  • 記事とニュースの違いは設定の Kind だけ(Collection:Feeds の各フィードに書く)。 保存先もタグの扱いも同じで、画面で出所が混ざらないようにするための区別

  • タグはフィードのカテゴリ + タイトルから見つけたトピック。Zenn の RSS も Qiita の Atom も category を持たないため、収集元のタグだけに頼ると 7 割方タグ無しになり、トピック横断にも 一覧の強調にも乗らない。誤爆を避けるため判定は KeywordMatcher(AIRailsemail に 当たらない)で、見るのはタイトルだけ(本文まで見ると一度触れただけの語で付いてしまう)

  • 論文は arXiv(英語)と J-STAGE(日本語)。どちらもキー不要で、選択中のトピックを検索語に 1 つずつ問い合わせる。arXiv にはカタログの英語別名を投げる —— 日本語のままだと 0 件になる (実測で 生成AI は 0 件)。取り込むのはタイトル・URL・投稿日だけで、abstract は取り込まない

  • 英語論文のタイトルは設定の「論文タイトルの翻訳」で和訳できる(要約と同じ LLM の枠)。 訳題を見出しにし、原題は下に小さく残す —— 消すと他の文献と突き合わせられなくなる。 日本語のタイトルは訳さないものとして確定するので、J-STAGE の論文は LLM を消費しない

イベント

「興味トピック → イベント」に、上が月カレンダー、下が一覧で出る。集めるのは 設定画面の「イベントの収集」で、選択中のトピックを検索語にする(connpass / Doorkeeper)か、 流れてくる RSS を絞り込む(TECH PLAY)。それに加えて、購読しているグループ面掃き(期間の全件を参加者数で切る。既定は無効)からはトピックに関係なく入る。

  • カレンダーは月グリッド。 前後の月へはリンクで移り(?month=2026-09)、 月を指定すると一覧もその月になる。JS は使っていない
  • 提供元(ベンダー)自身が主催しているイベントには「公式」バッジが付く。判定は 主催者名と名簿の突き合わせで、名簿は「設定 → イベント」から直せる —— そこには集まっているイベントの主催者が件数つきで並ぶので、判定を見ながら足し引きできる
  • 参加者数は 3 段階のバッジ(30 人 / 100 人)。開催が近づくと増えるので、 同じイベントを見かけるたびに数だけ取り直す
  • 一覧の並びは開催日順が既定で、タブから注目度順(公式であることと参加者数で測る)。 注目度順を既定にしないのは、来月の大きなイベントが先頭に来て明日の予定を見落とすため。 参加者数を返すのは connpass と Doorkeeper だけなので、数を持たない TECH PLAY の イベントは公式判定と記事の言及数だけで測ることになる (主催者は 3 つとも取れる —— TECH PLAY は RSS の dc:creator)
  • 「定番 → イベント」は同じデータをトピックの選択で絞らずに出す(既定が注目度順で、 タブから開催日順)。注目度の材料(公式・参加者数・記事の言及数)を1つも持たないものは 出さない —— カードの強調が付く条件と同じ基準。「毎年開かれる定番のカンファレンス」を 見分ける方法はまだ無いので、いまは注目度で代用している
  • トピックに当たらないイベントが入る経路は購読と面掃きの2つ。 そこが空だと、 定番の一覧も選んだトピックのイベントだけになる。購読は 「設定 → イベント」の「公式の主催者から足す」から増やせる —— 集めたイベントのうち公式と判定された主催者のグループを候補に出すので、 グループの識別子を自分で調べなくてよい(外部への問い合わせは無し)

書籍収集

書籍の収集」(設定 → ジョブ)は、選択中のトピック 1 つずつで 2 つの経路を通る —— Google Books の検索と、そのトピックについて書かれた Qiita 記事が本文で挙げている本の 拾い上げ。どちらも openBD で書誌情報を補ってから保存する。検索語は設定ではなく トピックの選択から来る(→トピックの整備)。

集めたいのは新刊ではなくその分野で読んでおくべき本なので、検索は関連度順で引き、 並びは記事に名指しされた票数(同数なら新しく集めたもの)で決める。

  • 名指しは 2 種類あり、1 票ずつ合算して並べる。 「推薦」は「読むべき技術書」を挙げた まとめ記事(定番の収集で拾う)、「引用」は選んだトピックの記事が本文で挙げたもの。 件数はカードに別々のバッジで出し、押すと出典の記事が開く —— 合算するのは並びだけで、どちらの根拠なのかは画面から読める (同じ記事が両方に入っても 1 票)。 引用が取れる量はトピック次第(教科書のある分野ほど厚い)

  • 読み終えた本には「読んだ」の印を付けられる(書籍の一覧の右端)。印の付いた本は 一覧から消えず末尾へ回る —— 「何を読んだか」の記録が消えず、押し間違いも戻せる。 名指し(世の中でどれだけ薦められているか)とは別の軸として持つ

  • 雑誌・ムック・増刊は入れない。 号を重ねるぶん数が多く、「読んでおくべき本」を 探すのに埋もれるため(Google Books の printType=books と、タイトルの型で落とす)。 同じ本がトレンドの「本になっているテーマ」では材料になる —— あちらは数えるのが目的

  • 検索は Google Books、補完は openBD(書誌) と役割を分けている。 openBD は日本の書誌を無料で引けるがキーワード検索を持たず ISBN 参照専用なので、 検索で得た ISBN で引き直して欠けている項目だけを埋める(既に値がある項目は上書きしない)

  • レビュー(読まれている度合い)は持たない。 唯一の取得元だった楽天ブックスの連携を 外したときに、列ごと落とした —— 他に日本語書籍のレビューを引ける無料の口が無く (Google Books の ratingsCount は日本語書籍にほぼ入っていない。実測 20 件中 0 件)、 永久に埋まらない列で並べ替えても順位に出ないため。書影は openBD で埋まらなければ Google Books へ ISBN で引きに行く(1 冊 1 リクエスト・1 秒間隔)

  • Google Books の API キーは実質必須。 キー無しのリクエストは Google 共有の匿名プロジェクトの 枠に入り、その枠は 1 日あたり 0 件なので最初の 1 回から 429 になる(キーは外部連携の画面から設定)

  • 検索条件は langRestrict=ja(日本語の技術書を拾うため)だけで、並びは既定の関連度順。 1 キーワードにつき 20 件、キーワードの間は 2 秒空ける。orderBy=newest を使わないのは、 新刊が欲しいわけではないうえに取りこぼしが大きいため(実測で 機械学習 は新着順だと 0 件、 関連度順なら 300 件)

  • 取り込むのは書誌事実だけ(タイトル・著者・出版社・刊行日・ISBN・リンク・書影 URL)。 description などの出版社の著作物は取り込まず、書影も画像は持たず URL のリンクにとどめる

  • 同じ本かどうかは ISBN-13 →(無ければ)詳細ページの URL →(無ければ)タイトルで判定する。 既にある本は書誌情報を上書きしないが、タグだけは足す —— 1 冊が AI でも LLM でも 見つかることがあり、捨てると最初のトピックにしか出てこないため

  • 「読むべき技術書」を挙げた記事から、薦められている本を拾う(Qiita の公式 API。キー不要)。 記事に貼られた Amazon リンクの ASIN は書籍なら ISBN-10 そのものなので、ISBN-13 に直して openBD で書誌を引く(チェックディジットを検算するので B0… の Kindle 専売は落ちる)。 保存するのは ISBN と出典記事の URL だけで、記事の本文は保存しない。 何本の記事で薦められたかが「推薦回数」

  • 「書籍」画面は収集対象に選んだトピックごとの折りたたみ。トピック名を押すと開き、 配下のトピックの本は親のグループにまとめて出す(どのタグで載ったかは、本のタグの帯で そのグループに反応したタグだけが強調される)。複数のトピックに当たる本はそのすべてに出る。 並びは名指しされた票数の順で、トピックの中でも名指しのある本は強調される。 推薦だけを集めた一覧(推薦 2 本以上)は「定番 → 書籍」の担当(収集は設定の「定番の収集」) 現状の制限:

  • 一度保存した本の書誌情報は更新しない(欠けている書影とタグ・名指しの出典だけ足す)

  • Google Books の q= はタイトル以外(著者・説明文)にも当たるため、キーワードと関係の薄い本が 混じる。イベント側の KeywordMatcher のような絞り込みは書籍には入れていない

本番運用

docker compose で動かす。ホストに .NET も Postgres も要らない。

cp .env.example .env   # ポートやタイムゾーンなど必要な設定を入れる
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build

外部 API のキーは、起動後に画面の「設定 → 外部連携」の「キーの設定」列から入れる (.env では渡せない)。

http://<ホスト>:7020 で開く(.envPORT で変更可)。データはリポジトリ直下の data/(Postgres は data/postgres、Data Protection の鍵は data/keys)に入る —— バインドするのはこの data/ 1つだけで、下のディレクトリは起動前に init が作る。 バックアップはこのディレクトリを丸ごとコピーするだけでよい。 コンテナは非 root で動き、既定は 10001:10001(ホストに実在しない番号)。 data/ をホストから直接編集・書き戻ししたいときは .envTECH_ANTENNA_UID / TECH_ANTENNA_GID を設定する(所有者合わせは init が自動でやる)。逆にまっさらに戻したいときは docker compose down してから data/ の中身を消す(次の起動で DB が初期化され、 語彙の初期値も入り直す。鍵も再生成されるので発行済みトークンが無効になるだけ)。未適用のマイグレーションは 起動時に自動で当たるため、更新は git pull して同じコマンドを打つだけでよい。

  • イメージは main への push で GitHub Actions がビルドし、GHCR へ公開する (.github/workflows/build-and-push-image.yml)。 タグは latest とコミット識別用の sha-xxxxxxx。デプロイ先はビルドせず docker compose pull && docker compose up -d でよい
  • 収集元は1つずつ止められる(設定 → 外部連携の「収集」)。止めたものは収集のときに叩きに行かない
  • どの AI に書かせるかは画面(設定 → 外部連携の一番上)で選ぶClaude Code(サブスクの枠)Anthropic API(従量課金)Chiezo の相手が同じ表に並び、メインに選んだものが 要約・翻訳・タグの仕分け・今日のサマリーで使われる(キーが未設定の相手は選べない。 行の「キーを入れる」を押すとモーダルが開き、その場でトークン/キーを設定できる)。 メインを選んでいなければ、 従来どおりトークン → API キーの順に設定されている方で動く
  • CHIEZO_URL を入れると、Chiezo の相手も選べるようになる。Chiezo (LAN 内の知識サーバー)が Gemini・Claude Code・推論サーバ…の鍵を持っているので、 こちらにキーは要らない。サブの AI を選ぶと、今日のサマリーをメインと同時に書き、 ホームで AI ごとの折りたたみを開いて読み比べられる(開いているのはメインの分だけ)。 未設定でも、同梱の Claude Code CLI と Anthropic API は画面から選べる
  • 要約を Claude Code(サブスクの枠)で回すのに別のコンテナは要らない —— CLI をイメージに同梱してあり、アプリがプロセスとして起動する (画面で入れたトークンは子プロセスの環境変数で渡すので、入れ替えても再起動は要らない)。 CLI の版は Dockerfile の CLAUDE_CODE_VERSION で固定してある
  • GHCR のパッケージは公開なので、pull に docker login は要らない。 イメージは amd64 と arm64 の両方が入っている
  • 障害時は .envTECH_ANTENNA_IMAGEghcr.io/rtcode337/tech-antenna:sha-xxxxxxx を 指定すれば任意の時点のイメージに戻せる
  • リポジトリを置けない環境(NAS のコンテナマネージャー等、管理画面に YAML を貼り付ける タイプ)向けには docker-compose.standalone.example.yml を 用意している。実値を直書きするので、.env と同じくコピーした側(docker-compose.standalone.yml)は コミットしない
  • TLS は前段のリバースプロキシで終端する前提(コンテナは HTTP のみ待ち受ける)。 プロキシ配下に置くときは .envFORWARDED_HEADERS_ENABLED=true
  • 収集も要約も今日のサマリーも、既定では自動実行しない(画面のボタンを押したときだけ 動く)。外部 API や LLM の無料枠を意図せず使い切らないため。自動で動かすときは 画面の「設定」で、走らせたいジョブのボタンの左にあるチェックを入れ、一覧の下の 「定期実行」に実行する時刻(何個でも。日本時間)を並べる(再起動不要)。 同じ場所の「定期実行を今すぐ実行」を押すと、時刻を待たずに同じ列を1回通せる。その時刻になると、チェックしたジョブが収集 → 話題度 → タグの仕分け → 要約・翻訳 → 今日のサマリーの順に1回ずつ走る —— 後ろのジョブは前のジョブが集めたものを材料にするため
  • 今日のサマリーは ntfy へ通知できる技術界隈全体と興味トピックで別々に 1 通ずつ届く(題名で見分けられる)。接続先(ベース URL・トピック名)は画面の 「設定 → 外部連携」から設定し、トピック名があるときだけ送る(ベース URL の既定は https://ntfy.sh )。通知のオン/オフは「設定」のチェックボックスで切り替えられる
  • PWA としてインストールできる(ブラウザの「インストール」/ iOS はホーム画面に追加)。 インストールするとブラウザの枠なしで開くので、戻る/進むは画面の左上に出る。 登録は https か localhost でだけ成立する(サービスワーカーの決まり)ので、 LAN の IP へ http で当てている環境ではインストールできない

開発環境

.NET 10 SDK が要る(Ubuntu 26.04 なら sudo apt install -y dotnet-sdk-10.0)。

dotnet build
dotnet test
dotnet run --project src/TechAntenna.Web   # http://localhost:7020

# 画面を触るときはホットリロード付きで(保存すると再起動なしでブラウザに反映される)
dotnet watch --project src/TechAntenna.Web --launch-profile watch   # http://localhost:7022
                                                                   # (0.0.0.0 で待つので他の端末からも見える)

要約を Claude Code 方式で試すときは、手元に claude が入っていればそのまま動く (npm i -g @anthropic-ai/claude-code。アプリが claude -p を起動する)。 別の場所へ入れているときは実行ファイルのパスを渡す:

ClaudeCode__ExecutablePath=/path/to/claude dotnet run --project src/TechAntenna.Web

DB は PostgreSQL。接続文字列 ConnectionStrings:Default を設定して起動すると 未適用のマイグレーションが自動で適用される。未設定の場合はメモリ上のストアで動く (再起動すると消える)。テーブル定義は docs/database.md

収集は画面のボタンから実行する(→トピックの整備)。記事はトピックを 選んでいなくても集まるが、イベントと書籍は選択が空だと 1 件も集まらない。

開発サーバーから compose の DB の実データを読むときは、docker-compose.dev.yml を 重ねて 7021 を開ける(127.0.0.1 のみ。本番では重ねない)。

docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d db
set -a; . ./.env; set +a
ConnectionStrings__Default="Host=localhost;Port=${POSTGRES_PORT:-7021};Database=${POSTGRES_DB:-techantenna};Username=${POSTGRES_USER:-techantenna};Password=${POSTGRES_PASSWORD:-techantenna}" \
  dotnet run --project src/TechAntenna.Web

本番コンテナと同じ DB を見ることになるので、開発中のマイグレーションを流したくない ときは重ねないこと(起動時に自動適用される)。SQL で覗くだけなら開ける必要はない —— docker compose exec db psql -U techantenna -d techantenna

About

技術記事・ニュース・論文・イベント・書籍を自動で集め、LLM の要約と「今日のサマリー」で1つの導線にまとめる Web アプリ(.NET 10 / Blazor / PostgreSQL)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages