Skip to content

Deploying Briefkasten

Briefkasten is a modern, self-hosted bookmarking application that helps you save, organize, and discover your web bookmarks. Built with Next.js, Prisma, and TailwindCSS, Briefkasten provides a powerful yet simple interface for managing your personal bookmark vault. Whether you’re a researcher, content curator, student, or professional, Briefkasten offers the flexibility to organize bookmarks with categories and tags, search through your entire collection with fulltext search, save bookmarks via a browser extension or drag-and-drop, and maintain complete control over your bookmark data with self-hosting.

Why Briefkasten?

Briefkasten stands out as the premier choice for self-hosted bookmark management with exceptional features:

  • Browser Extension: Save bookmarks directly from your browser with one click
  • Automatic Metadata: Automatic title and description extraction from saved pages
  • Drag-and-Drop Saving: Drag URLs directly onto the page to save bookmarks
  • Keyboard Shortcuts: Quick access with customizable keyboard shortcuts
  • Category Organization: Organize bookmarks into categories for easy navigation
  • Tag System: Flexible tagging system for fine-grained organization
  • Fulltext Search: Lightning-fast search across all your bookmarks
  • Import/Export: Import bookmarks from standard HTML format and export whenever needed
  • Multiple Views: Different view options for browsing your bookmarks
  • REST API: Complete API for integrations and automation
  • OAuth Authentication: Support for multiple OAuth providers
  • Email Magic Links: Simple email-based authentication without passwords
  • Image Fetching: Background job support for bookmark thumbnail generation
  • Responsive Design: Works seamlessly on desktop, tablet, and mobile
  • Database Flexibility: Works with MySQL, Postgres, SQLite, or any Prisma-compatible database
  • Fast and Lightweight: Optimized performance with minimal resource usage
  • Open Source: MIT licensed with active community
  • Self-Hosted Control: Complete data ownership and privacy
  • No Ads or Tracking: Your bookmarks stay private on your infrastructure
  • Screenshot Integration: Optional background job for capturing bookmark screenshots

Briefkasten is ideal for researchers organizing sources and references, content curators saving and sharing articles, knowledge workers managing research materials, students collecting educational resources, developers bookmarking documentation and code examples, and anyone wanting complete control over their bookmark data. With persistent storage on Klutch.sh, your bookmark vault is always available and secure.

Prerequisites

Before deploying Briefkasten, ensure you have:

  • A Klutch.sh account
  • A GitHub repository with your Briefkasten deployment configuration
  • Basic familiarity with Docker and Git
  • A database supporting Prisma (PostgreSQL, MySQL, or SQLite)
  • OAuth provider credentials (optional, for OAuth login)
  • Sufficient storage for bookmarks and images (typically 5-20GB)
  • Custom domain for your bookmark application (recommended)
  • Environment variables configured before deployment

Important Considerations

Deploying Briefkasten

  1. Create a New Project

    Log in to your Klutch.sh dashboard and create a new project for your Briefkasten bookmark vault.

  2. Prepare Your Repository

    Create a GitHub repository with the following structure for your Briefkasten deployment:

    briefkasten-deploy/
    ├─ Dockerfile
    ├─ .env.example
    ├─ entrypoint.sh
    ├─ .gitignore
    └─ README.md

    Here’s a Dockerfile for Briefkasten:

    FROM node:18-alpine
    WORKDIR /app
    # Install system dependencies
    RUN apk add --no-cache \
    curl \
    git \
    build-base \
    python3
    # Clone Briefkasten repository
    RUN git clone https://github.com/ndom91/briefkasten.git /tmp/briefkasten && \
    cp -r /tmp/briefkasten/* .
    # Install pnpm
    RUN npm install -g pnpm
    # Install dependencies
    RUN pnpm install --frozen-lockfile
    # Create necessary directories
    RUN mkdir -p /app/data \
    /app/logs \
    && chmod -R 755 /app
    # Copy entrypoint script
    COPY entrypoint.sh /
    RUN chmod +x /entrypoint.sh
    # Expose port
    EXPOSE 3000
    # Health check
    HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:3000/ || exit 1
    # Run entrypoint
    ENTRYPOINT ["/entrypoint.sh"]
    CMD ["pnpm", "start"]

    Create an entrypoint.sh file:

    #!/bin/bash
    set -e
    # Create necessary directories
    mkdir -p /app/data \
    /app/logs
    # Set proper permissions
    chmod -R 755 /app
    echo "Initializing Briefkasten..."
    # Wait for database to be ready
    echo "Checking database connection..."
    MAX_RETRIES=30
    RETRY_COUNT=0
    until node -e "
    const db = require('./prisma/client.js');
    db.\$connect().then(() => process.exit(0)).catch(() => process.exit(1));
    " 2>/dev/null; do
    RETRY_COUNT=$((RETRY_COUNT + 1))
    if [ $RETRY_COUNT -gt $MAX_RETRIES ]; then
    echo "Database not available after $MAX_RETRIES retries"
    exit 1
    fi
    echo "Waiting for database... (attempt $RETRY_COUNT/$MAX_RETRIES)"
    sleep 2
    done
    echo "Database is available!"
    # Run database migrations
    echo "Running database migrations..."
    pnpm db:push || true
    # Build Next.js application
    echo "Building Briefkasten..."
    pnpm build || true
    echo "Briefkasten is starting..."
    exec "$@"

    Create a .env.example file:

    Terminal window
    # Briefkasten Configuration
    APP_NAME=Briefkasten
    APP_DESCRIPTION=Self-hosted bookmarking application
    # Database Configuration
    DATABASE_URL=postgresql://briefkasten:secure_password@postgres.internal:5432/briefkasten
    SHADOW_DATABASE_URL=postgresql://briefkasten:secure_password@postgres.internal:5433/briefkasten_shadow
    # NextAuth Configuration
    NEXTAUTH_URL=https://bookmarks.yourdomain.com
    NEXTAUTH_SECRET=your-secret-key-32-characters-long
    # Authentication Providers (optional)
    GOOGLE_ID=your-google-oauth-id
    GOOGLE_SECRET=your-google-oauth-secret
    GITHUB_ID=your-github-oauth-id
    GITHUB_SECRET=your-github-oauth-secret
    # Image Storage Configuration (optional)
    # For Supabase
    SUPABASE_ANON_KEY=your-supabase-anon-key
    SUPABASE_BUCKET_URL=https://your-project.supabase.co/storage/v1/object/public/briefkasten
    # Application Settings
    NEXT_PUBLIC_APP_URL=https://bookmarks.yourdomain.com
    # Server Configuration
    NODE_ENV=production

    Create a .gitignore file:

    .env
    .env.local
    node_modules/
    .next/
    build/
    dist/
    out/
    *.log
    logs/
    data/
    .DS_Store
    .vercel/
    .idea/
    *.swp
    *.swo

    Commit and push to your GitHub repository:

    Terminal window
    git init
    git add .
    git commit -m "Initial Briefkasten bookmarking deployment"
    git remote add origin https://github.com/yourusername/briefkasten-deploy.git
    git push -u origin main
  3. Create a New App

    In the Klutch.sh dashboard:

    • Click “Create New App”
    • Select your GitHub repository containing the Dockerfile
    • Choose the branch (typically main or master)
    • Klutch.sh will automatically detect the Dockerfile in the root directory
  4. Configure Environment Variables

    Set up these essential environment variables in your Klutch.sh dashboard:

    VariableDescriptionExample
    DATABASE_URLPostgreSQL connectionpostgresql://user:password@host:5432/briefkasten
    NEXTAUTH_URLApplication URLhttps://bookmarks.yourdomain.com
    NEXTAUTH_SECRETSession encryption keyyour-secret-key
    NODE_ENVEnvironmentproduction
    NEXT_PUBLIC_APP_URLPublic app URLhttps://bookmarks.yourdomain.com

    For OAuth authentication, add provider credentials:

    VariableDescription
    GOOGLE_IDGoogle OAuth app ID
    GOOGLE_SECRETGoogle OAuth secret
    GITHUB_IDGitHub OAuth app ID
    GITHUB_SECRETGitHub OAuth secret

    For image storage with Supabase:

    VariableDescription
    SUPABASE_ANON_KEYSupabase anonymous key
    SUPABASE_BUCKET_URLSupabase storage bucket URL
  5. Configure Persistent Storage

    Briefkasten requires persistent storage for bookmark data. Add a persistent volume:

    Mount PathDescriptionRecommended Size
    /app/dataBookmark data and cache20GB

    In the Klutch.sh dashboard:

    • Navigate to your app settings
    • Go to the “Volumes” section
    • Click “Add Volume”
    • Set mount path: /app/data
    • Set size: 20GB (or appropriate for your needs)
    • Ensure volume has adequate space for your bookmark collection
  6. Set Network Configuration

    Configure your app’s network settings:

    • Select traffic type: HTTP
    • Recommended internal port: 3000 (Next.js default)
    • Klutch.sh will handle HTTPS termination via reverse proxy
    • Application will be accessible via your custom domain
  7. Configure Custom Domain

    Briefkasten benefits from a custom domain:

    • Navigate to your app’s “Domains” section in Klutch.sh
    • Add custom domain (e.g., bookmarks.yourdomain.com)
    • Configure DNS with CNAME record pointing to your Klutch.sh app
    • Update NEXTAUTH_URL and NEXT_PUBLIC_APP_URL environment variables
    • Klutch.sh will automatically provision SSL certificate
    • Wait for DNS propagation (typically 5-15 minutes)
  8. Deploy Your App

    • Review all settings and environment variables carefully
    • Verify database connection string is correct
    • Ensure OAuth provider credentials are configured (if using OAuth)
    • Verify custom domain is configured
    • Click “Deploy”
    • Klutch.sh will build the Docker image and start your Briefkasten instance
    • Wait for deployment to complete (typically 10-20 minutes)
    • Access your Briefkasten at your configured domain
    • Log in with OAuth provider or email magic link

Initial Setup and Configuration

After deployment completes, access your Briefkasten instance to configure your bookmarking system.

Accessing Briefkasten

Navigate to your domain: https://bookmarks.yourdomain.com

Choosing Authentication Method

OAuth Authentication

  1. Click “Sign in with [Provider]” (Google, GitHub, etc.)
  2. Complete provider authorization
  3. Briefkasten creates account automatically
  4. Access to bookmark vault granted
  1. Click “Sign in with Email”
  2. Enter your email address
  3. Check email for magic link
  4. Click link to sign in
  5. No password required

Dashboard Overview

Explore the main interface:

  1. Dashboard: Your bookmarks at a glance
  2. Browse: All bookmarks with filters and search
  3. Categories: Organize bookmarks by category
  4. Tags: Filter bookmarks by tags
  5. Collections: Group related bookmarks together
  6. Settings: Configure your account

Creating Categories

Organize bookmarks by topic:

  1. Go to “Settings” → “Categories”
  2. Click “Add Category”
  3. Enter category name and description
  4. Optionally set category color
  5. Click “Create”
  6. Assign bookmarks to category when saving

Adding Bookmarks

Save bookmarks in multiple ways:

Using Browser Extension

  1. Install Briefkasten browser extension
  2. Click extension icon on any webpage
  3. Edit title and description (pre-filled)
  4. Select category and tags
  5. Click “Save Bookmark”
  6. Bookmark instantly added to vault

Using Drag and Drop

  1. On Briefkasten dashboard, open a new tab
  2. Keep Briefkasten window visible
  3. Drag URL from address bar onto Briefkasten
  4. Bookmark created with auto-extracted title

Using REST API

Terminal window
curl -X POST https://bookmarks.yourdomain.com/api/bookmarks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"url": "https://example.com/article",
"title": "Example Article",
"description": "A great article about...",
"tags": ["article", "important"],
"category": "Reading List"
}'

Manual Addition

  1. Click “Add Bookmark” in dashboard
  2. Paste URL
  3. Edit auto-extracted title and description
  4. Select category
  5. Add tags
  6. Click “Save”

Managing Tags

Organize bookmarks with flexible tagging:

  1. In bookmark details, click “Add Tag”
  2. Type tag name
  3. Select from existing tags or create new
  4. Add multiple tags per bookmark
  5. Filter bookmarks by tag in browse view
  6. View tag cloud for popular tags

Searching Bookmarks

Find bookmarks quickly:

  1. Use search box at top
  2. Search by title, description, or URL
  3. Fulltext search across all content
  4. Filter by category
  5. Filter by tags
  6. Combine filters for precise results
  7. Save searches as collections (optional)

Creating Collections

Group related bookmarks:

  1. Go to “Collections”
  2. Click “Create Collection”
  3. Name your collection
  4. Add description
  5. Add bookmarks from browse view
  6. Or drag bookmarks to collection
  7. Share collection if desired (optional)

Import Bookmarks

Import from other services:

  1. Go to “Settings” → “Import”
  2. Export bookmarks from another service as HTML
  3. Select HTML file
  4. Choose how to organize imported bookmarks
  5. Map categories if needed
  6. Click “Import”
  7. Wait for import to complete
  8. Verify imported bookmarks

Export Bookmarks

Back up or migrate your bookmarks:

  1. Go to “Settings” → “Export”
  2. Choose export format:
    • HTML (standard bookmark format)
    • JSON (complete data export)
    • CSV (spreadsheet format)
  3. Select bookmarks to export or export all
  4. Click “Export”
  5. Download exported file
  6. Keep backup in secure location

Viewing Bookmark Details

Access full bookmark information:

  1. Click bookmark in list
  2. View full title and description
  3. See assigned category and tags
  4. View bookmark image (if available)
  5. Click URL to visit original page
  6. Edit bookmark details
  7. Delete bookmark if needed

Managing Multiple Views

Browse bookmarks different ways:

  1. Grid View: Visual cards with images
  2. List View: Compact list format
  3. Table View: Detailed columns
  4. Calendar View: Bookmarks by date
  5. Switch between views for different tasks
  6. Customize columns in table view
  7. Save view preferences

Environment Variable Examples

Basic Configuration

Terminal window
DATABASE_URL=postgresql://briefkasten:password@postgres.internal:5432/briefkasten
NEXTAUTH_URL=https://bookmarks.yourdomain.com
NEXTAUTH_SECRET=your-secret-key-32-characters
NODE_ENV=production
NEXT_PUBLIC_APP_URL=https://bookmarks.yourdomain.com

Complete Production Configuration

Terminal window
# Application Settings
APP_NAME=Briefkasten
APP_DESCRIPTION=Self-hosted bookmarking application
NODE_ENV=production
# Database Configuration
DATABASE_URL=postgresql://briefkasten:very_secure_password@postgres.internal:5432/briefkasten
SHADOW_DATABASE_URL=postgresql://briefkasten:very_secure_password@postgres.internal:5433/briefkasten_shadow
# Authentication
NEXTAUTH_URL=https://bookmarks.yourdomain.com
NEXTAUTH_SECRET=your-secret-key-32-characters-long
# Application URLs
NEXT_PUBLIC_APP_URL=https://bookmarks.yourdomain.com
NEXTAUTH_URL_INTERNAL=http://localhost:3000
# OAuth Providers - Google
GOOGLE_ID=your-google-oauth-client-id.apps.googleusercontent.com
GOOGLE_SECRET=your-google-oauth-secret
# OAuth Providers - GitHub
GITHUB_ID=your-github-oauth-app-id
GITHUB_SECRET=your-github-oauth-app-secret
# OAuth Providers - Discord (optional)
DISCORD_ID=your-discord-app-id
DISCORD_SECRET=your-discord-app-secret
# Image Storage - Supabase (optional)
SUPABASE_ANON_KEY=your-supabase-anonymous-key
SUPABASE_BUCKET_URL=https://your-project.supabase.co/storage/v1/object/public/briefkasten
# Image Storage - Cloudinary (optional)
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
# SMTP Configuration for Email (optional)
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
# Analytics (optional)
SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
SENTRY_ENVIRONMENT=production
# Performance and Logging
LOG_LEVEL=info
DEBUG=false

Sample Code and Getting Started

TypeScript - Bookmark Management Integration

// Briefkasten Bookmark Management
import axios, { AxiosInstance } from 'axios';
interface Bookmark {
id: string;
url: string;
title: string;
description?: string;
tags?: string[];
category?: string;
image?: string;
createdAt: Date;
updatedAt: Date;
}
interface CreateBookmarkRequest {
url: string;
title: string;
description?: string;
tags?: string[];
category?: string;
}
interface BookmarkFilters {
search?: string;
category?: string;
tags?: string[];
limit?: number;
offset?: number;
}
class BriefkastenClient {
private client: AxiosInstance;
private apiUrl: string;
private apiToken: string;
constructor(apiUrl: string, apiToken: string) {
this.apiUrl = apiUrl;
this.apiToken = apiToken;
this.client = axios.create({
baseURL: apiUrl,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiToken}`
}
});
}
async createBookmark(data: CreateBookmarkRequest): Promise<Bookmark> {
try {
const response = await this.client.post('/api/bookmarks', data);
return response.data;
} catch (error) {
console.error('Error creating bookmark:', error);
throw error;
}
}
async getBookmarks(filters?: BookmarkFilters): Promise<Bookmark[]> {
try {
const params = {
...(filters?.search && { search: filters.search }),
...(filters?.category && { category: filters.category }),
...(filters?.tags && { tags: filters.tags.join(',') }),
limit: filters?.limit || 50,
offset: filters?.offset || 0
};
const response = await this.client.get('/api/bookmarks', { params });
return response.data.bookmarks;
} catch (error) {
console.error('Error fetching bookmarks:', error);
throw error;
}
}
async getBookmark(id: string): Promise<Bookmark> {
try {
const response = await this.client.get(`/api/bookmarks/${id}`);
return response.data;
} catch (error) {
console.error('Error fetching bookmark:', error);
throw error;
}
}
async updateBookmark(id: string, data: Partial<Bookmark>): Promise<Bookmark> {
try {
const response = await this.client.put(`/api/bookmarks/${id}`, data);
return response.data;
} catch (error) {
console.error('Error updating bookmark:', error);
throw error;
}
}
async deleteBookmark(id: string): Promise<void> {
try {
await this.client.delete(`/api/bookmarks/${id}`);
} catch (error) {
console.error('Error deleting bookmark:', error);
throw error;
}
}
async searchBookmarks(query: string): Promise<Bookmark[]> {
try {
const response = await this.client.get('/api/bookmarks/search', {
params: { q: query }
});
return response.data.results;
} catch (error) {
console.error('Error searching bookmarks:', error);
throw error;
}
}
async getCategories(): Promise<string[]> {
try {
const response = await this.client.get('/api/categories');
return response.data.categories;
} catch (error) {
console.error('Error fetching categories:', error);
throw error;
}
}
async getTags(): Promise<string[]> {
try {
const response = await this.client.get('/api/tags');
return response.data.tags;
} catch (error) {
console.error('Error fetching tags:', error);
throw error;
}
}
async addCategory(name: string, description?: string): Promise<string> {
try {
const response = await this.client.post('/api/categories', {
name,
...(description && { description })
});
return response.data.id;
} catch (error) {
console.error('Error adding category:', error);
throw error;
}
}
async exportBookmarks(format: 'html' | 'json' | 'csv'): Promise<Blob> {
try {
const response = await this.client.get('/api/bookmarks/export', {
params: { format },
responseType: 'blob'
});
return response.data;
} catch (error) {
console.error('Error exporting bookmarks:', error);
throw error;
}
}
async importBookmarks(file: File): Promise<{ imported: number }> {
try {
const formData = new FormData();
formData.append('file', file);
const response = await this.client.post('/api/bookmarks/import', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
return response.data;
} catch (error) {
console.error('Error importing bookmarks:', error);
throw error;
}
}
}
// Usage example
const client = new BriefkastenClient(
'https://bookmarks.yourdomain.com',
'your-api-token'
);
// Create a bookmark
const newBookmark = await client.createBookmark({
url: 'https://example.com/article',
title: 'Great Article',
description: 'An informative article',
tags: ['article', 'read'],
category: 'Learning'
});
// Search bookmarks
const results = await client.searchBookmarks('javascript');
// Get bookmarks with filters
const filtered = await client.getBookmarks({
category: 'Learning',
tags: ['javascript'],
limit: 20
});
// Export bookmarks
const htmlExport = await client.exportBookmarks('html');

Bash - Bookmark Backup and Management Script

#!/bin/bash
# Briefkasten Backup and Maintenance Script
BACKUP_DIR="/backups/briefkasten"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
# Configuration
BRIEFKASTEN_URL="https://bookmarks.yourdomain.com"
API_TOKEN="your-api-token"
# Create backup directory
mkdir -p $BACKUP_DIR
echo "Starting Briefkasten backup..."
# Export bookmarks as JSON
echo "Exporting bookmarks..."
curl -s -X GET "$BRIEFKASTEN_URL/api/bookmarks/export?format=json" \
-H "Authorization: Bearer $API_TOKEN" \
-o "$BACKUP_DIR/bookmarks_json_$TIMESTAMP.json"
# Export bookmarks as HTML
echo "Exporting bookmarks as HTML..."
curl -s -X GET "$BRIEFKASTEN_URL/api/bookmarks/export?format=html" \
-H "Authorization: Bearer $API_TOKEN" \
-o "$BACKUP_DIR/bookmarks_html_$TIMESTAMP.html"
# Export bookmarks as CSV
echo "Exporting bookmarks as CSV..."
curl -s -X GET "$BRIEFKASTEN_URL/api/bookmarks/export?format=csv" \
-H "Authorization: Bearer $API_TOKEN" \
-o "$BACKUP_DIR/bookmarks_csv_$TIMESTAMP.csv"
# Backup persistent data
echo "Backing up persistent data..."
tar -czf "$BACKUP_DIR/briefkasten_data_$TIMESTAMP.tar.gz" \
/app/data 2>/dev/null || true
# Backup logs
echo "Backing up logs..."
tar -czf "$BACKUP_DIR/briefkasten_logs_$TIMESTAMP.tar.gz" \
/app/logs 2>/dev/null || true
# Cleanup old backups
echo "Cleaning up old backups..."
find $BACKUP_DIR -type f -mtime +$RETENTION_DAYS -delete
# Verify backups
echo "Verifying backups..."
for file in $BACKUP_DIR/*_$TIMESTAMP.*; do
if [ -f "$file" ]; then
size=$(du -h "$file" | awk '{print $1}')
echo "✓ Created: $(basename $file) ($size)"
fi
done
# Calculate total backup size
TOTAL_SIZE=$(du -sh $BACKUP_DIR | awk '{print $1}')
echo ""
echo "Backup completed at: $TIMESTAMP"
echo "Total backup size: $TOTAL_SIZE"
echo "Backup location: $BACKUP_DIR"
# Optional: Upload to cloud storage
# aws s3 sync $BACKUP_DIR s3://your-bucket/briefkasten-backups/ \
# --exclude "*" --include "bookmarks_*_$TIMESTAMP.*" \
# --delete
# Optional: Send backup notification
# curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
# -d "{\"text\":\"Briefkasten backup completed: $(du -sh $BACKUP_DIR | awk '{print $1}')\"}"

cURL - API Integration Examples

Terminal window
# Briefkasten API Examples
# Get all bookmarks
curl -X GET https://bookmarks.yourdomain.com/api/bookmarks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Get bookmarks with search
curl -X GET "https://bookmarks.yourdomain.com/api/bookmarks?search=javascript&limit=20" \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Get bookmarks by category
curl -X GET "https://bookmarks.yourdomain.com/api/bookmarks?category=Learning" \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Get bookmarks by tag
curl -X GET "https://bookmarks.yourdomain.com/api/bookmarks?tags=important,read" \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Create a bookmark
curl -X POST https://bookmarks.yourdomain.com/api/bookmarks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"url": "https://example.com/article",
"title": "Example Article",
"description": "A useful article about web development",
"tags": ["article", "webdev"],
"category": "Learning"
}'
# Get specific bookmark
curl -X GET https://bookmarks.yourdomain.com/api/bookmarks/bookmark-id \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Update bookmark
curl -X PUT https://bookmarks.yourdomain.com/api/bookmarks/bookmark-id \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"title": "Updated Title",
"description": "Updated description",
"tags": ["updated", "important"]
}'
# Delete bookmark
curl -X DELETE https://bookmarks.yourdomain.com/api/bookmarks/bookmark-id \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Search bookmarks
curl -X GET "https://bookmarks.yourdomain.com/api/bookmarks/search?q=react" \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Get all categories
curl -X GET https://bookmarks.yourdomain.com/api/categories \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Get all tags
curl -X GET https://bookmarks.yourdomain.com/api/tags \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Export bookmarks as JSON
curl -X GET "https://bookmarks.yourdomain.com/api/bookmarks/export?format=json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-o bookmarks.json
# Export bookmarks as HTML
curl -X GET "https://bookmarks.yourdomain.com/api/bookmarks/export?format=html" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-o bookmarks.html

Bookmark Management Best Practices

Organization Strategy

Develop an effective bookmarking system:

  1. Create Logical Categories: Use broad categories for main topics
  2. Use Consistent Tags: Establish tag naming conventions
  3. Regular Cleanup: Remove outdated bookmarks periodically
  4. Description Notes: Add context when saving technical resources
  5. Collection Groups: Use collections for project-related bookmarks
  6. Archive Old Bookmarks: Move old bookmarks to archive collection
  7. Consistent Naming: Use clear, descriptive bookmark titles

Workflow Tips

Optimize your bookmark workflow:

  1. Keyboard Shortcuts: Learn keyboard shortcuts for quick saving
  2. Browser Extension: Always use extension for fastest saving
  3. Batch Operations: Update multiple bookmarks at once when needed
  4. Regular Exports: Export bookmarks monthly as backup
  5. Share Collections: Share relevant collections with team members
  6. Review Bookmarks: Regularly review and organize new bookmarks
  7. Use Search: Leverage fulltext search for discovering old bookmarks

Privacy and Security

Maintain bookmark vault security:

  1. Strong Passwords: Use strong passwords for admin account
  2. OAuth Security: Use trusted OAuth providers
  3. Regular Backups: Export bookmarks regularly
  4. Database Encryption: Enable encryption at database level
  5. HTTPS Only: Always use HTTPS for accessing Briefkasten
  6. Access Control: Limit who can access your bookmark vault
  7. Audit Logs: Review access logs regularly

Troubleshooting

Common Issues and Solutions

Issue: Cannot access Briefkasten application

Solutions:

  • Verify Klutch.sh app is running
  • Check domain DNS resolution
  • Verify SSL certificate validity
  • Check network connectivity
  • Review Klutch.sh dashboard for errors

Issue: Database connection failed

Troubleshooting:

  • Verify database credentials are correct
  • Ensure database is accessible
  • Check DATABASE_URL environment variable
  • Verify database exists
  • Check firewall rules

Issue: OAuth login not working

Solutions:

  • Verify OAuth provider credentials
  • Check NEXTAUTH_URL matches domain
  • Verify redirect URI in OAuth provider settings
  • Check NEXTAUTH_SECRET is set
  • Review NextAuth logs

Issue: Bookmarks not saving

Troubleshooting:

  • Verify database connection
  • Check disk space on persistent volume
  • Review application logs
  • Try clearing browser cache
  • Test with manual bookmark addition

Issue: Slow performance or high memory usage

Solutions:

  • Increase persistent volume size
  • Check for database query performance
  • Optimize bookmark count
  • Review browser extension usage
  • Monitor server resources

Updating Briefkasten

To update Briefkasten to a newer version:

  1. Backup your database and bookmarks
  2. Update Dockerfile to latest version
  3. Commit and push to GitHub
  4. Klutch.sh will automatically rebuild
  5. Test bookmark access after update
  6. Verify all bookmarks still accessible
  7. Monitor logs for any issues

Use Cases

Personal Knowledge Management

  • Organize research and articles
  • Save documentation links
  • Maintain learning resources
  • Archive useful references

Team Collaboration

  • Share bookmark collections
  • Organize team resources
  • Collaborate on research
  • Maintain shared knowledge base

Content Curation

  • Save articles to review
  • Organize by topic or project
  • Export collections for reports
  • Share curated content

Project Management

  • Link to relevant documentation
  • Organize project resources
  • Track useful references
  • Maintain project history

Browser Extension Guide

Installing the Extension

  1. Visit Chrome Extension Store
  2. Click “Add to Chrome”
  3. Confirm permissions
  4. Extension icon appears in toolbar
  5. Configure extension settings
  6. Enter Briefkasten URL
  7. Test with a bookmark

Using the Extension

  1. Click extension icon on any webpage
  2. Pre-filled title and description appear
  3. Edit if necessary
  4. Select category from dropdown
  5. Add tags if desired
  6. Click “Save Bookmark”
  7. Confirmation appears
  8. View saved bookmarks in Briefkasten

Extension Settings

  1. Click extension icon
  2. Select “Options”
  3. Configure Briefkasten server URL
  4. Set default category
  5. Enable/disable auto-detect
  6. Configure keyboard shortcuts
  7. Save settings

Additional Resources

Conclusion

Deploying Briefkasten on Klutch.sh provides you with a powerful, self-hosted bookmarking application that helps you save, organize, and discover your web bookmarks with complete data ownership and privacy. With automatic metadata extraction, browser extension integration, powerful search capabilities, flexible organization with categories and tags, and support for multiple authentication methods, Briefkasten enables you to build a comprehensive personal knowledge management system. Klutch.sh’s managed infrastructure ensures your bookmark vault is always available, secure, and performant, allowing you to focus on curating and organizing your bookmarks.

Start managing your bookmarks today by deploying Briefkasten on Klutch.sh and experience the freedom of self-hosted bookmark management.