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.
Screenshots
Compact List View
Card View with Open Graph Images
Empty State
✨ Features
- 🚀 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)
- Create a
docker-compose.ymlfile:
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
- Start the service:
- Access QuickMark at
http://localhost:9022
Using Docker Run
docker run -d \ --name quickmark \ -p 9022:9022 \ -v ./data:/app/data \ -e NODE_ENV=production \ ghcr.io/drkpxl/quickmark:latest
Custom Port
To use a different port (e.g., 8080):
ports: - "8080:9022" environment: - PORT=9022 # Keep internal port at 9022
Local Development
Prerequisites
- Node.js 22 (LTS)
- npm or pnpm
Setup
- Clone the repository:
git clone https://github.com/drkpxl/quickmark.git
cd quickmark- Install dependencies:
- Start the development server:
- Open
http://localhost:9022
Build for Production
npm run build npm run preview
Keyboard Shortcuts
| 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 |
View Modes
- 📋 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
Using Tags
Tags help organize your bookmarks:
- Add tags when saving a bookmark (comma-separated:
dev, javascript, tutorial) - Click any tag to filter bookmarks by that tag
- Multiple tags can be selected simultaneously (AND filtering)
- Click "Clear" to reset filters
Data Management
Database Location
Your bookmarks database and assets are stored in the ./data directory:
data/
├── bookmarks.db # SQLite database
└── assets/ # Favicons and images
Backup
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
Restore
docker-compose down rm -rf data cp -r data-backup-20251017 data docker-compose up -d
Export
Use the built-in export functionality:
- JSON Export: Complete bookmark data with all metadata
- HTML Export: Standard Netscape bookmarks format (compatible with all browsers)
Architecture
Tech Stack
- 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)
Project Structure
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
Deployment
Environment Variables
| Variable | Default | Description |
|---|---|---|
NODE_ENV |
production |
Node environment |
PORT |
9022 |
Port to listen on |
HOST |
0.0.0.0 |
Host to bind to |
API Endpoints
| 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 |
Roadmap
- Uptime monitoring, see if a link is dead and update that its a deadlink
- Archive.org intergration.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built with SvelteKit
- Styled with Bootstrap
- Icons from Bootstrap Icons
Issues & Support
If you encounter any issues or have questions, please open an issue on GitHub.



