🎉

エンジニア向けAI情報収集アプリResearchlyをリリースしました

に公開

Researchlyというソフトウェアエンジニア向けのAI情報収集iOSアプリを開発しました!下記のApp Storeリンクからダウンロードできます(iOS18.5以上が対象)。

https://apps.apple.com/jp/app/id6739998813?l=jp

https://x.com/adsholoko/status/1956515521102479800

はじめに

Researchlyは、長らくエンジニアをしてきたなかで、自分が「もっとこうなればいいな」を詰め込みました。ソフトウェアエンジニアの日常における理想の情報収集を実現するために開発しています🍵

自分は、バックエンドエンジニア→iOSエンジニア→(PdM)→フルスタックエンジニアとキャリアを積んできました。世の中のエンジニアリングに関するキャッチアップは、ほぼ欠かさず日常的に行ってきました。

そんな自分の情報収集ルーティンは、以下のような感じでした。

  • Readwise ReaderというRSSリーダーを利用して、興味の近い企業ブログや個人ブログを受け取る
  • はてなブックマークのテクノロジー欄を眺めて読む
  • Hacker News(海外版のはてブのようなもの)で海外の技術動向を追う
  • 生成AI周りの領域は論文を眺める
  • 著名なエンジニアをXでフォローして補完しつつキャッチアップ

さらに、ChatGPTの登場以降は、よりこのルーティンにAIを絡ませていました。もちろんURLをコピーしてChatGPTやGeminiで要約や対話をさせることはできますし、NotebookLMのようなものもあります。

しかしながら、一つのアプリで各種経路からの情報を一元化しつつ、AIによる要約、チャット、翻訳を読みながら対話する体験を作りたいと思っていました。

エンジニアたるもの、自分でその夢を叶えたろう!と思いたち、開発をすることにしました!

全体の構成

アプリを開くと下記のように4タブ構成になっています。

  • Feedタブ
    • RSSフィードを購読/閲覧できるタブ。
  • Researchタブ
    • はてブ(テクノロジー)/企業ブログ/Hacker News/Zennの記事/arXivの論文を閲覧できるタブ
  • Inboxタブ
    • いいね/メモをした記事を閲覧できるタブ
  • Settingタブ
    • アカウントなどの設定タブ

となっており、さまざまな情報源から記事を集約することができます。そのすべてにおいて、AIによる要約やチャット、翻訳などの機能を提供しています。それではコア機能についてみていきましょう!

Researchlyのロゴ

AI関連機能の紹介

💬 サイトや論文を読みながらチャット会話

記事中の用語がわからない、「つまりどういうこと?」といったことを直接アプリ上から「その場で」回答させることができます。サイトや論文のなかで画面下部の💬ボタンを押すとその場で起動させることができます。

🪄 ワンタップで要約

これも記事の全てを読まずに、要約でサクッと中身を読みたい時に利用する機能です。地味に面白い機能としてX向けの要約という機能を用意しています。読んだものをアウトプットする文化が根付けばいいなと思いまして。🪄ボタンで起動できます。

🧑‍🏫 arXivの解説モード

arXivの論文を最新順でカテゴリ別に閲覧でき、いわゆる落合メソッドによる解説を開くことができます。これで論文の全体を把握しつつ、興味のある論文を深掘りしていくことができます。arXivのページのなかで右下の帽子フローティングボタンで起動できます。

🗣️ ドラッグのみで翻訳

iOSはテキストをドラッグすると、ContextMenu で翻訳をすることができますが、わざわざ翻訳をタップするのが面倒ですよね。なので自動翻訳できる機能を用意し、ここが開かれている場合はドラッグされた文字が自動で翻訳される仕組みがあります。下部ツールバーの翻訳ボタンで起動できます。

ただ、実はTranslationSessionというiOSネイティブの翻訳機構を採用しているため、LLMは一切関わりません。なのでこの機能はログインも不要で、無制限で利用できます。

📡 RSSフィードも完備

いわゆる枯れた技術ではありますが、RSSフィードを購読することができます。RSS自体が重要なのではなくて、RSSから遷移したサイト上で、前述したチャットや要約が使えるところがポイントになります。

当然ながらRSSフィードとしての機能やリッチさはまだまだ弱いです。ただ個人的には最強のRSSリーダであるReadwise Readerを参考にしつつ、少しずつ整備していきたいと考えています。

その他機能

❤️ いいね/メモ機能

今回はどこでも気軽に閲覧できる「モバイル端末」というのはひとつポイントで、本格的に読む体験自体はパソコンでやる人も多いでしょう。そのためクイックにストックすることを重要視しているため、「いいね」で保存してお気に入り記事を貯めておける機構を用意しています。

また、これも目新しい機能ではありませんが、各サイト単位でメモをつけることができます。気に入った記事には軽くメモをしておくもの、あくまでも自分専用で他人にシェアなどはされません。

いいね/メモしたものはInboxタブで開いて閲覧することができます。

🌕ダークモード完備

ソフトウェアエンジニアの人は特にダークモードの人が多いと思っています(偏見)。なにより自分が使いたいので、ダークモードを初期から対応しています。

技術の話

もし詳しく知りたい人がいれば詳しく記事に起こそうと思いますが、全体のアーキテクチャとしては下記のようになります。

  • iOS: SwiftUI + Combine + Swift Concurrency
  • Backend: hono + Supabase + UpStash
  • Infra: GCP + Cloud Run + Terraform

iOS Nativeのため、Swiftになります。SwiftUIを採用し、CombineとSwift Concurrencyを駆使して非同期処理を行っています。特にCombineは、UIの状態管理やデータの流れをシンプルに保つために非常に役立っています。自分がiOSエンジニアの時、callback地獄やRxSwiftの時代だったので、async/awaitやCombineの体験は本当に良い。

BackendはhonoによるAPIサーバでCloud Run上で動作しています。データベースは認証とRLSを併用できるSupabaseを採用しました。

honoの@hono/zod-openapiで、zodスキーマからopenapi.ymlを生成し、Apple謹製のswift-openapi-generatorでSwiftの型を生成します。この体験が本当に素晴らしく、zodスキーマを定義すれば、Swiftの型まで完結できるため、Claude Codeのようなエージェントからの自動コーディングがとにかく楽になりました。

目新しいところといえば、UpStashというサービスをフル活用していることでしょうか。UpStashは東京リージョンにおけるかつ、「安い」のもポイント高いです。

利用する用途としては、解説や要約のキャッシュとしてのRedisとして利用しています。これはイメージしやすいと思います。 さらに非同期タスクのためスケジューリング/キューイング/同時並行制御の仕組みとしてQStashを利用しています。

例えば下記のように特定の処理の並列数を制限するようなエンドポイントを定義し、その同時実行数を制限をかけることができます。

UpStashのダッシュボード

例えば、これをTypeScriptのコードで呼び出すことが可能です。簡単!

import { Client } from "@upstash/qstash";

(割愛)

const qstash = new Client({ token: process.env.QSTASH_TOKEN! });

// どれだけ並列で投げても自動で同時並行数を調整してくれる(非同期)
await qstash.publishJSON({
  url: `{並行処理するエンドポイント}`,
  body: body,
  retries: retries,
  delay: delay,
  headers: headers,
});

さらにはQStashを経由することで、実行時ログも残ります。リトライも回数を指定できます。さらに、なんといっても、DLQとして失敗したジョブがパラメータ付きで残るため、バグを修正後に再実行によるリカバリが可能です。本当に素晴らしい。

また(最近更新がされていない気もしますが)Terraformとの相性が良いのもポイントが高いです。例えばスケジューリングであれば下記のようにかけば、それだけでスケジューリング実行(cron)のようなものが実行できてしまいます。

resource "upstash_qstash_schedule_v2" "hackernews_crawl" {
  destination = "{バッチ用のエントリポイント}"
  method      = "POST"

  // every 30 minutes
  cron = "*/30 * * * *"
  
  body = "{}"
  content_type = "application/json"
  retries      = 1
}

本アプリはほとんどが、RSSフィードのクロール処理のようなバッチものであるため、こういった機構がミドルウェアやインフラ側で吸収されているのは非常にありがたいです。

余談

アイデアの萌芽は元々は年末年始からでした。作り始めたときは、React Nativeで実装していたものの、どうしても妥協できないポイントがいくつかあり、iOSネイティブに切り替えました。Androidユーザの人ごめんなさい🙏

現職のany株式会社では、普段はTypescriptを書く人間なので、フロントエンドもバックエンドもTSで書けるの最高やん!と思っているのですが、なかなか細かい箇所で求めるクオリティに到達せず...

仕事が忙しいときはほとんどできていないので、めちゃくちゃ牛歩ではありましたが、8ヶ月もかかってます笑 が、Claude Codeのおかげで一気に完成まで辿り着きました!🏄

💰マネタイズ

サブスクリプションプランを用意しているため、ヘビーに利用していただける場合はそちらに加入していただけると嬉しいです。

とはいえ無料版でも一定の制限のもと利用できるようにしつつ、代替として広告を表示することにしています。一定は運営費として負担するのですが、どの程度の制限をかけるか、現時点で読めないところがあるため、サーバ側でLimitを修正できるようにしています。いまは制限がかかったとしても12時間でリセットされるようになっています。

メンテナンス費用という面では、とにかく多段にキャッシュ化を徹底しており、Redis/DB/Prompt Cacheといった形で可能な限りコストを抑える設計にはしています。ただ若干怖くはある...!

一つ大切にしているポイントとして、記事や論文を読むWebサイトのView自体には広告を置かないようにしています。なにより著者にリスペクトをしたい点が一番。あくまでもResearchly自体の機能を利用しているUIには広告が出るようになっています。

さいごに

これまでいくつか個人開発をしてきたなかで、「ユーザが自分である」原体験に近いものがないとモチベーションが続かないと痛感していました。

そんななかで情報収集の観点でAIをフル活用できる、まずは「自分が本当に欲しいもの」を作ることができたのは非常に嬉しいです。 自分のようにひたすら情報を追いたいといったタイプの人は実はそこまで多くないかもしれませんが、少しでも興味を持っていただけると嬉しいです。

改めてインストールはこちらからどうぞ!

https://apps.apple.com/jp/app/id6739998813?l=jp

Discussion