On this page
The problem
An article pasted into Slack scrolls away. An article saved to Pocket never gets opened. Any team that does research hits the same two questions every week: “did anyone read this?” and “where was that document we saw?” A personal read-later list has finished its job the moment you save to it.
LaterHub turns saved links from personal items into something a team shares, with read status that is visible and search that works later.
What it does

- Save from the web, a Chrome extension, iOS and Android apps, or the OS share sheet. Items are “read later” or “watch later” and carry a status such as unread, in progress or done
- Share in groups, one per project or study group. Each member has their own status on the same item. Comments, reactions and real-time notifications for shares and comments
- Summarize. The moment an item is saved, a short summary, key points and tag suggestions are generated, so the team can triage before opening
- Search by keyword and by meaning, so “that article about AI agents, I think” is enough to find it again

How it is built
A Bun workspaces monorepo.
| Path | Contents |
|---|---|
apps/web |
Next.js (App Router), a PWA via Serwist |
apps/extension |
A WXT browser extension |
apps/mobile |
Expo (React Native) |
packages/db |
Drizzle ORM schema and migrations |
packages/shared |
Plan limits, URL normalization, AI prompts and output schemas |
Supabase is the backend: Postgres with pgvector and RLS on every table. Supabase Branching maps Git’s main and develop straight onto the production and preview databases. Summaries come from Claude Haiku through the Vercel AI SDK; embeddings from OpenAI’s text-embedding-3-small. The chain that runs after a save (metadata fetch, summary, embedding) is a Vercel Workflow, so a failure part-way resumes rather than restarts. Secrets live in Infisical and sync to Vercel.
Decisions
Two layers of authorization. Server-side Drizzle connects as the postgres role and bypasses RLS. So application authorization is written in Server Actions, and RLS is the layer that guards access through supabase-js and the Data API. Rely on only one and the other path becomes the hole.
Normalize URLs before saving. The same article showing up twice because of different UTM parameters is fatal for a shared list. The normalization rules live in packages/shared and the web app, the extension and the mobile app all call the same function.
Constrain AI output with a schema. Summary, key points and tags are structured output validated by a zod schema, and a broken response is retried. Free text parsed with regular expressions was the first attempt and did not last.
Plan limits in one place. Free and Pro limits on items and groups also sit in packages/shared, read by all three clients.
What was deferred
- The read-later / watch-later type is chosen by hand when saving. Automatic detection is in the spec (YouTube and Vimeo URLs as watch-later, pages with an extractable body as read-later, PDFs defaulting to read-later) and was deferred
- Sharing scopes started with three: only me, a specific group, the whole organization. Sharing with anyone who has a link stays a candidate in the spec
- Each member keeps their own status on a shared item. That one was never on the table for cutting: without “who has read this”, sharing with a team loses its point
Now
LaterHub is in open beta and every feature is free. It is for people who want a Pocket replacement that also works as shared team knowledge. laterhub.app
RELATED
Flutter, AWS, homelab. A few side projects and open-source tools. For architecture questions or collaboration, reach out via X DM or the About page. About