BookStack

Collaboration Tool

BookStack

Overview

BookStack is a simple, self-hosted, easy-to-use platform for organizing and storing information. It's fully free and open source, MIT licensed software. Based on the concept of books, BookStack provides an intuitive hierarchical structure that makes it easy to create and manage documentation, making it ideal for knowledge sharing within teams and organizations.

Details

BookStack organizes information into four hierarchical levels: Shelves, Books, Chapters, and Pages. It provides both WYSIWYG and Markdown editors with live preview capabilities, and includes built-in diagram creation through diagrams.net integration. With fully searchable content, multi-language support, flexible permission management, and a REST API for programmatic access, BookStack offers comprehensive documentation capabilities. Built using PHP on the Laravel framework with MySQL for data storage, it can run efficiently even on modest hardware.

Key Features

  • Hierarchical Organization: Four-level structure with shelves, books, chapters, and pages
  • Dual Editors: WYSIWYG and Markdown editors with live preview
  • Diagram Creation: Built-in diagrams.net integration
  • Powerful Search: Full-text search at book level or across all content
  • Version Control: Page history and revision tracking
  • Permission Management: Role-based access control (Viewer, Editor, Admin)
  • Authentication Options: Email/password, social logins, SAML2, LDAP support
  • Customization: Customizable logo, name, and themes (light/dark)

API Overview

REST API Basic Structure

GET https://example.com/api/books
Authorization: Token {id}:{secret}
Content-Type: application/json

Key Endpoints

# List all books
GET /api/books

# Create a new page
POST /api/pages
{
    "book_id": 1,
    "name": "New Page",
    "html": "<p>Page content</p>"
}

# Update a page
PUT /api/pages/{id}
{
    "name": "Updated Page",
    "html": "<p>Updated content</p>"
}

Advantages and Disadvantages

Advantages

  • Completely free and open source (MIT license)
  • Simple and intuitive user interface
  • Self-hosted with full data control
  • Lightweight and fast (runs on $5 VPS)
  • Multi-language support (including Japanese, French, German, etc.)
  • Flexible authentication options
  • Extensible through REST API

Disadvantages

  • Requires self-hosting
  • No traditional plugin system
  • No real-time collaboration features
  • No native mobile apps (web is fully responsive)
  • Backup and maintenance are user responsibility
  • Permission management can become complex for large organizations

Practical Examples

1. BookStack Setup with Docker

version: '3'
services:
  bookstack:
    image: linuxserver/bookstack
    container_name: bookstack
    environment:
      - PUID=1000
      - PGID=1000
      - DB_HOST=bookstack_db
      - DB_USER=bookstack
      - DB_PASS=password
      - DB_DATABASE=bookstackapp
      - APP_URL=https://docs.example.com
    volumes:
      - ./bookstack_data:/config
    ports:
      - 6875:80
    restart: unless-stopped
    depends_on:
      - bookstack_db
      
  bookstack_db:
    image: mariadb
    container_name: bookstack_db
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=bookstackapp
      - MYSQL_USER=bookstack
      - MYSQL_PASSWORD=password
    volumes:
      - ./bookstack_db_data:/var/lib/mysql
    restart: unless-stopped

2. API Authentication and Token Generation (PHP)

<?php
// BookStack API Client
class BookStackClient {
    private $baseUrl;
    private $tokenId;
    private $tokenSecret;
    
    public function __construct($baseUrl, $tokenId, $tokenSecret) {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->tokenId = $tokenId;
        $this->tokenSecret = $tokenSecret;
    }
    
    private function getAuthHeader() {
        return 'Token ' . $this->tokenId . ':' . $this->tokenSecret;
    }
    
    public function request($method, $endpoint, $data = null) {
        $ch = curl_init($this->baseUrl . '/api' . $endpoint);
        
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: ' . $this->getAuthHeader(),
            'Content-Type: application/json'
        ]);
        
        if ($data !== null) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
        
        $response = curl_exec($ch);
        curl_close($ch);
        
        return json_decode($response, true);
    }
}

// Usage example
$client = new BookStackClient(
    'https://docs.example.com',
    'your-token-id',
    'your-token-secret'
);

// Get all books
$books = $client->request('GET', '/books');

3. Automated Page Creation (Python)

import requests
import json
from datetime import datetime

class BookStackAPI:
    def __init__(self, base_url, token_id, token_secret):
        self.base_url = base_url.rstrip('/')
        self.headers = {
            'Authorization': f'Token {token_id}:{token_secret}',
            'Content-Type': 'application/json'
        }
    
    def create_page(self, book_id, chapter_id, name, content, tags=None):
        """Create a new page"""
        data = {
            'book_id': book_id,
            'chapter_id': chapter_id,
            'name': name,
            'html': content
        }
        
        if tags:
            data['tags'] = tags
        
        response = requests.post(
            f'{self.base_url}/api/pages',
            headers=self.headers,
            json=data
        )
        return response.json()
    
    def create_documentation_structure(self):
        """Automatically create project documentation structure"""
        # Create book
        book_data = {
            'name': 'Project Documentation',
            'description': 'Technical documentation for the development project'
        }
        book = requests.post(
            f'{self.base_url}/api/books',
            headers=self.headers,
            json=book_data
        ).json()
        
        # Create chapters
        chapters = [
            {'name': 'Architecture', 'description': 'System design'},
            {'name': 'API Specification', 'description': 'API endpoints'},
            {'name': 'Developer Guide', 'description': 'Guide for developers'}
        ]
        
        for chapter_data in chapters:
            chapter_data['book_id'] = book['id']
            requests.post(
                f'{self.base_url}/api/chapters',
                headers=self.headers,
                json=chapter_data
            )
        
        return book

# Usage example
api = BookStackAPI(
    'https://docs.example.com',
    'your-token-id',
    'your-token-secret'
)

# Create documentation structure
book = api.create_documentation_structure()
print(f"Created book: {book['name']} (ID: {book['id']})")

4. Custom Theme Settings (CSS)

/* BookStack Custom Theme - Add via settings */
:root {
    --color-primary: #2c3e50;
    --color-primary-light: #34495e;
    --color-link: #3498db;
    --color-page: #ffffff;
    --color-page-draft: #fff5d9;
}

/* Dark mode support */
.dark-mode {
    --color-page: #1a1a1a;
    --color-text: #e0e0e0;
    --color-page-draft: #3a3a2a;
}

/* Custom logo style */
.logo-image {
    max-height: 50px;
    margin-right: 10px;
}

/* Sidebar customization */
.book-tree .sidebar-page-list {
    border-left: 3px solid var(--color-primary);
    padding-left: 10px;
}

/* Improved code block styling */
pre code {
    background-color: #2d2d2d;
    color: #f8f8f2;
    padding: 15px;
    border-radius: 5px;
    font-family: 'Fira Code', monospace;
}

5. Backup Script (Bash)

#!/bin/bash
# BookStack Automated Backup Script

# Configuration
BACKUP_DIR="/backup/bookstack"
DOCKER_CONTAINER="bookstack"
DB_CONTAINER="bookstack_db"
DATE=$(date +%Y%m%d_%H%M%S)

# Create backup directory
mkdir -p "$BACKUP_DIR/$DATE"

# Backup database
echo "Backing up database..."
docker exec $DB_CONTAINER mysqldump -u bookstack -ppassword bookstackapp > "$BACKUP_DIR/$DATE/database.sql"

# Backup uploaded files
echo "Backing up uploaded files..."
docker cp $DOCKER_CONTAINER:/config/uploads "$BACKUP_DIR/$DATE/uploads"

# Backup configuration
echo "Backing up configuration..."
docker cp $DOCKER_CONTAINER:/config/.env "$BACKUP_DIR/$DATE/.env"

# Compress backup
echo "Compressing backup..."
cd "$BACKUP_DIR"
tar -czf "bookstack_backup_$DATE.tar.gz" "$DATE"
rm -rf "$DATE"

# Remove old backups (older than 30 days)
find "$BACKUP_DIR" -name "bookstack_backup_*.tar.gz" -mtime +30 -delete

echo "Backup complete: bookstack_backup_$DATE.tar.gz"

Reference Links