DEV Community

Andreas Sander
Andreas Sander

Posted on • Originally published at andi1984.dev

Ferrico - Taking My Bookmarks Back Home with Tauri and Rust

Hello developers,

Today I would like to talk about a tool I have been building in the open: Ferrico. It is a desktop bookmark manager, but the interesting part is where your bookmarks live - and it is not in someone else's cloud.

The itch was a very ordinary one. My bookmarks were scattered across three browsers, two devices and one read-it-later service that had quietly started rate-limiting my free account. Every one of them wanted an account, sold me sync as a feature, and politely held my own links hostage behind a login. So I did what I always end up doing: I built my own thing and learned a lot on the way.

What does "local-first" even mean?

Before we dive into code, let us define the term, because the whole project hangs on it:

Local-first software [...] gives users full agency over their own data. [...] The availability of another computer should never prevent you from working.
-- Ink & Switch, "Local-first software"

That is the whole pitch. Ferrico stores everything in a single SQLite file on your machine. No account, no telemetry, no Ferrico-operated backend anywhere. The network is something you can opt into, never something you depend on.

Why build my own (again)?

Let us be honest - the world does not need another bookmark manager. But I wanted three things at once, and nothing on the market gave me all of them:

  1. Ownership: my links in a file format I can read, back up and grep ten years from now.
  2. A native footprint: not a 300 MB Electron app idling at 400 MB of RAM to show me a list.
  3. Something to learn: I had been itching to write real Rust instead of toy examples.

That third point is the honest one. Just like with Back2Roots, my home-grown static site generator, half the motivation was simply to get my fingers dirty with a stack I wanted to understand better.

The stack

Layer Technology
Shell Tauri 2 (Rust)
Frontend React 19, TypeScript, Vite, Tailwind 4
Storage SQLite via rusqlite
Extension A loopback axum server
Tooling Bun for the JS side

Tauri is the star here. Instead of bundling a whole Chromium like Electron does, it uses the operating system's own webview and ships a small Rust binary next to it. You write your UI in plain web tech, and anything that touches the disk, the database or the OS goes through Rust commands. The result is an installer measured in single-digit megabytes instead of hundreds.

A single file you actually own

The data layer is intentionally boring, and that is the point. One SQLite database, in the place your OS expects it:

Linux    ~/.local/share/ferrico/ferrico.db
macOS    ~/Library/Application Support/ferrico/ferrico.db
Windows  %APPDATA%\ferrico\ferrico.db
Enter fullscreen mode Exit fullscreen mode

Because it is just SQLite, fuzzy search across titles, URLs and page content is a query, not a service. Import and export are lossless JSON snapshots, so you are never locked in - and for the migration day there is Netscape HTML, OPML and CSV on top. A bookmark manager whose export button actually round-trips: revolutionary, I know.

The browser extension problem

Here is the part I found genuinely fun to solve. A bookmark manager is useless if saving the current tab means alt-tabbing to a separate app. You want a button in the browser. But the browser and a native Tauri app live in two different worlds and cannot just call each other.

The trick: Ferrico runs a tiny HTTP server inside the Rust process, bound to loopback only.

// Bound to 127.0.0.1 - never reachable from the network.
let listener = TcpListener::bind("127.0.0.1:59432").await?;
axum::serve(listener, app).await?;
Enter fullscreen mode Exit fullscreen mode

The Manifest V3 extension then POSTs the current tab to http://127.0.0.1:59432, authenticated with a token you copy out of the app's settings. Two important properties fall out of this:

  • It never leaves your machine. The socket is bound to 127.0.0.1, so nothing on your LAN - let alone the internet - can reach it.
  • It is explicit. No pairing handshake, no account; the extension only works once you paste the token.

Loopback-only plus a shared secret is a humble pattern, but for a one-user desktop tool it is exactly the right amount of security: enough to stop a random page from talking to your library, not so much that you need a login server to manage it.

Optional, never required

Two features deliberately sit outside the local core, and both are off by default.

Cloud sync is a lossless JSON snapshot in your Google Drive, using OAuth credentials you create, scoped to drive.file so the app can only touch its own files. Conflict resolution is deliberately dumb - last write wins, one machine at a time. No clever CRDT, no Ferrico server in the middle. You own the OAuth app; I never see a byte.

AI features lean on the Claude CLI if - and only if - it happens to be on your PATH. Natural-language search, auto-sorting the inbox, mapping messy CSV columns on import. When you explicitly invoke one of these, the relevant bookmark metadata is handed to your local claude binary, which talks to Anthropic on your behalf. No invocation, no network call. The intelligence is a guest in the house, not the landlord.

Let us be honest about the trade-offs

No free lunch, as always:

  • Sync is primitive on purpose. Last-write-wins means if you edit on two machines between syncs, one set of edits loses. For a personal bookmark stash that is a fine trade; for a shared team tool it would not be.
  • Local-first means you own the backups too. There is no magical cloud safety net unless you switch one on. Your file, your responsibility.
  • It is young. Ferrico is happily sitting at v0.x (currently v0.9.0). Desktop runs on macOS, Linux and Windows; Android is still very much a work in progress.

But for me the deal is worth it. My bookmarks are a file I can see, search instantly, back up however I like, and read without asking anyone's permission.

It is open-source!

Ferrico is published on GitHub under the GPL-3.0-or-later license, and there is a live demo if you would like to click around before installing anything. Want to build it yourself? It is the usual two lines:

bun install
bun tauri dev
Enter fullscreen mode Exit fullscreen mode

Feel free to fork it, file an issue, or send a feature request. And if you have been looking for an excuse to write some Rust - this is a very welcoming one.

Cheers,

Andi 🔖

Top comments (0)