b5d57f5c8a3af1749aba94e6935c13dd5b8b8a50
- Document password complexity requirements - Document account lockout mechanism (5 attempts, 15 min) - Update JWT expiration to 1 hour - Add refresh token documentation (7-day expiration) - Add token management endpoints - Enhance security features section - Document standardized error responses
📚 Bookmann
A modern self-hosted media library system built with Go, PostgreSQL, HTMX, and Tailwind CSS featuring multiple library support, beautiful dark themes, and comprehensive media management.
✨ Features
🏗 Multi-Library System
- Multiple Media Types: Support for Ebooks, Comics, and Manga with modular architecture
- Per-Library Folders: Each library can have multiple scanning folders for flexible organization
- Library Visibility Control: Admins can control which libraries are visible to each user
- Type-Specific File Extensions:
- Ebooks:
.epub,.pdf,.mobi,.azw,.azw3,.txt,.rtf,.doc,.docx,.lit,.fb2,.pdb - Comics:
.cbz,.cbr,.cb7,.cbt,.pdf - Manga:
.cbz,.cbr,.png,.jpg,.jpeg,.gif,.bmp,.webp
- Ebooks:
- Easy Extension: Designed to add new media types in the future
🔒 Authentication & Security
- Multi-User Support: Complete user registration and authentication system
- JWT-Based Sessions: Secure token-based authentication with 1-hour expiration and refresh token support
- Role-Based Access: Admin and user roles with granular permission control
- Password Security: bcrypt hashing with complex password requirements:
- Minimum 8 characters
- At least one uppercase letter (A-Z)
- At least one lowercase letter (a-z)
- At least one number (0-9)
- At least one special character (!@#$%^&*()_+-=[]{}|;':",./<>?)
- Account Lockout: Automatic account lockout after 5 failed login attempts (15-minute lockout period)
- Rate Limiting: Built-in rate limiting on auth endpoints (10 requests/minute) to prevent brute force attacks
- Refresh Tokens: Secure refresh token mechanism (7-day expiration) for seamless token renewal
- Input Validation: Comprehensive validation including username whitespace checks, email format validation
- Pagination Protection: Maximum pagination limits (1000 items) to prevent DoS attacks
- Path Validation: Library folder paths are validated for existence and accessibility
- Case-Insensitive Roles: Role values automatically normalized to lowercase
- Database Transactions: Multi-step database operations use transaction support for data consistency
- Standardized Error Responses: Consistent error format across all API endpoints
🎨 Beautiful UI
- 11 Dark Themes: Tokyo Night, Dracula, Nord, Solarized Dark, Monokai, One Dark Pro, Material Dark, Catppuccin variants
- Theme Persistence: User theme preferences saved to database
- Mobile-First Design: Fully responsive interface for all devices
- HTMX Integration: Dynamic interactions without page reloads
📱 Media Management
- Universal Media Support: Single system for all media types with unified interface
- Rich Metadata: Automatic extraction of title, author, series, publisher, ISBN, tags
- Advanced Rating: 5-star system with half-star precision (1-10 scale)
- Reading Progress: User-specific progress tracking with current page and total pages
- Notes & Highlights: Personal annotations and text highlighting with color customization
- Highlight Notes: Link highlights to detailed notes for comprehensive annotations
- Library Statistics: Media count and usage statistics per library
🚀 Quick Start
Prerequisites
- Docker and Docker Compose
- PostgreSQL database (handled by Docker)
Environment Setup
- Create .env file:
cp .env.example .env
- Edit .env with your secure values:
JWT_SECRET="your-secure-jwt-secret-key-here"
DBPASS="your-secure-database-password-here"
Running the Application
# Option 1: Using .env file
docker-compose up --build
# Option 2: Direct environment variables
export JWT_SECRET="your-secure-jwt-secret-key-here"
export DBPASS="your-secure-database-password-here"
docker-compose up --build
Access the application at: http://localhost:8765
👤 User Management
Role System
- Admin Users: Can create/manage libraries, add/delete media items, manage users
- Regular Users: Can view permitted libraries, rate items, track reading progress
First Admin Setup
The first user who registers automatically becomes an admin. For additional admins:
-- Connect to database
docker exec -it bookmann_db psql -U postgres -d bookmann
-- Promote user to admin
UPDATE users SET role = 'admin' WHERE email = 'user@example.com';
🏛 Library Management
Creating Libraries
- Admin Access: Only administrators can create libraries
- Library Types: Choose from Ebooks, Comics, or Manga
- Multi-Folder Support: Add multiple scanning folders per library
- Folder Organization: Organize your media collection across multiple paths
Library Visibility Control
- Admin Dashboard: Complete interface for managing library access
- User-Specific Control: Admins can show/hide libraries per user
- Personal Preferences: Admins can also hide libraries from their own view
- Simple Toggles: Checkbox-based interface for easy management
API Endpoints
Notes & Highlights (All Authenticated Users)
# Media Notes
GET /api/media-items/{id}/notes # Get user's notes for media
POST /api/media-items/{id}/notes # Create new note
GET /api/media-items/{id}/notes/{noteId} # Get specific note
PUT /api/media-items/{id}/notes/{noteId} # Update note
DELETE /api/media-items/{id}/notes/{noteId} # Delete note
# Media Highlights
GET /api/media-items/{id}/highlights # Get user's highlights for media
POST /api/media-items/{id}/highlights # Create new highlight
GET /api/media-items/{id}/highlights/{highlightId} # Get specific highlight
PUT /api/media-items/{id}/highlights/{highlightId} # Update highlight
DELETE /api/media-items/{id}/highlights/{highlightId} # Delete highlight
# Ebook Compatibility (Backward Compatible)
GET /api/ebooks/{id}/notes # Get user's notes for ebook
POST /api/ebooks/{id}/notes # Create new ebook note
PUT /api/ebooks/{id}/notes/{noteId} # Update ebook note
DELETE /api/ebooks/{id}/notes/{noteId} # Delete ebook note
GET /api/ebooks/{id}/highlights # Get user's highlights for ebook
POST /api/ebooks/{id}/highlights # Create new ebook highlight
PUT /api/ebooks/{id}/highlights/{highlightId} # Update ebook highlight
DELETE /api/ebooks/{id}/highlights/{highlightId} # Delete ebook highlight
Library Management (Admin Only)
# Create new library
POST /api/libraries
{
"name": "My Comic Collection",
"description": "Digital comics and graphic novels",
"type": "comics"
}
# List all libraries
GET /api/libraries
# Add folder to library
POST /api/libraries/{library_id}/folders
{
"folder_path": "/path/to/comics"
}
# Set library visibility for user
POST /api/libraries/visibility
{
"library_id": "library-uuid",
"is_visible": true
}
User Access
# Get user's visible libraries
GET /api/libraries/visible
# Browse media in library
GET /api/media-items?library_id={library_id}&limit=20&offset=0
# Media Progress & Ratings
GET /api/media-items/{id}/progress # Get reading progress
PUT /api/media-items/{id}/progress # Update reading progress
GET /api/media-items/{id}/rating # Get user rating
POST /api/media-items/{id}/rating # Create/update rating
PUT /api/media-items/{id}/rating # Update rating
DELETE /api/media-items/{id}/rating # Delete rating
# Token Management
POST /api/auth/refresh # Refresh access token
POST /api/auth/logout # Logout (revokes refresh token)
📖 Media Support
Ebooks
- Formats: EPUB (full metadata), PDF, MOBI, AZW, TXT, DOC, FB2
- Metadata: Automatic extraction from EPUB files with Calibre support
- Reading: Built-in web reader for EPUB files
Comics
- Formats: CBZ, CBR, CB7, CBT, PDF
- Structure: Archive-based organization with chapter support
- Viewing: Image extraction and web-based comic reader
Manga
- Formats: CBZ, CBR (archives), PNG, JPG (image folders)
- Structure: Archive support with folder-based image organization
- Viewing: Chapter-by-chapter viewing with page navigation
🎨 Development
Local Development
# Backend development
go mod tidy
go run cmd/server/main.go
# Frontend development
npm run dev
# Templates automatically recompile on changes
Environment
- Backend: Go 1.25+ with pgx v5 for database operations
- Frontend: Tailwind CSS with HTMX for dynamic interactions
- Database: PostgreSQL 15+ with pgx v5 driver
- Authentication: JWT tokens with bcrypt password hashing
🐳 Deployment
Docker Configuration
# docker-compose.yml
services:
bookmann:
build: .
ports:
- "8765:8765"
environment:
- JWT_SECRET=${JWT_SECRET}
- DBHOST=db
depends_on:
- db
Database Schema
- Multi-Library Architecture: Libraries, library types, folders, visibility tables
- Annotations System: Notes, highlights with position tracking and color customization
- Backward Compatibility: Views maintain existing API contracts for ebooks
- Type Safety: pgx v5 with proper error handling
- Migration Ready: Schema designed for easy future extensions
🧪 API Documentation
Bruno Testing Collection
Complete API testing collection in bruno/ directory:
bruno/
├── user/ # Authentication & profile endpoints
├── admin/ # Admin-only operations
├── library/ # Library management
├── media-items/ # Media content browsing
├── notes/ # Notes API testing
├── highlights/ # Highlights API testing
└── collection.bru # Main dashboard
Authentication Flow
- Register:
POST /api/auth/register→ JWT token - Login:
POST /api/auth/login→ JWT token - Protected Routes: Use
Authorization: Bearer {token}header
Error Handling
All API endpoints return standardized error responses:
{
"error": "Error message",
"message": "Detailed error information (if available)",
"code": "Error code (if applicable)"
}
HTTP Status Codes:
- 400: Bad request (validation errors)
- 401: Unauthorized (invalid/missing token)
- 403: Forbidden (insufficient permissions)
- 404: Resource not found
- 429: Too many requests (rate limit exceeded)
- 500: Internal server error
🛡 Security Features
Authentication & Authorization
- JWT Tokens:
- Short-lived access tokens (1-hour expiration)
- Refresh tokens (7-day expiration) for seamless session renewal
- Secure token storage and transmission
- Password Security:
- bcrypt hashing with cost factor 12
- Complex password requirements enforced
- Password validation on registration and updates
- Account Protection:
- Automatic lockout after 5 failed login attempts
- 15-minute lockout period with countdown
- IP-based and username-based attempt tracking
- Rate Limiting: 10 requests per minute on authentication endpoints
- Input Validation: Comprehensive server-side validation for all inputs
- CSRF Protection: Built-in with HTMX
- Role-Based Access Control: Admin and user roles enforced on all endpoints
Authorization
- Role-Based Access: Admin vs user permissions
- Library Visibility: Per-user library access control
- Admin Middleware: Protected routes for admin operations
- Content Security: XSS protection and secure headers
Database Security
- Parameterized Queries: SQL injection prevention with pgx v5
- Connection Pooling: Efficient database connection management
- Transaction Support: Multi-step operations wrapped in transactions
- Environment Variables: Secure secret management
- Row-Level Security: User data isolation
- Secure Refresh Token Storage: Encrypted token storage in database
- Automatic Token Cleanup: Expired tokens cleaned up periodically
🔧 Configuration
Environment Variables
# Required
JWT_SECRET= # JWT signing secret (64-byte random string)
DBHOST=db # PostgreSQL database host
# Optional
SERVER_PORT=8765 # Application port
NODE_ENV=development # Environment mode
Database Configuration
-- Library types are automatically seeded
INSERT INTO library_types (name, description, allowed_extensions) VALUES
('ebooks', 'Ebook files including EPUB, PDF, MOBI, etc.',
ARRAY['.epub', '.pdf', '.mobi', '.azw', '.azw3', '.txt', '.rtf', '.doc', '.docx', '.lit', '.fb2', '.pdb']),
('comics', 'Comic book archives and image formats',
ARRAY['.cbz', '.cbr', '.cb7', '.cbt', '.pdf']),
('manga', 'Manga files including archives and image folders',
ARRAY['.cbz', '.cbr', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp']);
🧪 Testing
API Testing
# Install Bruno
npm install -g @usebruno/cli
# Run tests
bruno run
Unit Tests
go test ./...
📊 Architecture
Backend
cmd/server/main.go # Application entry point
├── internal/
│ ├── config/ # Configuration management
│ ├── database/ # Database operations (SQLC generated)
│ │ ├── queries/ # SQL queries
│ │ └── models.go # Generated models
│ ├── handlers/ # HTTP handlers
│ │ ├── auth.go # Authentication & users
│ │ ├── library.go # Library management
│ │ └── ebook.go # Media operations
│ └── services/ # Business logic
│ └── library_service.go # Library service
templates/ # HTML templates with HTMX
Database
libraries # Library definitions
library_types # Media type definitions (ebooks, comics, manga)
library_folders # Folders per library
library_visibility # User library access control
media_items # All media content (replaces ebooks table)
media_ratings # User ratings for media items
media_notes # User notes on media items
media_highlights # User highlights with optional note links
reading_progress # User reading progress
users # User accounts and profiles
# Backward Compatibility Views
ebook_notes # Notes view for ebook API compatibility
ebook_highlights # Highlights view for ebook API compatibility
🎯 Future Roadmap
Media Type Extensions
- Audiobooks: Audio file support with chapter tracking
- Podcasts: RSS feed integration and automatic downloading
- Video: Movie/TV series management with metadata
- Music: Album and track management with artwork
Advanced Features
- Mobile App: React Native mobile application
- API v2: GraphQL API for efficient data fetching
- Webhooks: External service integrations
- Analytics: Usage statistics and reporting
- Backup/Restore: Library backup and migration tools
📝 Contributing
Development Guidelines
- Follow Go best practices and effective Go
- Use pgx v5 for all database operations
- Implement proper error handling with pgx.ErrNoRows
- Write comprehensive tests for new features
- Update documentation for API changes
Code Style
- Follow existing code formatting
- Use meaningful variable and function names
- Add comments for complex business logic
- Ensure type safety with proper error handling
📄 License
GPL-3.0 - See LICENSE file for details.
Built with ❤️ using Go, PostgreSQL, HTMX, and Tailwind CSS