Saving links doesn't make you smarter. Learning from them does.

Personal Project·2026–now·Web App · PWA·view project ↗

Problem

I was that person with hundreds of saved links I'd never open again. I saved articles, videos, references. But when I needed something, I'd end up searching for a title I barely remembered, in folders I barely organized. The tool I used organized what I saved. The problem was it didn't help me learn from it or find it when I actually needed it.

So I built Coisas.space around one question: what if the content you saved could surface itself when you need it, without you having to remember it existed?

The AI stack

Categorization runs on gpt-4o-mini via OpenRouter at temperature 0.2. I found that temperature through testing: higher temperatures introduced category drift, the same link categorized differently on repeat saves. 0.2 gives the consistency that a categorization feature needs to be trusted.

The conversational retrieval layer uses the category as a scoped context signal, a RAG-like approach fast enough for consumer UX and accurate enough to be useful. I tested with full document embedding and it was slower than the actual query patterns justified.

When context is thin, retrieval falls back through three levels: visible content from the active category (last 3 days), then all content from that category, then all content regardless of category. The fallback strategy keeps responses grounded even for users who just started.

The Foco Time matching algorithm uses semantic AI, so "Learn React" surfaces links about hooks, components, and JSX, including links that never mention React in the title. Results are cached in KV with hash-based invalidation: when a new link is saved, the hash changes, cache invalidates, and the next match request regenerates.

The design decisions

Streaming was non-negotiable for me. Any categorization that required waiting would break the save habit. The product only works if saving feels instant. The link appears immediately in the grid with a pending state, categorization completes in the background, status progresses from pending to processed to read.

I scoped the conversational interface by category on purpose. Open-ended chat over all saved content produced irrelevant answers in testing, so narrowing the context was the decision that made the feature work. When users switch categories while a chat is open, an inline warning appears with two options: keep the current context or re-ground the conversation in the new category.

The /resumir command uses Fibonacci-based progressive disclosure: the first call returns 5 links. Users can ask for more, and the sequence expands to 8, 13, 21, 34. Users discover what they have at the pace they need.

The failure mode

When the model can't categorize a link confidently (paywalled pages, ambiguous content, broken URLs), the link lands in an Uncategorized state with a manual override option. The link is always there, always accessible. The AI is an additive layer on top of the data, so when it fails, the link stays available.

The AI provider layer has a fallback: if OpenRouter returns a 402 (credits exhausted), the system automatically routes to OpenAI with a 1-hour retry window. Service status is tracked in KV: provider, last error, failed attempts, last success time. Users never see a provider switch.

Content extraction uses silent failure: if it times out at 10 seconds, the link still works with its metadata. I prioritized response speed here, because a link in the grid already serves the user, even without the full content extracted.

Row-level security is enforced at the database level and in the application layer. Every user data table has RLS policies bound to auth.uid(). No application bug can leak one user's data to another.

What's next

I want to add deep reading via Firecrawl, extracting actual content from saved links beyond the metadata. And Gmail OAuth to pull newsletters and threads directly into the library, turning the inbox into a learning feed. What I'm most excited about is the reading layer, because that's what will make the AI responses genuinely useful, grounded in what you actually read.

previous read

Resense →

Resense is a product that uses AI to turn any data a team already has (CSVs, PDFs, text, images) into Synthetic Users, with RAG and embeddings. It also generates insights with weighted cause-and-effect connections. I used AI across the whole process, from research to testing.