Show HN: Quickmark Lightweight Bookmark Manager

3 weeks ago 2

A minimalist, self-hosted bookmarking service designed to be your default new tab page. Built with SvelteKit 5, QuickMark provides a fast, privacy-focused way to save and organize your bookmarks.

 MIT Docker SvelteKit

Compact View - showing bookmarks with favicons, titles, descriptions, and tag filtering

Card View with Open Graph Images

Card View - grid layout with preview images and tags

Empty state - clean interface ready for your first bookmark

  • 🚀 Fast & Lightweight: Single-page application optimized for speed
  • 🔒 Privacy-First: Self-hosted, no tracking, no external dependencies
  • 📝 Auto Metadata: Automatically extracts titles, descriptions, and favicons
  • 🏷️ Tag Support: Organize bookmarks with comma-separated tags
  • 🔍 Instant Search: Real-time filtering across all bookmark metadata
  • ⌨️ Keyboard Shortcuts: Navigate and manage bookmarks without touching your mouse
  • 🎨 Multiple Views: Choose between compact list, card, or dense layouts
  • 🌓 Dark Mode: Built-in theme support with system preference detection
  • 📤 Export: Download your bookmarks as JSON or HTML (Netscape format)
  • 💾 Data Persistence: SQLite database with local asset storage

🐳 Quick Start with Docker

Using Docker Compose (Recommended)

  1. Create a docker-compose.yml file:
services: quickmark: image: ghcr.io/drkpxl/quickmark:latest container_name: quickmark restart: unless-stopped ports: - "9022:9022" volumes: - ./data:/app/data environment: - NODE_ENV=production - PORT=9022 - HOST=0.0.0.0
  1. Start the service:
  1. Access QuickMark at http://localhost:9022
docker run -d \ --name quickmark \ -p 9022:9022 \ -v ./data:/app/data \ -e NODE_ENV=production \ ghcr.io/drkpxl/quickmark:latest

To use a different port (e.g., 8080):

ports: - "8080:9022" environment: - PORT=9022 # Keep internal port at 9022
  • Node.js 22 (LTS)
  • npm or pnpm
  1. Clone the repository:
git clone https://github.com/drkpxl/quickmark.git cd quickmark
  1. Install dependencies:
  1. Start the development server:
  1. Open http://localhost:9022
npm run build npm run preview
Shortcut Action
Ctrl+Enter Save bookmark (when URL field is focused)
/ or Ctrl+F Focus search input
j or ↓ Navigate to next bookmark
k or ↑ Navigate to previous bookmark
Enter Open selected bookmark in new tab
d Delete selected bookmark (with confirmation)
Esc Clear search or close modal
? Show keyboard shortcuts help
  • 📋 Compact List (default): Single line per bookmark with all metadata visible
  • 🖼️ Card View: Responsive grid layout with Open Graph images
  • 📝 Dense View: Minimal list showing only favicons and titles

Tags help organize your bookmarks:

  1. Add tags when saving a bookmark (comma-separated: dev, javascript, tutorial)
  2. Click any tag to filter bookmarks by that tag
  3. Multiple tags can be selected simultaneously (AND filtering)
  4. Click "Clear" to reset filters

Your bookmarks database and assets are stored in the ./data directory:

data/ ├── bookmarks.db # SQLite database └── assets/ # Favicons and images

Simply copy the entire data/ directory to create a backup:

# Stop the container first docker-compose down # Backup cp -r data data-backup-$(date +%Y%m%d) # Restart docker-compose up -d
docker-compose down rm -rf data cp -r data-backup-20251017 data docker-compose up -d

Use the built-in export functionality:

  • JSON Export: Complete bookmark data with all metadata
  • HTML Export: Standard Netscape bookmarks format (compatible with all browsers)

JSON Export Example

  • Frontend: SvelteKit 5 with Svelte 5 runes
  • Styling: Bootstrap 5.3.3
  • Database: SQLite via better-sqlite3
  • Metadata Extraction: jsdom for HTML parsing
  • Runtime: Node.js 22 (Alpine Linux in Docker)
src/ ├── routes/ │ ├── +layout.svelte # App layout with theme toggle │ ├── +page.svelte # Main bookmarks page │ ├── +page.server.ts # SSR data loading │ ├── api/ │ │ ├── bookmark/+server.ts # POST: Save bookmark │ │ ├── bookmark/[id]/+server.ts # DELETE: Remove bookmark │ │ └── export/+server.ts # GET: Export bookmarks │ └── assets/[...path]/+server.ts # Serve local assets └── lib/ └── server/ ├── db.ts # SQLite operations └── metadata.ts # Metadata extraction logic
Variable Default Description
NODE_ENV production Node environment
PORT 9022 Port to listen on
HOST 0.0.0.0 Host to bind to
Method Endpoint Description
GET / Main application page
POST /api/bookmark Save new bookmark with metadata
DELETE /api/bookmark/:id Delete specific bookmark
GET /api/export?format=json|html Export bookmarks
GET /assets/:path Serve locally stored assets
  • Uptime monitoring, see if a link is dead and update that its a deadlink
  • Archive.org intergration.

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

This project is licensed under the MIT License - see the LICENSE file for details.

If you encounter any issues or have questions, please open an issue on GitHub.

Read Entire Article