Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
88d6eb1
Add .env auto-discovery to migration scripts, install Rust/Java8/Mave…
alvonellos Dec 31, 2025
b4c4115
Sync .env discovery to canonical Rust at bookstack-migration/rust/, r…
alvonellos Dec 31, 2025
dec1fc0
Remove scattered migration scripts from dev/migration and dev/tools -…
alvonellos Dec 31, 2025
a4bcc3a
Restore and enhance Java DokuWikiExporter with .env discovery
alvonellos Dec 31, 2025
74461c5
Add auto-install for Perl modules (DBI, DBD::mysql, JSON, LWP::UserAg…
alvonellos Dec 31, 2025
7e625a2
adxf
alvonellos Dec 31, 2025
1f712f7
Tighten migration tooling and docs
alvonellos Dec 31, 2025
e190ebd
Harden Perl deps install and doc note
alvonellos Dec 31, 2025
b1040ed
Fix Python table detection to export real content
alvonellos Dec 31, 2025
f1228a5
Add 'all tables' dump option and default yes/all confirmation
alvonellos Dec 31, 2025
ebae800
Convert HTML to DokuWiki-ish output and allow full-table dumps
alvonellos Dec 31, 2025
a8b8940
Prefer canonical pages/books/chapters tables and 'all' dump
alvonellos Dec 31, 2025
3b49837
Export pages into book/chapter folders and keep mappings
alvonellos Dec 31, 2025
0b1c962
Ensure pages are written under book/chapter folders
alvonellos Dec 31, 2025
595a1bd
Include bookshelves in path and mapping detection
alvonellos Dec 31, 2025
13dc60c
Add AI coding instructions and restructure migration toolkit
alvonellos Jan 4, 2026
92401c5
Add bookstack-migrate tool
alvonellos Jan 7, 2026
fbc251d
Implement export logic for bookstack-migrate
alvonellos Jan 7, 2026
cc814d6
cur
alvonellos Jan 7, 2026
1fc64da
Merge branch 'BookStackApp:development' into feature/bookstack-migrat…
alvonellos Jan 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# BookStack Development Guide

## Architecture Overview

BookStack is a Laravel 12-based documentation platform with a traditional MVC structure. The codebase uses:
- **Backend**: PHP 8.2+ with Laravel 12, namespace `BookStack\`
- **Frontend**: TypeScript/JavaScript with component-based architecture, SASS for styles
- **Database**: MySQL with Eloquent ORM

### Key Directory Structure

- `app/` - Core application organized by domain (Access, Activity, Entities, Permissions, Users, etc.)
- `Models/` subdirectories contain Eloquent models
- `Repos/` subdirectories contain repository pattern implementations
- `Controllers/` subdirectories contain HTTP and API controllers
- Service classes (e.g., `LoginService`, `LdapService`) handle business logic
- `resources/js/` - TypeScript/JavaScript frontend code using component system
- `resources/sass/` - SASS stylesheets
- `resources/views/` - Blade templates
- `routes/` - `web.php` (authenticated UI routes) and `api.php` (REST API routes)
- `tests/` - PHPUnit tests mirroring `app/` structure

### Core Patterns

**Entities Hierarchy**: The platform uses a hierarchical content structure:
- `Bookshelf` → `Book` → `Chapter` → `Page`
- Models in `app/Entities/Models/` extend `Entity` or specialized base classes (`BookChild`)
- Use `scopeVisible()` on queries to enforce permission filtering

**Repository Pattern**: Business logic lives in repository classes (e.g., `BookRepo`, `PageRepo`) in `*Repos/` directories. These handle CRUD operations, not controllers directly.

**Permission System**: Complex permission handling via:
- `PermissionApplicator` - Apply permission filters to queries
- `userCan($permission, $ownable)` helper function in `app/App/helpers.php`
- Check permissions using `Permission` class constants, not string literals
- Joint permissions table caches permission evaluation for performance

**Activity Tracking**: Use `Activity::add(ActivityType::*, $entity)` facade for audit logging, not direct database calls.

**Frontend Components**:
- Component-based system in `resources/js/components/`
- Register components via HTML attributes: `component="component-name"`
- Reference elements with `refs="component-name@refName"`
- Component options via `option:component-name:option-key="value"`
- Components extend `Component` base class from `component.ts`

## Development Workflows

### Build Commands

```bash
# PHP dependencies
composer install

# JavaScript/CSS development (watch mode)
npm run dev # Watches both JS and CSS
npm run build:js:watch # JS only
npm run build:css:watch # CSS only

# Production builds
npm run production # Minified JS and CSS

# Linting and testing
composer lint # PHP CodeSniffer
composer format # Auto-fix PHP formatting
composer check-static # PHPStan static analysis
composer test # PHPUnit tests
npm run lint # ESLint
npm run test # Jest tests
```

### Testing

- PHPUnit configuration in `phpunit.xml` with extensive test environment variables
- Tests use `DatabaseTransactions` trait for automatic rollback
- Test helpers: `EntityProvider`, `UserRoleProvider`, `PermissionsProvider` available via `$this->entities`, `$this->users`, `$this->permissions`
- Factory-based test data creation via `database/factories/`

### Database Migrations

```bash
php artisan migrate # Run migrations
php artisan migrate:refresh # Reset and re-run
php artisan db:seed --class=DummyContentSeeder # Seed test content
composer refresh-test-database # Refresh test DB with seeding
```

## Conventions

**Naming**:
- Controllers: `*Controller` for web, `*ApiController` for API endpoints
- Services: `*Service` suffix (e.g., `LoginService`, `EmailConfirmationService`)
- Repositories: `*Repo` suffix
- Use explicit imports, avoid aliases except for established facades

**Routing**:
- Web routes require `auth` middleware (see `routes/web.php`)
- API routes follow RESTful conventions (list, create, read, update, delete)
- Controllers are namespaced by domain, imported via `as` aliases at route file top

**Eloquent Relationships**:
- Always define inverse relationships
- Use lazy-loading protection (check `Model::preventLazyLoading()` in `AppServiceProvider`)
- Leverage query scopes for common filters (e.g., `scopeVisible()` for permissions)

**Frontend**:
- Use TypeScript for new code where possible
- Avoid jQuery - use vanilla DOM APIs or existing framework utilities
- Translations via `window.$trans.get('key')` or `trans('key')` helper in Blade
- HTTP requests via `window.$http` service, not raw fetch/axios

## External Integrations

- **Authentication**: Supports LDAP, SAML2, OAuth2 (via Socialite), and standard email/password
- Auth services in `app/Access/` (e.g., `LdapService`, `Saml2Service`, `SocialAuthService`)
- **Storage**: Configurable via Laravel filesystems (local, S3) for images/attachments
- **Exports**: PDF generation via wkhtmltopdf (knplabs/snappy) or dompdf
- **Editor**: TinyMCE and custom Markdown editor with CodeMirror integration

## Common Gotchas

- Don't bypass the permission system - always use `scopeVisible()` or `userCan()` checks
- Database transactions for multi-step operations use `DatabaseTransaction` helper class
- Use `Activity::add()` for audit events, not manual logging
- Frontend component initialization is automatic via `window.$components.init()` - don't manually instantiate
- Helpers in `app/App/helpers.php` are autoloaded - use `user()`, `userCan()`, `setting()`, etc.
Loading