Inspiration
Every research morning starts the same way: an arXiv listing with hundreds of new papers, ten open tabs, and the quiet fear of missing the one that matters. The existing fixes ask for a trade we didn't want to make keyword alerts that don't know you, or recommender services that know you too well, because your entire reading history lives on their servers. And when we asked an LLM to "read" a paper, it usually read an abstract, not the paper: no figures, no tables, no equations. PaperOrbit started as one question: can a daily paper companion be genuinely personal, read the actual PDF, and still keep your research profile entirely on your own device?
What it does
PaperOrbit is a daily paper-reading site for anyone who signs in with ChatGPT: ten personalized recommendations every day, structured arXiv search, a Paper Copilot that answers questions grounded in the full PDF, auto-generated reading reports, and a personal library with reading progress. Every reader connects their own OpenAI-compatible API key.
How we built it
The stack is Next.js + TypeScript, deployed on Sites with Sign in with ChatGPT for identity.
A two-layer recommender ("Orbit v3 Local"). The server only generates a public candidate pool: a fixed OR-query pulls up to 60 fresh papers and enriches them with Semantic Scholar citation and influential-citation signals. All personalization happens in the browser: interest relevance, explicit feedback, and a decayed preference profile with a 90-day half-life,
$$w_{\mathrm{eff}} = w \cdot 2^{-\Delta t / 90}$$
blended over baseline weights $S = 0.42\,s_{\text{rel}} + 0.12\,s_{\text{pref}} + 0.16\,s_{\text{fresh}} + 0.17\,s_{\text{impact}} + 0.13\,s_{\text{evidence}}$, then re-ranked for topic diversity, with no Math.random(), so the same inputs always yield the same ten papers. Every card explains why it was picked with 0–100 sub-scores computed by rules, not by an LLM: explanation costs zero tokens.
A PDF-grounded Copilot. The server accepts only valid arXiv IDs and constructs the PDF URL itself. Before any model call, it verifies the file independently. Responses are byte-bounded (4 MiB success / 32 KiB error), retries are limited to fast 5xx failures so a long PDF run is never billed twice, and a 16-output-token text probe tells apart "your AI service is down" from "only the PDF path failed."
Privacy as plumbing, not as a toggle. API keys live only in AES-GCM-encrypted HttpOnly cookies; libraries, profiles, and feedback live only in localStorage, namespaced per signed-in account. Custom endpoints must be public HTTPS; redirects are never followed (so keys can't leak to another host), and localhost, intranet, and cloud-metadata addresses are rejected outright.
Challenges we ran into
Personalization without a profile upload. A recommender normally wants your data on its side. We split the problem instead: candidate generation is public and identical for everyone; ranking is local.
Bring-your-own-key multi-tenancy. Letting users connect arbitrary OpenAI-compatible services safely was harder than calling one official API: we validate each endpoint with a /models check plus a minimal real /responses probe before encrypting the session, and treat every URL as hostile until proven public-HTTPS.
Making failure diagnosable without leaking secrets. PDF calls are expensive and fail in a dozen distinct ways. We ended up building a failure taxonomy — arXiv unreachable, oversized file, invalid key, quota, incompatible Responses/PDF support, malformed SSE — surfaced as layered diagnostics with a correlation ID, while never echoing API keys or raw upstream bodies.
A local dev identity that doesn't weaken production auth. Local mode uses an in-memory loopback-only entry marker that the server re-attaches itself, so forging X-Forwarded-Host or X-Forwarded-Proto can't turn a public request into a trusted local one.
What we learned
Privacy is an architecture decision, not a feature: choosing where computation runs decided what we had to protect, and the public-candidates / local-ranking split dissolved an entire class of trust questions before they arose. Shipping an AI product turned out to be roughly 5% model calls and 95% transport — verification handshakes, byte caps, billing-aware retries, failure taxonomies. And deterministic, rule-based explanations earned more trust than LLM-generated ones would have, at exactly zero token cost.
Log in or sign up for Devpost to join the conversation.