A modern, self-hosted bookmark manager with browser sync, Flow Launcher integration, REST API, and SQLite backend.
Note: This project was built with AI-assisted development using mostly GitHub Copilot but also Claude and Google Antigravity.
If the animation doesnβt load, see the Live Tour below.
See a quick visual tour below, or jump to Quick Start.
Most bookmark managers focus on either personal archiving or team knowledge bases. AnchorMarks optimizes everyday personal workflows:
- Fast daily use: Instant search, keyboard-first filtering, and a clean UI you can live in.
- Self-hosted and simple: SQLite backend, single Express app, optional Docker β no heavy infra.
- Works with your tools: Browser extensions for sync and a Flow Launcher plugin for quick lookup.
Compared to Linkwarden/Linkding/Shaarli, AnchorMarks emphasizes minimal setup, responsive UI, and smooth browser + launcher integration over heavy archiving pipelines.
| Capability | Details |
|---|---|
| π Browser Sync | Chrome / Edge / Firefox extension included |
| π Flow Launcher | Plugin integration for quick search |
| π REST API | Read/write endpoints with JWT + CSRF |
| ποΈ SQLite DB | better-sqlite3 with WAL |
| π³ Docker | Compose setup, helper scripts provided |
| π SSL | Reverse proxy ready (sample nginx.conf) |
| π₯ Import/Export | Netscape HTML + JSON |
| π·οΈ Tags & Folders | Nested folders, tag analytics & suggestions |
| πΌοΈ Favicons | Automatic fetching and local caching |
| π Dark Mode | Beautiful light and dark themes |
| π± Responsive | Works on desktop, tablet, and mobile |
| β Favorites | Quick access to important bookmarks |
| π― Advanced Filtering | Full-width filter bar with folder/tag counts, persistent search filters, & tag mode toggle (see Help) |
| π¬ Smart Omnibar | Unified search + command palette with recent searches, tag suggestions, & filter application |
-
Dashboard: configurable widgets and quick-access favorites.
-
Search: fast, ranked results with filter bar.
-
Mobile: responsive layout with the same features on-the-go.
- Sign up and create your account.
- Import bookmarks (HTML/JSON) and auto-fetch favicons.
- Organize with folders and tags; use suggestions to speed up categorization.
- Search and filter by folder/tag; pin favorites for quick access.
# From repo root
make install-deps
# Option A: Full stack (backend + Vite frontend) using Makefile
make run-all
# Backend on http://localhost:3000, Frontend on http://localhost:5173
# Option B: Backend only (serve classic UI)
make run-backend
# Visit http://localhost:3000
# Option C: Frontend-only HMR during UI work
make run-frontend
# Visit http://localhost:5173 (API must be running: make run-backend)
# Option D: Run E2E tests (requires backend + frontend running)
make test-e2e
# Or in UI mode: make test-e2e-ui
# Or in debug mode: make test-e2e-debug
# For a complete list of commands:
make help# Build and start the stack
make build-docker
make run-docker
# Logs and shell
make logs-docker
make shell-dockerCompose file: tooling/docker/docker-compose.yml. The stack reads variables from .env.
- For production, set
JWT_SECRETandCORS_ORIGIN; never rely on defaults. Use a strong random value forJWT_SECRETand your actual front-end origin(s) forCORS_ORIGIN(comma-separated if multiple). - Enable rate limiting on auth endpoints.
- Run behind an SSL-terminating reverse proxy (see tooling/deploy/nginx.conf).
- Block private/loopback SSRF targets; production code already enforces this. π View full documentation β Β· Installation Guide Β· Vite Migration
For production, set JWT_SECRET and CORS_ORIGIN; never rely on defaults. The app will not start in production without valid values.
# Required (production)
NODE_ENV=production
JWT_SECRET=change-me
CORS_ORIGIN=https://yourdomain.tld
# Optional
PORT=3000
DB_PATH=apps/database/anchormarks.db
ENABLE_RATE_LIMIT=true
VITE_PORT=5173Then run:
make run-prodSee INSTALL.md for advanced deployment options.
- Help & Documentation - Complete user guide with all features (in-app)
- INSTALL.md - Installation and quick start guide
- CHANGELOG.md - Release history and notable changes
- SECURITY.md - Security policy and best practices
- CONTRIBUTING.md - Development guidelines
- Auth & CSRF Flow - Developer reference: help.html#developer-auth-csrf
The project uses Vitest for unit/integration tests and Playwright for E2E tests.
# Run unit/integration tests
make test-all # Run all tests
make test-backend # Backend only
make test-frontend # Frontend only
make test-coverage # Coverage report
# Run E2E tests
make test-e2e # Headless mode
make test-e2e-ui # Interactive UI mode
make test-e2e-headed # Visible browser
make test-e2e-debug # Debug mode with InspectorE2E tests verify:
- Tag cloud rendering and interaction
- Tag filtering updates header and bookmarks
- Bookmark cards display correctly
- Dynamic legend height calculation
- Responsive layout on resize
- Password Hashing - bcryptjs
- JWT Authentication - Secure token-based auth
- CSRF Protection - Tokens for state mutations
- User Isolation - Per-user data filtering
- Input Validation - URLs, names, tags sanitized
- SSRF Guard - Private IP blocking
See SECURITY.md for details.
- Node.js 18 or newer
- SQLite available on host (bundled with better-sqlite3)
- Recommended: 1 vCPU, 512MB RAM for small datasets
- Tested browsers: Chrome, Firefox, Edge (latest)
- Monorepo with workspaces:
apps/server(Express + SQLite) andapps/client(Vite + TypeScript). - Single API app handles auth, bookmarks, folders, tags, smart collections, and health tools.
- Frontend is a vanilla JS/TS app with stateful views and API helper.
- Background helpers: favicon/metadata fetchers with SSRF guards.
- Start backend only:
make run-backend - Start frontend HMR:
make run-frontend(requires backend running) - Full stack dev:
make run-all - Run unit tests:
make test-all, coverage:make test-coverage - Run E2E tests:
make test-e2e(requires backend running on port 3000) - Lint & format:
make lint-codeormake lint-check - Docker during local dev:
make run-dockerthenmake logs-docker
Note: Makefile target aliases (e.g.,
dev,docker-up,e2e,lint) were removed to standardize on the Verb-Noun pattern. Please update scripts and CI to use the new target names (for example:run-backend,run-docker,test-e2e).
- Open an issue: https://github.com/gogogadgetscott/AnchorMarks/issues
- Feature ideas and feedback welcome β see CONTRIBUTING.md
MIT License - use, modify, and distribute freely.
View full documentation in Help β
- Docker compose file:
tooling/docker/docker-compose.yml(use from project root) - Environment file:
.envβdocker:upparsesPORTfrom this file and the compose stack usesenv_fileto inject runtime variables. - If host bind-mounted
data/directory lacks correct permissions, fix ownership before starting:
sudo chown -R 1001:1001 data/ # adjust path/user to your environment
make run-docker- For production servers, prefer fixing host permissions (chown to UID 1001) and removing the need for sudo in automation.
To run the test suite inside a container (installs dev dependencies temporarily):
docker compose -f tooling/docker/docker-compose.yml run --rm anchormarks make test-all- AnchorMarks now stores flexible user preferences in a JSON column
settings_jsonwithin theuser_settingstable. This avoids schema changes for each new setting. - On startup, the server auto-migrates existing databases by adding the
settings_jsoncolumn if it does not exist. No manual action is required. - Known settings continue using dedicated columns for backward compatibility. New settings are saved under
settings_jsonand merged into/api/settingsresponses transparently.
