Stashly: A Link Memory System That Searches by Meaning, Not Just Title

A browser-extension-first monorepo that scrapes pages, builds embeddings in the background, and uses PostgreSQL plus pgvector to turn saved links into retrievable knowledge.

8 min read • View on GitHub • More from Rahi-padwal

A browser extension panel captures a link from a webpage while a saved card moves through a sequence of processing steps and reappears as a match in search results. The scene explains that saving is instant, but retrieval is powered by a deeper semantic pipeline behind the scenes.
Stashly treats link saving as a memory problem. The user clicks once, then the system quietly turns a URL into something that can be found by meaning later.
Key Takeaways

Saving a link is easy. Finding it three days later is the part that hurts. Stashly is built around that gap, and it treats the problem like memory, not filing.

That is the useful twist. It is not trying to be a prettier bookmark shelf. It is trying to make “I know I saved that somewhere” stop being a dead end.

The bookmark problem Stashly is really solving

Traditional bookmark tools optimize for placement. Put the link in a folder, add a tag, maybe remember the title. Stashly optimizes for recovery. It wants to get you back to a page when your memory is partial, fuzzy, or wrong.

I love working at the intersection of backend engineering and AI — from designing REST APIs to experimenting with RAG pipelines and vector databases.

Rahi Padwal, Creator / Maintainer · Rahi Padwal Portfolio

That framing fits the codebase. The repo is organized as a monorepo with a backend, a web app, and a browser extension, which is exactly what you would build if capture and recall were the whole product.

Why extension-first is the right capture model

The browser extension is not a garnish here. It is the front door. If capture has friction, the semantic layer never gets enough material to become useful.

That matters because memory systems fail when saving becomes a chore. Stashly’s extension-first design keeps the action close to the moment of discovery, which is when people are willing to save the page at all.

The interesting product move is that the extension does not need to solve retrieval in the moment. It only needs to make capture painless. Everything else can happen later.

A split scene shows the same person searching two ways. On the left, an exact-title search produces a brittle partial match from a thin stack of folders. On the right, a concept-driven query pulls the right link out of a clustered web of related cards and nodes. The image explains why semantic retrieval beats exact keyword matching for recall.
Exact titles are fragile. Semantic search gives saved links a second chance when the user remembers the idea but not the label.

What happens after you click save

The core pipeline is simple to describe and more interesting to implement. A URL comes in, the backend scrapes it, cleans the text, and sends the content into an embedding job that runs in the background.

The save action returns fast, but the expensive part keeps running in the background. That separation is what makes the product feel instant while still producing better results later.

The implementation detail that matters is the asynchronous boundary. The API can respond before embedding finishes, so the user gets speed up front and retrieval quality later. That is the right trade-off for a consumer tool.

Why pgvector matters here

Stashly is not using Postgres as passive storage. It uses Postgres as the retrieval engine. That is a subtle but important difference, because it keeps the app data and vector data in the same operational model.

In the schema, embeddings are stored as a 768-dimensional vector, which matches the model output and makes similarity search native to the database. The result is less infrastructure sprawl and fewer moving parts to reason about.

That choice also keeps the stack legible. You do not need a separate vector service just to ask, “Which saved page feels most like this query?”

ApproachStrengthWeaknessWhat Stashly does differently
Traditional bookmark managerFast to save and easy to organize by folderHard to recover when you forget the title or tagAdds semantic retrieval on top of capture
Keyword-only searchSimple and predictableBreaks on fuzzy memory and technical jargonBlends keywords with extracted text and vectors
Pure vector searchGood at concept matchingCan feel opaque and sometimes overmatchKeeps semantic search grounded with metadata and query expansion

The search trick: embeddings plus expansion

This is the heart of the system. Stashly does not rely on vectors alone. It also stores extracted text and keywords, then expands certain search terms so technical shorthand does not disappear into the noise.

That hybrid approach is what makes the product feel practical. Pure vector search can be elegant, but if a user types a niche abbreviation or a memory fragment, keyword signals still matter.

The result is less glamorous than a demo of embeddings and more useful in day-to-day use. The system can match intent without pretending the exact words no longer matter.

What the backend is doing under the hood

The scraper uses Cheerio to strip scripts and styles, then extracts page metadata and body text. That gives the embedding model cleaner input and avoids teaching the system from junk.

The embedding layer is also defensive. It validates dimensions and falls back to alternate models when the primary one is unavailable, which turns an external dependency into something the app can survive.

The monorepo is doing product work, not just code organization

The structure tells you the product shape. `apps/extension` captures. `apps/backend` processes and searches. `apps/web` makes the saved graph visible. That is a user journey, not just a folder tree.

The repo’s layout also says something about ambition. This is not a weekend script glued to a UI. It is an attempt to make capture, enrichment, and retrieval behave like one system.

LayerRole in the productWhy it exists
ExtensionCapture at the point of discoveryReduces friction to nearly zero
BackendScrape, enrich, index, and searchTurns raw links into retrievable memory
Web appReview and search the libraryMakes the saved material usable
DatabaseStore relational data and vectorsKeeps structure and semantic recall together

What Stashly is really competing with

The obvious comparison is a bookmark manager. The better comparison is a tool that improves recall. Stashly is competing on whether a user can get back to the right page with half a memory and a vague prompt.

That puts it in a different category from simple link storage. The benchmark is not “Can I save this?” The benchmark is “Can I find it when my memory is bad?”

That is a harder problem, and a more interesting one. If Stashly works, the user stops thinking about folders altogether.

Why this design is credible

The strongest thing about the repo is restraint. It uses AI where AI is useful, and conventional software where conventional software is better. Scraping, storage, auth, and search all stay close to standard backend practice.

That is what makes the project feel real. It is not chasing novelty for its own sake. It is using a modern stack to solve an old problem more intelligently.

In the end, Stashly is interesting because it turns link saving into a memory system with a serious retrieval model behind it. That is a small idea with a lot of product surface area.