Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dogear

A personal bookmark server, plus the Firefox extension that feeds it. Runs on your own machine, works on desktop and Android, and keeps its own copy of every preview image so your library never goes blank.

┌─────────────────┐        ┌──────────────────────────────┐
│  Firefox        │        │  Dogear server               │
│  desktop/mobile │──save─▶│  FastAPI + SQLite            │
│  (extension)    │        │  fetches metadata            │
└─────────────────┘        │  caches previews locally     │
                           │  serves the web library      │
┌─────────────────┐        │                              │
│  Any browser    │◀──────▶│  http://your-machine:8000    │
│  (web library)  │        └──────────────────────────────┘
└─────────────────┘

Install

git clone https://github.com/Suman2023/dogear.git dogear
cd dogear
./scripts/install.sh

That creates a virtual environment, installs the dependencies, writes a systemd unit, and starts the service. It survives reboots and restarts itself if it crashes. It prints the address to use from your phone.

./scripts/install.sh --port 9000       # different port
./scripts/install.sh --user            # per-user service, no root
./scripts/install.sh --host 127.0.0.1  # this machine only

Requires Python 3.10+ and systemd. Nothing else.

Removing it

./scripts/uninstall.sh          # stops and removes the service, keeps bookmarks
./scripts/uninstall.sh --purge  # also deletes the database and cached images

Running it without installing

./scripts/dev.sh          # auto-reloads on edit, http://127.0.0.1:8000
./scripts/dev.sh --lan    # also reachable from your phone
python3 scripts/seed.py   # fill it with sample bookmarks to click around

Onto a Raspberry Pi

./scripts/deploy.sh john@<pi-ip> --setup-keys   # once, stops password prompts
./scripts/deploy.sh john@<pi-ip> --with-data --install

Copies the project over rsync (skipping the venv, caches and build output), then runs install.sh there. --with-data brings your existing bookmarks and cached previews across. Everything shares one SSH connection, so you are asked for a password at most once.

./scripts/deploy.sh john@<pi-ip> --install   # push an update
./scripts/deploy.sh john@<pi-ip> --restart   # just restart the service

The extension

Try it now

about:debuggingThis FirefoxLoad Temporary Add-on → pick extension/manifest.json. It stays until Firefox closes.

Then open its settings, enter your server address (the one install.sh printed), and press Save and connect. Firefox will ask permission to talk to that address.

Publishing it

extension/STORE.md has the whole process — every listing field written out ready to paste, the reviewer notes, the Android compatibility steps, and the screenshot list.

Using a different server

The extension doesn't know or care that server/ exists — it only speaks the HTTP contract in API.md. Point it at any server that implements those endpoints and it works the same way.

./scripts/package-extension.sh   # builds dist/dogear-<version>.zip and lints it

The extension currently passes web-ext lint with 0 errors, 0 warnings, 0 notices, uses no bundler or minifier (so AMO needs no source submission), and declares Android support.


What it does

Saving

  • One click saves the page, with title, description, preview image and favicon already filled in.
  • The toolbar icon shows a checkmark when the page is already saved, so you don't file the same thing twice. Click it again to update or remove.
  • Tag while saving, with suggestions drawn from tags you already use.
  • Select text on a page and save it as the bookmark's note.
  • Right-click any link to save it without opening it.
  • Alt+Shift+S saves silently; Alt+Shift+D opens the popup.

Firefox bookmark sync

  • Star a page in Firefox and it lands on your server too, tagged with the folder you filed it under. Switch off in settings if you don't want it.
  • Push all bookmarks in settings sends your entire existing Firefox library across in one go, folders becoming tags, with a progress bar. It skips anything already there, so it is safe to run twice.

The library

  • Grid, list, and compact layouts.
  • Full-text search across titles, descriptions, notes, tags and URLs, using SQLite FTS5 with prefix matching — results appear as you type.
  • Filter by tag, by site, or by favourites / unvisited / untagged / archive / broken links. Filters live in the URL, so any view can be bookmarked itself.
  • Select several cards for bulk tagging, archiving or deletion.
  • A monospace "Console" interface: hairline rules, no shadows or blur, numbered rows.
  • Appearance settings are stored on the server, so the theme, accent colour and default layout are the same on every device you open it from. Dark by default, with a light "paper terminal" alternative and six accent schemes. ?theme= and ?layout= override per link.
  • Every bookmark records which browser and device saved it — Zen (Linux), Firefox (Android) — so you can tell where something came from.
  • Installable as a web app on Android, and it still opens offline.
  • Deleting shows an Undo for eight seconds.

Keeping previews working

This is the part that most bookmark tools get wrong, and the reason the old version showed blank cards:

  1. The extension reads what the page publishes, handling both property="og:image" and the widespread name="og:image" spelling.
  2. The server independently fetches the page and parses it again, so pages the extension couldn't read still get a preview.
  3. If there is no card metadata at all, the server looks for a suitable image in the page body, ignoring logos, sprites and tracking pixels.
  4. Sites that refuse anonymous requests (Wikipedia among them) are retried once with a user agent that identifies Dogear honestly.
  5. Every preview and favicon is downloaded and stored locally. Hotlink protection, expiring CDN URLs and deleted images cannot break your library afterwards.
  6. Anything still missing can be filled in later with Rebuild previews under Import & export.

Against a sample of twenty real sites this yields previews for 14, and favicons and descriptions for essentially all of them.

Import and export

  • Export as JSON, or as a standard browser bookmark file that imports straight back into Firefox, Chrome or Safari.
  • Import a browser export (folders become tags), a Dogear JSON file, or a plain list of URLs. Duplicates are detected and skipped.

Housekeeping

  • Check for dead links flags bookmarks whose pages no longer respond, collected under a Broken links view.
  • URLs are normalised before saving — tracking parameters stripped, www. and trailing slashes ignored — so the same page saved twice stays one bookmark.
  • Reading time is estimated from the page's word count.

Layout

dogear/
├── scripts/
│   ├── install.sh              systemd service, starts on boot
│   ├── uninstall.sh            removes it; --purge deletes data too
│   ├── dev.sh                  local server with auto-reload
│   ├── seed.py                 sample bookmarks for testing
│   ├── deploy.sh               copy to a Pi and install it there
│   ├── make-icons.py           regenerates every PNG icon
│   └── package-extension.sh    builds and lints the AMO zip
├── server/
│   ├── app/
│   │   ├── main.py             HTTP API
│   │   ├── db.py               schema, migrations, search index
│   │   ├── enrich.py           page fetching, metadata, image cache
│   │   ├── urls.py             normalisation and deduplication
│   │   ├── transfer.py         import/export
│   │   ├── models.py           request/response shapes
│   │   └── config.py           environment settings
│   ├── static/                 the web library (no build step)
│   ├── tests/                  77 tests
│   └── data/                   your database and cached images
└── extension/
    ├── manifest.json           MV3, desktop + Android
    ├── background.js           metadata, icon state, sync, menus
    ├── lib/dogear.js           shared API client
    ├── popup/                  the save panel
    ├── options/                settings and bulk push
    └── STORE.md                how to publish on AMO

Your data lives in server/data/ — one SQLite file and a folder of cached images. Back it up by copying that directory.


Tests

cd server
.venv/bin/python -m pytest tests/ -q

77 tests covering the API, URL normalisation and deduplication, metadata extraction, import/export round trips, and — importantly — upgrading an existing v2 database without losing bookmarks. They run offline; no test touches the network.


Configuration

Everything has a working default. Override with environment variables in the systemd unit if you need to:

Variable Default Meaning
BOOKMARKS_DATA_DIR server/data Where the database and images live
BOOKMARKS_API_KEY auto-generated The shared key; see "A note on access"
BOOKMARKS_SESSION_DAYS 90 How long a web login stays signed in
BOOKMARKS_FETCH_TIMEOUT 15 Seconds to wait for a page
BOOKMARKS_ENRICH_CONCURRENCY 4 Pages fetched at once
BOOKMARKS_MAX_IMAGE_BYTES 8000000 Largest preview to cache
BOOKMARKS_USER_AGENT a Chrome string Used when fetching pages

A note on access

Dogear is protected by a single shared key, BOOKMARKS_API_KEY. If you don't set one, the server generates a random one on first run and keeps it in server/data/.api_key — read it with cat server/data/.api_key.

  • The web library exchanges the key for a session cookie at a login screen the first time you open it, and stays signed in from then on.
  • The extension needs the key pasted into its settings, next to the server address.
  • A bookmarklet or share-sheet shortcut that can't set a header can instead append ?api_key=... to the request URL — e.g. https://your-server/api/bookmarks?api_key=... for a POST body it can't otherwise sign. This is weaker than the other two: the key ends up in browser history and in the server's access log, so only use it where a header genuinely isn't an option, and rotate the key if such a URL ever leaks.

Rotate it at any time by deleting server/data/.api_key (and .session_secret, to sign everyone out) and restarting the service, or by setting BOOKMARKS_API_KEY yourself in the systemd unit.

This is still a single shared secret, not a full account system — treat it like a password. It's what makes it reasonable to expose Dogear through a tunnel (Cloudflare Tunnel, Tailscale Funnel) or a reverse proxy; for anything more sensitive, put it behind a VPN such as Tailscale instead.


Licence

Mozilla Public License 2.0 — the same licence Firefox itself uses. Use it, modify it, ship it inside something larger; changes to the files themselves stay under the MPL.

PRIVACY.md is the privacy policy, reproduced on the add-on's listing page. Nothing here collects or transmits anything to anyone but the server you run.

About

Save pages to your own Dogear bookmark server, with previews, tags and notes. Works on desktop and Android.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages