Skip to content

AichaDigital/bookstack-sync

Repository files navigation

BookStack Sync

Latest Version on Packagist Total Downloads GitHub Tests Action Status GitHub Code Style Action Status PHPStan Level 8 codecov PHP Version Laravel Version License

A Laravel package for synchronizing Markdown documentation with BookStack wiki. Perfect for keeping your project documentation in sync between your codebase and BookStack.

Features

  • Bidirectional Sync: Push local Markdown files to BookStack or pull BookStack content to local files
  • Local SQLite Cache: Reduces API calls by caching wiki structure locally with change detection
  • Bookmark Conversion: Automatically converts AI-generated bookmarks (Claude, Cursor, etc.) to BookStack's URL-encoded format
  • Spanish Character Support: Full support for UTF-8 characters (á, é, í, ó, ú, ñ, ç, ü, etc.)
  • Artisan Commands: Easy-to-use CLI commands for all operations
  • Conflict Resolution: Multiple strategies for handling sync conflicts
  • Dry Run Mode: Preview changes before making them

Requirements

  • PHP 8.2+
  • Laravel 10, 11, or 12
  • BookStack instance with API access

Installation

composer require aichadigital/bookstack-sync --dev

Publish the configuration file:

php artisan vendor:publish --tag="bookstack-sync-config"

Configuration

Add these variables to your .env file:

BOOKSTACK_URL=https://your-bookstack-instance.com/
BOOKSTACK_TOKEN_ID=your-token-id
BOOKSTACK_TOKEN_SECRET=your-token-secret

# Optional defaults
BOOKSTACK_BOOK_ID=123
BOOKSTACK_MARKDOWN_PATH=docs

Alternative variable names are also supported for compatibility:

WIKI_URL=https://your-bookstack-instance.com/
WIKI_TOKEN_ID=your-token-id
WIKI_TOKEN=your-token-secret

Usage

Artisan Commands

Check Connection Status

php artisan bookstack:status
php artisan bookstack:status --books
php artisan bookstack:status --shelves

Push Local Files to BookStack

# Push docs directory to book ID 5
php artisan bookstack:push docs --book=5

# Dry run (preview without changes)
php artisan bookstack:push docs --book=5 --dry-run

# Skip confirmation
php artisan bookstack:push docs --book=5 --force

Pull from BookStack to Local Files

# Pull book ID 5 to local directory
php artisan bookstack:pull --book=5 --path=docs

# Dry run
php artisan bookstack:pull --book=5 --path=docs --dry-run

Export Content

# Export as Markdown
php artisan bookstack:export page 123

# Export book as PDF
php artisan bookstack:export book 5 --format=pdf --output=manual.pdf

# Available formats: markdown, html, pdf, plaintext

Search

php artisan bookstack:search "configuration"
php artisan bookstack:search "instalación" --limit=50

Sync Wiki Structure to Local Cache

# Sync all wiki structure to local SQLite database
php artisan bookstack:sync

# Fresh sync (deletes existing database first)
php artisan bookstack:sync --fresh

# Sync only specific entities
php artisan bookstack:sync --no-shelves --no-chapters

Query Local Cache

# Show database statistics
php artisan bookstack:db stats

# List cached entities
php artisan bookstack:db shelves
php artisan bookstack:db books
php artisan bookstack:db chapters --book=5
php artisan bookstack:db pages --book=5 --chapter=10

# Include deleted items
php artisan bookstack:db pages --deleted

# Show database path and size
php artisan bookstack:db path

# Delete local database
php artisan bookstack:db delete --force

Programmatic Usage

use AichaDigital\BookStackSync\Facades\BookStackSync;

// List all books
$books = BookStackSync::books();

// Get a specific page
$page = BookStackSync::page(123);

// Create a new page with Markdown content
$page = BookStackSync::createPage(
    bookId: 5,
    name: 'Configuración Inicial',
    content: '# Introducción\n\nContenido aquí...',
    chapterId: 10
);

// Search
$results = BookStackSync::search('instalación');

// Sync operations
$result = BookStackSync::pushToBook('/path/to/docs', 5);
$result = BookStackSync::pullFromBook(5, '/path/to/docs');

Bookmark Conversion

The package automatically handles the conversion between AI-generated bookmark formats and BookStack's URL-encoded format:

use AichaDigital\BookStackSync\Facades\BookStackSync;

// Encode for BookStack
$encoded = BookStackSync::encodeBookmark('sección-principal');
// Returns: secci%C3%B3n-principal

// Decode from BookStack
$decoded = BookStackSync::decodeBookmark('secci%C3%B3n-principal');
// Returns: sección-principal

Direct Parser Usage

use AichaDigital\BookStackSync\Parsers\MarkdownParser;

$parser = new MarkdownParser();

// Convert content for BookStack
$content = '# Introducción\n\nSee [sección](#sección) for details.';
$converted = $parser->parseForBookStack($content);
// Anchors are now URL-encoded

// Extract headings
$headings = $parser->extractHeadings($content);

// Generate Table of Contents
$toc = $parser->generateTableOfContents($content);

Markdown Frontmatter

You can use YAML frontmatter in your Markdown files to specify metadata:

---
title: Mi Página
chapter: Introducción
---

# Content here...

Supported frontmatter fields:

  • title / name: Page title (overrides filename)
  • chapter: Chapter name (creates if doesn't exist)
  • bookstack_id: Links to existing BookStack page for updates

Sync Configuration

Configure sync behavior in config/bookstack-sync.php:

'sync' => [
    // Direction: 'push', 'pull', or 'bidirectional'
    'direction' => env('BOOKSTACK_SYNC_DIRECTION', 'push'),

    // Conflict resolution: 'local', 'remote', 'newest', 'manual'
    'conflict_resolution' => env('BOOKSTACK_CONFLICT_RESOLUTION', 'manual'),

    // Auto-create missing structure
    'auto_create_structure' => true,

    // Dry run mode
    'dry_run' => false,
],

Local Database Configuration

The package includes a local SQLite cache to reduce API calls and enable change detection:

'database' => [
    // Enable/disable local database caching
    'enabled' => env('BOOKSTACK_LOCAL_DB', true),

    // Database path (relative to storage/ or absolute path)
    'path' => env('BOOKSTACK_DB_PATH', 'bookstack-sync.sqlite'),
],

Environment Variables

# Enable local SQLite cache (default: true)
BOOKSTACK_LOCAL_DB=true

# Custom database path (default: storage/bookstack-sync.sqlite)
BOOKSTACK_DB_PATH=bookstack-sync.sqlite

How It Works

  1. Run php artisan bookstack:sync to populate the local cache
  2. The cache stores all shelves, books, chapters, and pages with their metadata
  3. During push/pull operations, the package uses content hashes to skip unchanged files
  4. Deleted items in BookStack are marked with is_deleted flag for tracking

Spanish Character Encoding Reference

Character URL Encoded
á %C3%A1
é %C3%A9
í %C3%AD
ó %C3%B3
ú %C3%BA
ñ %C3%B1
ü %C3%BC
ç %C3%A7

Testing

composer test

To run tests against your actual BookStack instance, copy .env.example to .env and configure your credentials:

cp .env.example .env
# Edit .env with your BookStack credentials
composer test

API Reference

This package uses the BookStack REST API. Key endpoints used:

  • /api/shelves - Shelf operations
  • /api/books - Book operations
  • /api/chapters - Chapter operations
  • /api/pages - Page operations
  • /api/search - Search across content

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

Special thanks to:

  • BookStack - The excellent open-source wiki platform that this package integrates with
  • Dan Brown - Creator and maintainer of BookStack

Trademark Notice: BookStack® is a registered trademark of Daniel Brown. This package is not affiliated with, endorsed by, or sponsored by BookStack or Daniel Brown.

License

This package is licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Please see License File for more information.

About

Gateway for clean and easy use correct markdown

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages