eightynine / filament-docs
Elegant documentation system for your Filament application with search, navigation, and markdown support
Requires
- php: ^8.2
- barryvdh/laravel-dompdf: ^3.0
- filament/filament: ^3.0
- illuminate/contracts: ^10.0|^11.0|^12.0
- league/commonmark: ^2.4
- spatie/laravel-package-tools: ^1.15.0
Requires (Dev)
- nunomaduro/collision: ^7.9|^8.0
- orchestra/testbench: ^8.0|^9.0|^10.0
- pestphp/pest: ^2.0|^3.0
- pestphp/pest-plugin-arch: ^2.0|^3.0
- pestphp/pest-plugin-laravel: ^2.0|^3.0
README
Filament Docs is a comprehensive documentation management system designed specifically for Filament admin panels. It provides an elegant, user-friendly interface for creating, organizing, and presenting documentation directly within your Filament application.
This package transforms your documentation workflow by offering a sophisticated markdown-based documentation system with advanced search capabilities, intelligent navigation, and seamless integration with Filament's design language. Whether you're building internal documentation for your team, user manuals for clients, or API documentation for developers, Filament Docs provides all the tools you need to create professional, searchable, and maintainable documentation.
Why Choose Filament Docs?
Unlike traditional documentation solutions that require separate hosting or complex setups, Filament Docs integrates seamlessly into your existing Filament application. This means:
- Unified Experience: Your documentation lives alongside your application interface
- Consistent Design: Automatically inherits your Filament theme and styling
- Access Control: Leverage Filament's existing authentication and authorization
- No Additional Infrastructure: No need for separate documentation hosting
- Developer-Friendly: Built with Laravel and Filament best practices
Features
๐ Advanced Markdown Support
- Full CommonMark Compatibility: Support for all standard markdown features including tables, code blocks, and links
- Syntax Highlighting: Automatic code syntax highlighting for 100+ programming languages
- Custom Extensions: Support for custom markdown extensions and processing
- Safe HTML: Configurable HTML input handling with XSS protection
- Mathematical Expressions: Optional support for LaTeX-style mathematical notation
๐ Intelligent Search System
- Real-time Search: Instant search results as you type with configurable debouncing
- Context-Aware Results: Search results include surrounding context for better understanding
- Content Highlighting: Automatic highlighting of search terms within results
- Section-Based Filtering: Search within specific documentation sections
- Performance Optimized: Efficient indexing and caching for large documentation sets
- Fuzzy Matching: Smart search that handles typos and partial matches
๐งญ Smart Navigation & User Experience
- Hierarchical Sidebar: Automatically generated navigation from your file structure
- Progress Tracking: Visual indicators showing reading progress through sections
- Persistent State: Navigation state persists across browser sessions
- Breadcrumb Navigation: Clear path indication for deep documentation structures
- Quick Jump: Keyboard shortcuts for rapid navigation
- Table of Contents: Auto-generated TOC for long documents
๐ฑ Responsive & Accessible Design
- Mobile-First: Optimized for all screen sizes from mobile to desktop
- Touch-Friendly: Gesture support for mobile navigation
- Accessibility Compliant: WCAG 2.1 AA compliance with proper ARIA labels
- Dark Mode Support: Automatic adaptation to Filament's theme preferences
- Print-Friendly: Optimized layouts for printing documentation
๐จ Customization & Theming
- Theme Integration: Seamlessly integrates with your Filament theme
- Custom CSS: Easy to override styles with your own CSS
- Configurable Components: Customize search behavior, navigation, and display options
- Brand Consistency: Maintains your application's look and feel
- Layout Options: Multiple layout configurations for different use cases
๐ Internationalization & Localization
- Multi-Language Support: Built-in support for multiple languages
- RTL Language Support: Full support for right-to-left languages
- Translatable Content: Documentation can be organized by language
- Locale-Aware Search: Search respects language-specific text processing
- Date/Time Formatting: Localized date and time displays
โก Performance & Optimization
- Lazy Loading: Content loads on-demand for better performance
- Efficient Caching: Smart caching strategies for both content and search indices
- Minimal Bundle Size: Optimized JavaScript and CSS for fast loading
- Progressive Enhancement: Core functionality works without JavaScript
- CDN-Ready: Assets can be served from CDN for global performance
๐ง Developer Tools & Commands
- Artisan Commands: Comprehensive CLI tools for generating and managing documentation
- Template System: Pre-built templates for different documentation types
- Hot Reloading: Development mode with automatic refresh on file changes
- Validation Tools: Built-in validation for markdown syntax and structure
- Import/Export: Tools for migrating documentation from other systems
Requirements
Before installing Filament Docs, ensure your system meets the following requirements:
System Requirements
- PHP: 8.1 or higher (8.2+ recommended for optimal performance)
- Laravel: 10.0 or higher
- Filament: 3.0 or higher
PHP Extensions
The following PHP extensions are required:
mbstring
- For proper text encoding handlingjson
- For configuration and data processingfileinfo
- For file type detectiondom
- For HTML parsing and manipulation
Optional Dependencies
For enhanced functionality, consider installing:
league/commonmark
- Enhanced markdown processing (auto-installed)spatie/laravel-markdown
- Additional markdown featuresintervention/image
- Image processing for documentation assets
Browser Compatibility
- Modern Browsers: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
- Mobile: iOS Safari 14+, Chrome Mobile 90+
- Legacy Support: Internet Explorer is not supported
Installation
Step 1: Install via Composer
Install the package using Composer. This will automatically handle all dependencies:
composer require eightynine/filament-docs
Step 2: Publish Configuration Files
Publish the configuration file to customize the package behavior:
php artisan vendor:publish --tag="filament-docs-config"
This creates config/filament-docs.php
where you can configure:
- Default documentation paths
- Markdown processing options
- Search behavior settings
- UI customization options
Step 3: Publish Views (Optional)
If you need to customize the views, publish them:
php artisan vendor:publish --tag="filament-docs-views"
This publishes views to resources/views/vendor/filament-docs/
for customization.
Step 4: Publish Translations (Optional)
For internationalization support, publish the language files:
php artisan vendor:publish --tag="filament-docs-translations"
This creates language files in resources/lang/vendor/filament-docs/
.
Step 5: Publish Assets (Optional)
To customize CSS and JavaScript:
php artisan vendor:publish --tag="filament-docs-assets"
Step 6: Create Documentation Directory
Create your documentation directory structure:
mkdir -p resources/docs
Automatic Registration
The package uses auto-discovery, so the service provider will be automatically registered. If you've disabled auto-discovery, manually add the service provider to config/app.php
:
'providers' => [ // Other service providers... EightyNine\FilamentDocs\FilamentDocsServiceProvider::class, ],
Configuration
After publishing the configuration file, you'll find config/filament-docs.php
with comprehensive options to customize the package behavior.
Complete Configuration Reference
<?php <?php return [ /* |-------------------------------------------------------------------------- | Default Documentation Path |-------------------------------------------------------------------------- | | This option defines the default path where markdown documentation | files will be stored. You can override this in your DocsPage | implementation by overriding the getDocsPath() method. | */ 'default_docs_path' => resource_path('docs'), /* |-------------------------------------------------------------------------- | Markdown Parser Configuration |-------------------------------------------------------------------------- | | Configuration options for the CommonMark markdown parser. | These settings will be passed to the CommonMarkConverter. | */ 'markdown' => [ 'html_input' => 'strip', 'allow_unsafe_links' => false, 'max_nesting_level' => 10, 'slug_normalizer' => [ 'max_length' => 255, ], ], /* |-------------------------------------------------------------------------- | Search Configuration |-------------------------------------------------------------------------- | | Configuration options for the search functionality. | */ 'search' => [ 'debounce_ms' => 300, 'max_results_per_section' => 3, 'highlight_class' => 'bg-yellow-200 text-yellow-800 px-1 rounded', ], /* |-------------------------------------------------------------------------- | UI Configuration |-------------------------------------------------------------------------- | | Configuration options for the user interface. | */ 'ui' => [ 'sidebar_width' => 'lg:w-80', 'max_sidebar_height' => 'max-h-96', 'loading_delay_ms' => 300, 'default_navigation_icon' => 'heroicon-o-book-open', 'default_navigation_group' => 'Documentation', ], /* |-------------------------------------------------------------------------- | Section Ordering |-------------------------------------------------------------------------- | | Default ordering for documentation sections. You can override this | in your DocsPage implementation by overriding the getSectionOrder() method. | */ 'section_order' => [ 'getting-started' => 1, 'installation' => 2, 'configuration' => 3, 'usage' => 4, 'examples' => 5, 'api' => 6, 'api-reference' => 7, 'troubleshooting' => 8, 'faq' => 9, 'changelog' => 10, ], /* |-------------------------------------------------------------------------- | File Extensions |-------------------------------------------------------------------------- | | Supported file extensions for documentation files. | */ 'supported_extensions' => ['md', 'markdown'], /* |-------------------------------------------------------------------------- | Commands Configuration |-------------------------------------------------------------------------- | | Configuration for the package commands. | */ 'commands' => [ 'make_docs_page' => [ 'default_panel' => 'admin', 'default_navigation_group' => 'Documentation', 'default_navigation_icon' => 'heroicon-o-book-open', ], 'make_markdown' => [ 'templates' => ['basic', 'guide', 'api', 'troubleshooting', 'feature'], 'default_template' => 'basic', ], ], ];
Configuration Examples
Basic Setup
For a simple documentation setup, minimal configuration is needed:
return [ 'default_docs_path' => resource_path('docs'), 'search' => [ 'debounce_ms' => 200, 'max_results_per_section' => 5, ], ];
Multi-Language Setup
For international applications:
return [ 'localization' => [ 'supported_locales' => ['en', 'es', 'fr'], 'locale_paths' => [ 'en' => 'docs/en', 'es' => 'docs/es', 'fr' => 'docs/fr', ], ], ];
High-Performance Setup
For large documentation sites:
return [ 'performance' => [ 'cache_duration' => 7200, 'lazy_loading' => true, 'preload_adjacent' => true, ], 'search' => [ 'index' => [ 'cache_duration' => 86400, 'rebuild_on_change' => false, ], ], ];
Usage
Filament Docs provides multiple ways to create and manage documentation within your Filament application. This section covers everything from basic setup to advanced customization.
Quick Start Guide
1. Create Your First Documentation Page
The fastest way to get started is using the Artisan command:
php artisan make:filament-docs-page UserManual \ --navigation-group="Help & Documentation" \ --navigation-icon="heroicon-o-book-open" \ --navigation-sort=10
This single command creates:
- Page Class:
app/Filament/Pages/UserManual.php
- The Filament page - View File:
resources/views/filament/pages/user-manual.blade.php
- Custom view (if needed) - Documentation Directory:
resources/user-manual/
- Where your markdown files go - Sample Content: Example markdown files to get you started
2. Add Your Documentation Content
Navigate to your newly created documentation directory and start adding markdown files:
# Navigate to your docs directory cd resources/user-manual # Create your first documentation file echo "# Welcome to the User Manual" > getting-started.md
3. Access Your Documentation
Your documentation page is now available in your Filament admin panel under the navigation group you specified!
Command Reference
Creating Documentation Pages
The make:filament-docs-page
command offers extensive customization options:
# Basic page creation php artisan make:filament-docs-page MyDocs # Full featured page with all options php artisan make:filament-docs-page ApiDocumentation \ --navigation-group="Developer Resources" \ --navigation-icon="heroicon-o-code-bracket" \ --navigation-label="API Docs" \ --navigation-sort=20 \ --navigation-badge="Beta" \ --title="API Documentation" \ --slug="api-docs" \ --docs-path="docs/api" \ --force
Available Options:
--navigation-group
: Groups pages in the sidebar--navigation-icon
: Heroicon name for the navigation item--navigation-label
: Custom label (defaults to page name)--navigation-sort
: Sort order in navigation (lower = higher)--navigation-badge
: Badge text shown next to navigation item--title
: Page title shown in browser and header--slug
: URL slug for the page--docs-path
: Custom path for markdown files--force
: Overwrite existing files
Creating Markdown Content
The make:filament-docs-markdown
command helps you create structured content:
# Basic markdown file php artisan make:filament-docs-markdown "Getting Started" # Using templates for different content types php artisan make:filament-docs-markdown "Installation Guide" --template=guide php artisan make:filament-docs-markdown "API Reference" --template=api php artisan make:filament-docs-markdown "Troubleshooting" --template=troubleshooting php artisan make:filament-docs-markdown "Feature Overview" --template=feature # Specify custom path and options php artisan make:filament-docs-markdown "Advanced Configuration" \ --path="docs/advanced" \ --template=guide \ --section="Advanced Topics" \ --order=10
Available Templates:
-
basic
- Simple documentation template with:- Introduction section
- Main content area
- Basic formatting examples
-
guide
- Step-by-step guide template with:- Prerequisites section
- Numbered step structure
- Code examples
- Troubleshooting tips
-
api
- API reference template with:- Endpoint documentation
- Request/response examples
- Parameter descriptions
- Authentication info
-
troubleshooting
- Problem-solving template with:- Common issues section
- Solution steps
- FAQ format
- Contact information
-
feature
- Feature documentation template with:- Feature overview
- Use cases
- Configuration options
- Examples
Advanced Page Customization
Complete Custom Documentation Page
Create sophisticated documentation pages with full control:
<?php namespace App\Filament\Pages; use EightyNine\FilamentDocs\Pages\DocsPage; use Filament\Pages\Actions\Action; use Illuminate\Contracts\Support\Htmlable; class UserManual extends DocsPage { // Basic page configuration protected static ?string $navigationIcon = 'heroicon-o-book-open'; protected static ?string $navigationGroup = 'Help & Documentation'; protected static ?string $navigationLabel = 'User Guide'; protected static ?int $navigationSort = 10; protected static string $view = 'filament.pages.user-manual'; // Page metadata protected static ?string $title = 'User Manual'; protected static ?string $slug = 'user-manual'; // Custom properties public bool $showToc = true; public string $currentVersion = '2.0'; /** * Page title and heading customization */ public function getTitle(): string | Htmlable { return 'User Manual v' . $this->currentVersion; } public function getHeading(): string | Htmlable { return 'Complete User Manual & Documentation'; } public function getSubheading(): string | Htmlable | null { return 'Everything you need to know to use the system effectively'; } /** * Documentation path configuration */ protected function getDocsPath(): string { return resource_path('user-manual'); } /** * Custom section ordering */ protected function getSectionOrder(string $filename): int { $orderMap = [ 'introduction' => 1, 'getting-started' => 2, 'basic-usage' => 3, 'user-management' => 4, 'advanced-features' => 5, 'troubleshooting' => 6, 'api-reference' => 7, 'changelog' => 8, ]; return $orderMap[$filename] ?? 99; } /** * Custom section titles */ protected function getSectionTitle(string $filename): string { $titleMap = [ 'getting-started' => 'Getting Started', 'user-management' => 'User Management', 'api-reference' => 'API Reference', 'troubleshooting' => 'Troubleshooting & FAQ', ]; return $titleMap[$filename] ?? ucwords(str_replace(['-', '_'], ' ', $filename)); } /** * Custom page actions */ protected function getActions(): array { return [ Action::make('download_pdf') ->label('Download PDF') ->icon('heroicon-o-arrow-down-tray') ->url(route('docs.pdf', ['page' => 'user-manual'])) ->openUrlInNewTab(), Action::make('print') ->label('Print') ->icon('heroicon-o-printer') ->action('print') ->extraAttributes(['onclick' => 'window.print()']), Action::make('feedback') ->label('Give Feedback') ->icon('heroicon-o-chat-bubble-left-ellipsis') ->url('mailto:support@example.com?subject=Documentation Feedback') ->openUrlInNewTab(), ]; } /** * Page authorization */ public static function canAccess(): bool { return auth()->user()?->can('view_documentation') ?? false; } /** * Custom navigation badge */ public static function getNavigationBadge(): ?string { // Show version or status return 'v2.0'; } /** * Dynamic navigation badge color */ public static function getNavigationBadgeColor(): ?string { return 'success'; // or 'primary', 'warning', 'danger', etc. } /** * Custom middleware */ public static function getMiddleware(): string | array { return ['auth', 'verified']; } /** * Page lifecycle hooks */ public function mount(): void { // Log documentation access logger()->info('User accessed documentation', [ 'user_id' => auth()->id(), 'page' => static::class, 'timestamp' => now(), ]); } /** * Custom view data */ protected function getViewData(): array { return array_merge(parent::getViewData(), [ 'showToc' => $this->showToc, 'currentVersion' => $this->currentVersion, 'lastUpdated' => $this->getLastUpdatedDate(), ]); } /** * Get last updated date for documentation */ protected function getLastUpdatedDate(): string { $path = $this->getDocsPath(); $latestTimestamp = 0; if (is_dir($path)) { $files = glob($path . '/*.md'); foreach ($files as $file) { $timestamp = filemtime($file); if ($timestamp > $latestTimestamp) { $latestTimestamp = $timestamp; } } } return $latestTimestamp > 0 ? date('F j, Y', $latestTimestamp) : 'Unknown'; } }
Documentation File Organization
Recommended Directory Structure
Organize your documentation for maximum clarity and maintainability:
resources/docs/
โโโ getting-started/
โ โโโ 01-introduction.md
โ โโโ 02-installation.md
โ โโโ 03-quick-start.md
โ โโโ 04-first-steps.md
โโโ user-guide/
โ โโโ 01-dashboard.md
โ โโโ 02-navigation.md
โ โโโ 03-user-management.md
โ โโโ 04-reports.md
โ โโโ 05-settings.md
โโโ advanced/
โ โโโ api-integration.md
โ โโโ custom-fields.md
โ โโโ automation.md
โ โโโ webhooks.md
โโโ troubleshooting/
โ โโโ common-issues.md
โ โโโ error-codes.md
โ โโโ faq.md
โโโ reference/
โ โโโ api-endpoints.md
โ โโโ configuration.md
โ โโโ glossary.md
โโโ assets/
โโโ images/
โโโ diagrams/
โโโ downloads/
Markdown Best Practices
Create effective documentation with these markdown conventions:
# Page Title (H1 - Use only once per file) Brief description of what this page covers. ## Main Section (H2) Content for the main section. ### Subsection (H3) More detailed content. #### Details (H4) Fine-grained details. ## Code Examples Use fenced code blocks with language specification: ```php <?php class Example { public function method(): string { return 'Hello World'; } }
Important Information
Note: Use blockquotes for important notes.
Warning: Use blockquotes for warnings.
Tip: Use blockquotes for helpful tips.
Lists
Unordered Lists
- First item
- Second item
- Nested item
- Another nested item
- Third item
Ordered Lists
- First step
- Second step
- Sub-step
- Another sub-step
- Third step
Tables
Column 1 | Column 2 | Column 3 |
---|---|---|
Data 1 | Data 2 | Data 3 |
Data 4 | Data 5 | Data 6 |
Links and References
Images
Task Lists
- Completed task
- Pending task
- Another pending task
### Multi-Language Documentation
#### Setting Up Multi-Language Support
Configure your application for multiple languages:
```php
// config/filament-docs.php
return [
'localization' => [
'supported_locales' => ['en', 'es', 'fr', 'de'],
'locale_paths' => [
'en' => 'docs/en',
'es' => 'docs/es',
'fr' => 'docs/fr',
'de' => 'docs/de',
],
'fallback_to_default' => true,
],
];
Directory Structure for Multi-Language
resources/docs/
โโโ en/
โ โโโ getting-started.md
โ โโโ user-guide.md
โ โโโ api-reference.md
โโโ es/
โ โโโ getting-started.md
โ โโโ user-guide.md
โ โโโ api-reference.md
โโโ fr/
โ โโโ getting-started.md
โ โโโ user-guide.md
โ โโโ api-reference.md
โโโ de/
โโโ getting-started.md
โโโ user-guide.md
โโโ api-reference.md
Language-Aware Documentation Page
class MultiLanguageDocs extends DocsPage { protected function getDocsPath(): string { $locale = app()->getLocale(); $paths = config('filament-docs.localization.locale_paths'); return resource_path($paths[$locale] ?? $paths['en']); } public function getTitle(): string { return __('filament-docs::docs.title'); } protected function getSectionTitle(string $filename): string { // Try to get translated title first $translationKey = "docs.sections.{$filename}"; $translated = __($translationKey); if ($translated !== $translationKey) { return $translated; } // Fallback to formatted filename return parent::getSectionTitle($filename); } }
Customization & Theming
Filament Docs provides extensive customization options to match your application's design and functionality requirements.
Visual Customization
Custom Styling with CSS
Publish and customize the CSS assets:
php artisan vendor:publish --tag="filament-docs-assets"
This creates customizable CSS files in resources/css/vendor/filament-docs/
:
/* resources/css/vendor/filament-docs/custom.css */ /* Custom documentation container */ .docs-container { @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8; } /* Custom sidebar styling */ .docs-sidebar { @apply w-64 flex-shrink-0 bg-white dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700; } /* Custom content area */ .docs-content { @apply flex-1 min-w-0 p-6; } /* Custom search styling */ .docs-search { @apply mb-6 relative; } .docs-search input { @apply w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500; } /* Custom typography */ .docs-prose { @apply prose prose-lg dark:prose-invert max-w-none; } .docs-prose h1 { @apply text-3xl font-bold text-gray-900 dark:text-white mb-6; } .docs-prose h2 { @apply text-2xl font-semibold text-gray-800 dark:text-gray-200 mt-8 mb-4; } /* Custom navigation styling */ .docs-nav-item { @apply block px-3 py-2 rounded-md text-sm font-medium transition-colors; } .docs-nav-item:hover { @apply bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white; } .docs-nav-item.active { @apply bg-blue-100 dark:bg-blue-900 text-blue-900 dark:text-blue-100; } /* Custom code block styling */ .docs-prose pre { @apply bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700; } /* Custom table styling */ .docs-prose table { @apply border-collapse border border-gray-300 dark:border-gray-600; } .docs-prose th, .docs-prose td { @apply border border-gray-300 dark:border-gray-600 px-4 py-2; } .docs-prose th { @apply bg-gray-50 dark:bg-gray-800 font-semibold; } /* Responsive design */ @media (max-width: 768px) { .docs-sidebar { @apply w-full; } .docs-container { @apply flex-col; } }
Custom Blade Views
Publish and customize the Blade templates:
php artisan vendor:publish --tag="filament-docs-views"
Customize the main documentation template:
{{-- resources/views/vendor/filament-docs/docs-page.blade.php --}} <x-filament-panels::page> <div class="docs-container flex gap-6"> {{-- Custom sidebar --}} <aside class="docs-sidebar"> <div class="docs-search"> <input type="text" placeholder="{{ __('filament-docs::docs.search_placeholder') }}" x-data="docsSearch" x-model="query" x-on:input.debounce.300ms="search" /> </div> <nav class="docs-navigation"> @foreach($sections as $section) <div class="docs-nav-section"> <h3 class="docs-nav-title">{{ $section['title'] }}</h3> @foreach($section['items'] as $item) <a href="#{{ $item['slug'] }}" class="docs-nav-item {{ $item['active'] ? 'active' : '' }}" x-on:click="loadSection('{{ $item['slug'] }}')" > {{ $item['title'] }} @if($item['badge']) <span class="docs-nav-badge">{{ $item['badge'] }}</span> @endif </a> @endforeach </div> @endforeach </nav> </aside> {{-- Custom content area --}} <main class="docs-content"> <div class="docs-prose" x-html="currentContent"> {!! $defaultContent !!} </div> {{-- Custom footer --}} <footer class="docs-footer mt-12 pt-6 border-t border-gray-200 dark:border-gray-700"> <div class="flex justify-between items-center"> <p class="text-sm text-gray-500 dark:text-gray-400"> Last updated: {{ $lastUpdated }} </p> <div class="flex space-x-4"> @if($previousSection) <a href="#{{ $previousSection['slug'] }}" class="docs-nav-prev"> โ {{ $previousSection['title'] }} </a> @endif @if($nextSection) <a href="#{{ $nextSection['slug'] }}" class="docs-nav-next"> {{ $nextSection['title'] }} โ </a> @endif </div> </div> </footer> </main> </div> </x-filament-panels::page>
Functional Customization
Advanced Section Management
Create sophisticated section ordering and grouping:
class AdvancedDocsPage extends DocsPage { /** * Define section groups with custom ordering */ protected function getSectionGroups(): array { return [ 'getting-started' => [ 'title' => 'Getting Started', 'description' => 'Essential information to get you up and running', 'icon' => 'heroicon-o-play', 'order' => 1, 'sections' => [ 'introduction', 'installation', 'quick-start', 'configuration', ], ], 'user-guide' => [ 'title' => 'User Guide', 'description' => 'Comprehensive guide for end users', 'icon' => 'heroicon-o-user', 'order' => 2, 'sections' => [ 'dashboard', 'navigation', 'user-management', 'reports', ], ], 'advanced' => [ 'title' => 'Advanced Topics', 'description' => 'Advanced features and customization', 'icon' => 'heroicon-o-cog', 'order' => 3, 'sections' => [ 'api-integration', 'custom-fields', 'automation', 'webhooks', ], ], 'reference' => [ 'title' => 'Reference', 'description' => 'Technical reference and troubleshooting', 'icon' => 'heroicon-o-book-open', 'order' => 4, 'sections' => [ 'api-reference', 'configuration-reference', 'troubleshooting', 'faq', ], ], ]; } /** * Custom section ordering within groups */ protected function getSectionOrder(string $filename): int { foreach ($this->getSectionGroups() as $group) { $index = array_search($filename, $group['sections'] ?? []); if ($index !== false) { return ($group['order'] * 100) + $index; } } return 999; } /** * Add custom metadata to sections */ protected function getSectionMetadata(string $filename): array { $metadata = [ 'introduction' => [ 'estimated_reading_time' => '5 min', 'difficulty' => 'Beginner', 'prerequisites' => [], ], 'api-integration' => [ 'estimated_reading_time' => '15 min', 'difficulty' => 'Advanced', 'prerequisites' => ['Basic API knowledge', 'Authentication setup'], ], 'troubleshooting' => [ 'estimated_reading_time' => '10 min', 'difficulty' => 'Intermediate', 'prerequisites' => ['Basic system knowledge'], ], ]; return $metadata[$filename] ?? []; } }
Custom Search Configuration
Implement advanced search features:
class SearchableDocsPage extends DocsPage { /** * Custom search indexing */ protected function buildSearchIndex(): array { $index = []; $docsPath = $this->getDocsPath(); foreach ($this->getMarkdownFiles() as $file) { $content = file_get_contents($file); $filename = basename($file, '.md'); // Parse frontmatter if present $frontmatter = $this->parseFrontmatter($content); $content = $this->removeFrontmatter($content); // Extract headings for better search structure $headings = $this->extractHeadings($content); // Build searchable content blocks foreach ($headings as $heading) { $index[] = [ 'section' => $filename, 'title' => $heading['title'], 'level' => $heading['level'], 'content' => $heading['content'], 'tags' => $frontmatter['tags'] ?? [], 'weight' => $this->getSearchWeight($heading['level']), ]; } } return $index; } /** * Custom search scoring */ protected function getSearchWeight(int $headingLevel): int { return match($headingLevel) { 1 => 100, // H1 - highest priority 2 => 80, // H2 - high priority 3 => 60, // H3 - medium priority 4 => 40, // H4 - lower priority default => 20, // Content - lowest priority }; } /** * Parse YAML frontmatter */ protected function parseFrontmatter(string $content): array { if (!str_starts_with($content, '---')) { return []; } $parts = explode('---', $content, 3); if (count($parts) < 3) { return []; } return yaml_parse($parts[1]) ?: []; } }
Content Enhancement Features
Interactive Elements
Add interactive components to your documentation:
class InteractiveDocsPage extends DocsPage { /** * Custom markdown processing with interactive elements */ protected function processMarkdown(string $content): string { // Process standard markdown first $html = parent::processMarkdown($content); // Add interactive elements $html = $this->addInteractiveCallouts($html); $html = $this->addCopyCodeButtons($html); $html = $this->addExpandableCodeBlocks($html); $html = $this->addLiveExamples($html); return $html; } /** * Add interactive callout boxes */ protected function addInteractiveCallouts(string $html): string { // Convert blockquotes with special syntax to callouts $patterns = [ '/\[!NOTE\](.*?)<\/blockquote>/s' => '<div class="callout callout-note">$1</div>', '/\[!WARNING\](.*?)<\/blockquote>/s' => '<div class="callout callout-warning">$1</div>', '/\[!TIP\](.*?)<\/blockquote>/s' => '<div class="callout callout-tip">$1</div>', ]; return preg_replace(array_keys($patterns), array_values($patterns), $html); } /** * Add copy buttons to code blocks */ protected function addCopyCodeButtons(string $html): string { return preg_replace( '/(<pre><code[^>]*>)(.*?)(<\/code><\/pre>)/s', '$1<button class="copy-code-btn" onclick="copyCode(this)">Copy</button>$2$3', $html ); } /** * Add expandable code blocks for long examples */ protected function addExpandableCodeBlocks(string $html): string { return preg_replace_callback( '/(<pre><code[^>]*>)(.*?)(<\/code><\/pre>)/s', function ($matches) { $content = $matches[2]; $lineCount = substr_count($content, "\n"); if ($lineCount > 20) { return sprintf( '<div class="expandable-code" x-data="{ expanded: false }"> <div x-show="!expanded" class="code-preview">%s</div> <div x-show="expanded">%s</div> <button x-on:click="expanded = !expanded" x-text="expanded ? \'Show Less\' : \'Show More\'"></button> </div>', $matches[1] . substr($content, 0, 500) . '...' . $matches[3], $matches[0] ); } return $matches[0]; }, $html ); } }
Theme Integration
Custom Filament Theme Integration
Integrate seamlessly with custom Filament themes:
// In your AppServiceProvider or custom service provider public function boot(): void { // Register custom theme for documentation Filament::serving(function () { Filament::registerTheme( app(AssetManager::class)->getThemeStylesheets()[0] ?? asset('css/filament/docs/theme.css') ); }); }
Create a custom theme CSS file:
/* resources/css/filament/docs/theme.css */ /* Inherit from main Filament theme */ @import '../app/theme.css'; /* Documentation-specific overrides */ .fi-docs-page { --docs-primary-color: theme('colors.blue.600'); --docs-secondary-color: theme('colors.gray.600'); --docs-accent-color: theme('colors.amber.500'); } /* Dark theme support */ .dark .fi-docs-page { --docs-primary-color: theme('colors.blue.400'); --docs-secondary-color: theme('colors.gray.300'); --docs-accent-color: theme('colors.amber.400'); } /* Integrate with Filament's design system */ .fi-docs-sidebar { @apply bg-white dark:bg-gray-900; border-right: 1px solid theme('colors.gray.200'); } .dark .fi-docs-sidebar { border-right-color: theme('colors.gray.700'); } .fi-docs-nav-item { @apply text-gray-700 dark:text-gray-300; @apply hover:bg-gray-100 dark:hover:bg-gray-800; @apply focus:bg-gray-100 dark:focus:bg-gray-800; } .fi-docs-nav-item--active { @apply bg-primary-50 dark:bg-primary-900/50; @apply text-primary-700 dark:text-primary-300; @apply border-r-2 border-primary-600 dark:border-primary-400; }
Advanced Features & Integrations
Performance Optimization
Content Caching Strategy
Implement intelligent caching for large documentation sites:
class CachedDocsPage extends DocsPage { /** * Cache duration for different content types */ protected function getCacheDuration(string $type): int { return match($type) { 'content' => 3600, // 1 hour for content 'search_index' => 86400, // 24 hours for search index 'navigation' => 1800, // 30 minutes for navigation 'metadata' => 43200, // 12 hours for metadata default => 3600, }; } /** * Cache content with automatic invalidation */ protected function getCachedContent(string $filename): string { $cacheKey = "docs.content.{$filename}." . md5_file($this->getFilePath($filename)); return Cache::remember( $cacheKey, $this->getCacheDuration('content'), fn() => $this->loadAndProcessMarkdown($filename) ); } /** * Preload adjacent sections for faster navigation */ protected function preloadAdjacentSections(string $currentSection): void { $sections = $this->getAllSections(); $currentIndex = array_search($currentSection, $sections); if ($currentIndex !== false) { // Preload previous and next sections $toPreload = array_filter([ $sections[$currentIndex - 1] ?? null, $sections[$currentIndex + 1] ?? null, ]); foreach ($toPreload as $section) { // Cache in background dispatch(fn() => $this->getCachedContent($section)); } } } }
Search Performance Optimization
Implement efficient search with indexing:
class OptimizedSearchDocsPage extends DocsPage { /** * Build and cache search index */ protected function getSearchIndex(): array { return Cache::remember( 'docs.search_index.' . $this->getIndexHash(), $this->getCacheDuration('search_index'), fn() => $this->buildOptimizedSearchIndex() ); } /** * Create hash of all documentation files for cache invalidation */ protected function getIndexHash(): string { $files = $this->getMarkdownFiles(); $hashes = array_map('md5_file', $files); return md5(implode('', $hashes)); } /** * Build optimized search index with stemming and stop words */ protected function buildOptimizedSearchIndex(): array { $index = []; $stopWords = $this->getStopWords(); foreach ($this->getMarkdownFiles() as $file) { $content = file_get_contents($file); $filename = basename($file, '.md'); // Tokenize and clean content $tokens = $this->tokenizeContent($content); $tokens = $this->removeStopWords($tokens, $stopWords); $tokens = $this->stemWords($tokens); // Build inverted index foreach ($tokens as $position => $token) { if (!isset($index[$token])) { $index[$token] = []; } $index[$token][] = [ 'section' => $filename, 'position' => $position, 'context' => $this->getTokenContext($content, $position), ]; } } return $index; } /** * Perform optimized search with ranking */ protected function performSearch(string $query): array { $index = $this->getSearchIndex(); $queryTokens = $this->tokenizeContent($query); $results = []; foreach ($queryTokens as $token) { if (isset($index[$token])) { foreach ($index[$token] as $match) { $key = $match['section']; if (!isset($results[$key])) { $results[$key] = [ 'section' => $match['section'], 'score' => 0, 'matches' => [], ]; } $results[$key]['score'] += $this->calculateRelevanceScore($match); $results[$key]['matches'][] = $match; } } } // Sort by relevance score uasort($results, fn($a, $b) => $b['score'] <=> $a['score']); return array_slice($results, 0, 20); } }
Integration with External Systems
Version Control Integration
Integrate with Git for documentation versioning:
class VersionedDocsPage extends DocsPage { /** * Get available documentation versions */ protected function getAvailableVersions(): array { $gitTags = shell_exec('git tag -l "docs-*" --sort=-version:refname'); $versions = array_filter(explode("\n", $gitTags)); return array_map(function ($tag) { return [ 'tag' => $tag, 'version' => str_replace('docs-', '', $tag), 'date' => $this->getTagDate($tag), ]; }, $versions); } /** * Load documentation for specific version */ protected function loadVersionedContent(string $version, string $filename): string { $tag = "docs-{$version}"; $filePath = $this->getDocsPath() . "/{$filename}.md"; // Get file content from specific Git tag $content = shell_exec("git show {$tag}:{$filePath} 2>/dev/null"); return $content ?: $this->loadCurrentContent($filename); } /** * Show documentation changes between versions */ protected function getVersionDiff(string $fromVersion, string $toVersion, string $filename): array { $fromTag = "docs-{$fromVersion}"; $toTag = "docs-{$toVersion}"; $filePath = $this->getDocsPath() . "/{$filename}.md"; $diff = shell_exec("git diff {$fromTag}..{$toTag} -- {$filePath}"); return $this->parseDiff($diff); } }
Analytics Integration
Track documentation usage and effectiveness:
class AnalyticsDocsPage extends DocsPage { /** * Track documentation page views */ public function mount(): void { parent::mount(); // Track page view $this->trackEvent('docs_page_view', [ 'page' => static::class, 'user_id' => auth()->id(), 'session_id' => session()->getId(), 'timestamp' => now(), ]); } /** * Track section interactions */ protected function trackSectionView(string $section): void { $this->trackEvent('docs_section_view', [ 'page' => static::class, 'section' => $section, 'user_id' => auth()->id(), 'timestamp' => now(), ]); } /** * Track search queries */ protected function trackSearch(string $query, array $results): void { $this->trackEvent('docs_search', [ 'query' => $query, 'results_count' => count($results), 'user_id' => auth()->id(), 'timestamp' => now(), ]); } /** * Generate usage analytics */ protected function getUsageAnalytics(): array { return [ 'popular_sections' => $this->getPopularSections(), 'search_patterns' => $this->getSearchPatterns(), 'user_journey' => $this->getUserJourney(), 'effectiveness_metrics' => $this->getEffectivenessMetrics(), ]; } /** * Send event to analytics service */ protected function trackEvent(string $event, array $data): void { // Send to your preferred analytics service // Google Analytics, Mixpanel, custom analytics, etc. event(new DocumentationEvent($event, $data)); } }
Security & Access Control
Role-Based Documentation Access
Implement fine-grained access control:
class SecureDocsPage extends DocsPage { /** * Define section-level permissions */ protected function getSectionPermissions(): array { return [ 'getting-started' => 'view_basic_docs', 'user-guide' => 'view_user_docs', 'api-reference' => 'view_api_docs', 'admin-guide' => 'view_admin_docs', 'security' => 'view_security_docs', ]; } /** * Filter sections based on user permissions */ protected function getFilteredSections(): array { $allSections = $this->getAllSections(); $permissions = $this->getSectionPermissions(); $user = auth()->user(); return array_filter($allSections, function ($section) use ($permissions, $user) { $permission = $permissions[$section] ?? null; return $permission === null || $user?->can($permission); }); } /** * Secure content loading with access checks */ protected function loadSecureContent(string $filename): string { $permissions = $this->getSectionPermissions(); $requiredPermission = $permissions[$filename] ?? null; if ($requiredPermission && !auth()->user()?->can($requiredPermission)) { return $this->getAccessDeniedContent(); } return parent::loadContent($filename); } /** * Content for access denied scenarios */ protected function getAccessDeniedContent(): string { return "# Access Denied\n\nYou don't have permission to view this documentation section."; } }
Troubleshooting & Best Practices
Common Issues and Solutions
Issue: Documentation Not Loading
Symptoms: Empty documentation page or "No content found" message
Possible Causes & Solutions:
-
Incorrect file path:
// Check if the path exists protected function getDocsPath(): string { $path = resource_path('docs'); if (!is_dir($path)) { throw new \Exception("Documentation path does not exist: {$path}"); } return $path; }
-
File permissions:
# Fix file permissions chmod -R 755 resources/docs chown -R www-data:www-data resources/docs
-
Missing markdown files:
# Verify files exist ls -la resources/docs/ # Create sample file if needed echo "# Welcome" > resources/docs/getting-started.md
Issue: Search Not Working
Symptoms: Search returns no results or throws errors
Debugging Steps:
-
Check search configuration:
// In config/filament-docs.php 'search' => [ 'debounce_ms' => 300, 'max_results_per_section' => 3, 'min_query_length' => 2, // Make sure this isn't too high ],
-
Clear search cache:
php artisan cache:forget docs.search_index.*
-
Debug search index:
protected function debugSearch(): void { $index = $this->getSearchIndex(); logger()->info('Search index contents', ['index' => $index]); }
Issue: Styling Not Applied
Symptoms: Documentation appears unstyled or doesn't match theme
Solutions:
-
Publish and compile assets:
php artisan vendor:publish --tag="filament-docs-assets" npm run build
-
Check asset paths:
// In your layout @vite(['resources/css/vendor/filament-docs/app.css'])
-
Verify Tailwind configuration:
// tailwind.config.js module.exports = { content: [ './vendor/eightynine/filament-docs/**/*.blade.php', // ... other paths ], }
Issue: Performance Problems
Symptoms: Slow loading, high memory usage
Optimization Strategies:
-
Enable caching:
// In config/filament-docs.php 'performance' => [ 'cache_content' => true, 'cache_duration' => 3600, 'lazy_loading' => true, ],
-
Optimize large files:
protected function shouldLazyLoad(string $filename): bool { $fileSize = filesize($this->getFilePath($filename)); return $fileSize > 1024 * 100; // 100KB threshold }
-
Implement pagination for large documentation sets:
protected function getPaginatedSections(int $perPage = 10): array { $sections = $this->getAllSections(); $page = request('page', 1); $offset = ($page - 1) * $perPage; return array_slice($sections, $offset, $perPage); }
Performance Best Practices
Optimizing Content Structure
- Keep files reasonably sized (< 100KB per markdown file)
- Use descriptive filenames for better organization
- Implement proper heading hierarchy (H1 โ H2 โ H3)
- Optimize images and use appropriate formats
Caching Strategies
class OptimizedDocsPage extends DocsPage { /** * Multi-layer caching strategy */ protected function getCachedContent(string $filename): string { // Layer 1: Memory cache (fastest) if (isset($this->memoryCache[$filename])) { return $this->memoryCache[$filename]; } // Layer 2: Redis/Memcached (fast) $content = Cache::store('redis')->remember( "docs.content.{$filename}", 3600, function () use ($filename) { // Layer 3: File system cache (slower) return $this->loadAndProcessContent($filename); } ); // Store in memory for subsequent requests $this->memoryCache[$filename] = $content; return $content; } }
Database Optimization for Large Sites
class DatabaseOptimizedDocs extends DocsPage { /** * Store parsed content in database for very large sites */ protected function getContentFromDatabase(string $filename): ?string { return DB::table('docs_cache') ->where('filename', $filename) ->where('updated_at', '>', $this->getFileModifiedTime($filename)) ->value('content'); } protected function storeContentInDatabase(string $filename, string $content): void { DB::table('docs_cache')->updateOrInsert( ['filename' => $filename], [ 'content' => $content, 'updated_at' => now(), 'file_modified_at' => $this->getFileModifiedTime($filename), ] ); } }
Security Best Practices
Content Sanitization
class SecureDocsPage extends DocsPage { /** * Sanitize markdown content before processing */ protected function sanitizeContent(string $content): string { // Remove potentially dangerous HTML $content = strip_tags($content, $this->getAllowedTags()); // Sanitize URLs $content = preg_replace_callback( '/\[([^\]]+)\]\(([^)]+)\)/', [$this, 'sanitizeUrl'], $content ); return $content; } protected function sanitizeUrl(array $matches): string { $text = $matches[1]; $url = $matches[2]; // Only allow safe protocols $allowedProtocols = ['http', 'https', 'mailto', 'tel']; $protocol = parse_url($url, PHP_URL_SCHEME); if (!in_array($protocol, $allowedProtocols)) { return $text; // Remove link if protocol not allowed } return "[{$text}]({$url})"; } protected function getAllowedTags(): string { return '<p><br><strong><em><u><strike><ol><ul><li><h1><h2><h3><h4><h5><h6><blockquote><code><pre><a><img><table><thead><tbody><tr><td><th>'; } }
Input Validation
class ValidatedDocsPage extends DocsPage { /** * Validate search input */ protected function validateSearchQuery(string $query): string { // Sanitize and validate search query $query = trim($query); $query = preg_replace('/[^\w\s\-\.]/u', '', $query); if (strlen($query) < 2) { throw new \InvalidArgumentException('Search query too short'); } if (strlen($query) > 100) { throw new \InvalidArgumentException('Search query too long'); } return $query; } /** * Rate limiting for search requests */ protected function checkSearchRateLimit(): void { $key = 'docs.search.' . request()->ip(); $attempts = Cache::get($key, 0); if ($attempts >= 30) { // 30 searches per minute throw new \Exception('Search rate limit exceeded'); } Cache::put($key, $attempts + 1, 60); } }
SEO and Accessibility
SEO Optimization
class SEOOptimizedDocs extends DocsPage { /** * Generate SEO-friendly meta tags */ protected function getMetaTags(string $section): array { $content = $this->loadContent($section); $title = $this->extractTitle($content); $description = $this->extractDescription($content); return [ 'title' => $title . ' - ' . config('app.name'), 'description' => $description, 'keywords' => $this->extractKeywords($content), 'og:title' => $title, 'og:description' => $description, 'og:type' => 'article', 'og:url' => request()->url(), 'twitter:card' => 'summary', 'twitter:title' => $title, 'twitter:description' => $description, ]; } /** * Generate structured data for search engines */ protected function getStructuredData(string $section): array { return [ '@context' => 'https://schema.org', '@type' => 'TechArticle', 'headline' => $this->extractTitle($this->loadContent($section)), 'author' => [ '@type' => 'Organization', 'name' => config('app.name'), ], 'datePublished' => $this->getFileCreatedDate($section), 'dateModified' => $this->getFileModifiedDate($section), 'description' => $this->extractDescription($this->loadContent($section)), ]; } }
Accessibility Features
class AccessibleDocsPage extends DocsPage { /** * Add accessibility attributes to navigation */ protected function getAccessibleNavigation(): array { $sections = $this->getAllSections(); return array_map(function ($section, $index) { return [ 'title' => $this->getSectionTitle($section), 'url' => "#section-{$section}", 'aria-label' => "Navigate to {$this->getSectionTitle($section)}", 'tabindex' => $index === 0 ? '0' : '-1', 'role' => 'menuitem', ]; }, $sections, array_keys($sections)); } /** * Add ARIA landmarks to content */ protected function addAriaLandmarks(string $html): string { // Add navigation landmark $html = preg_replace( '/<nav([^>]*)>/', '<nav$1 role="navigation" aria-label="Documentation navigation">', $html ); // Add main content landmark $html = preg_replace( '/<main([^>]*)>/', '<main$1 role="main" aria-label="Documentation content">', $html ); // Add heading IDs for skip links $html = preg_replace_callback( '/<h([1-6])([^>]*)>(.*?)<\/h[1-6]>/', function ($matches) { $level = $matches[1]; $attributes = $matches[2]; $content = $matches[3]; $id = Str::slug($content); return "<h{$level}{$attributes} id=\"{$id}\" tabindex=\"-1\">{$content}</h{$level}>"; }, $html ); return $html; } }
Testing Documentation
Automated Testing
// tests/Feature/DocumentationTest.php class DocumentationTest extends TestCase { /** @test */ public function it_loads_documentation_pages() { $user = User::factory()->create(); $response = $this->actingAs($user) ->get('/admin/user-manual'); $response->assertStatus(200) ->assertSee('User Manual') ->assertSee('Documentation'); } /** @test */ public function it_loads_all_documentation_sections() { $docsPath = resource_path('docs'); $markdownFiles = glob("{$docsPath}/*.md"); $this->assertGreaterThan(0, count($markdownFiles), 'No markdown files found'); foreach ($markdownFiles as $file) { $filename = basename($file, '.md'); $response = $this->get("/admin/user-manual?section={$filename}"); $response->assertStatus(200); } } /** @test */ public function it_searches_documentation_content() { $response = $this->postJson('/admin/user-manual/search', [ 'query' => 'installation', ]); $response->assertStatus(200) ->assertJsonStructure([ 'results' => [ '*' => ['section', 'title', 'excerpt', 'matches'] ] ]); } /** @test */ public function it_validates_markdown_syntax() { $docsPath = resource_path('docs'); $markdownFiles = glob("{$docsPath}/*.md"); foreach ($markdownFiles as $file) { $content = file_get_contents($file); // Check for basic markdown structure $this->assertStringContainsString('# ', $content, "File {$file} should have at least one H1 heading"); // Check for proper heading hierarchy $this->validateHeadingHierarchy($content, $file); } } private function validateHeadingHierarchy(string $content, string $file): void { preg_match_all('/^(#{1,6})\s+(.+)$/m', $content, $matches); $previousLevel = 0; foreach ($matches[1] as $heading) { $level = strlen($heading); if ($level > $previousLevel + 1) { $this->fail("Heading hierarchy error in {$file}: jumped from H{$previousLevel} to H{$level}"); } $previousLevel = $level; } } }
Migration Guide
Upgrading from Version 1.x to 2.x
Breaking Changes
-
Namespace Changes:
// Old (v1.x) use EightyNine\FilamentDocs\Pages\DocsPage; // New (v2.x) - No change needed use EightyNine\FilamentDocs\Pages\DocsPage;
-
Configuration Structure:
// Old config structure (v1.x) return [ 'docs_path' => resource_path('docs'), 'search_enabled' => true, ]; // New config structure (v2.x) return [ 'default_docs_path' => resource_path('docs'), 'search' => [ 'enabled' => true, 'debounce_ms' => 300, // ... more options ], ];
-
Method Signatures:
// Old method (v1.x) protected function getDocsContent(): array { // Old implementation } // New method (v2.x) protected function getSections(): array { // New implementation with enhanced features }
Migration Steps
-
Update Composer Dependencies:
composer update eightynine/filament-docs
-
Republish Configuration:
php artisan vendor:publish --tag="filament-docs-config" --force
-
Update Custom Pages:
// If you have custom documentation pages, update them: class CustomDocsPage extends DocsPage { // Update any overridden methods according to new signatures protected function getSectionOrder(string $filename): int { // Updated implementation } }
-
Clear Caches:
php artisan cache:clear php artisan config:clear php artisan view:clear
Migrating from Other Documentation Systems
From Laravel Docs
// Create migration command php artisan make:command MigrateFromLaravelDocs class MigrateFromLaravelDocs extends Command { protected $signature = 'docs:migrate-laravel'; public function handle() { $oldDocsPath = base_path('docs'); $newDocsPath = resource_path('docs'); // Copy and convert files $this->copyAndConvertFiles($oldDocsPath, $newDocsPath); $this->info('Migration completed successfully!'); } private function copyAndConvertFiles(string $from, string $to): void { // Implementation for file conversion } }
From GitBook
// GitBook to Filament Docs converter class GitBookConverter { public function convertSummary(string $summaryPath): array { $content = file_get_contents($summaryPath); // Parse GitBook SUMMARY.md format preg_match_all('/\* \[([^\]]+)\]\(([^)]+)\)/', $content, $matches); $structure = []; foreach ($matches[1] as $index => $title) { $file = $matches[2][$index]; $structure[] = [ 'title' => $title, 'file' => str_replace('.md', '', $file), 'order' => $index + 1, ]; } return $structure; } }
API Reference
DocsPage Class
Core Methods
abstract class DocsPage extends Page { /** * Get the path to documentation files */ protected function getDocsPath(): string; /** * Get custom section ordering */ protected function getSectionOrder(string $filename): int; /** * Get custom section title */ protected function getSectionTitle(string $filename): string; /** * Load and process markdown content */ protected function loadContent(string $filename): string; /** * Perform search across documentation */ protected function search(string $query): array; /** * Get all available sections */ protected function getAllSections(): array; /** * Get cached content for performance */ protected function getCachedContent(string $filename): string; }
Customizable Properties
class DocsPage extends Page { // Navigation properties protected static ?string $navigationIcon = 'heroicon-o-book-open'; protected static ?string $navigationGroup = 'Documentation'; protected static ?string $navigationLabel = null; protected static ?int $navigationSort = null; // Page properties protected static ?string $title = 'Documentation'; protected static ?string $slug = null; // View properties protected static string $view = 'filament-docs::docs-page'; // Content properties protected bool $showSearchBox = true; protected bool $showTableOfContents = true; protected bool $showNavigationProgress = true; }
Configuration Options
Complete Configuration Schema
return [ // Core settings 'default_docs_path' => string, // Markdown processing 'markdown' => [ 'html_input' => 'allow|strip|escape', 'allow_unsafe_links' => boolean, 'max_nesting_level' => integer, 'extensions' => array, 'renderer' => array, ], // Search configuration 'search' => [ 'debounce_ms' => integer, 'max_results_per_section' => integer, 'max_total_results' => integer, 'highlight_class' => string, 'min_query_length' => integer, 'context_length' => integer, 'fuzzy_search' => boolean, 'index' => array, ], // UI customization 'ui' => [ 'dark_mode' => boolean, 'show_toc' => boolean, 'toc_min_headings' => integer, 'toc_max_depth' => integer, 'print_support' => boolean, 'classes' => array, 'typography' => array, ], // Performance settings 'performance' => [ 'cache_content' => boolean, 'cache_duration' => integer, 'lazy_loading' => boolean, 'preload_adjacent' => boolean, 'images' => array, ], // Security settings 'security' => [ 'allowed_html_tags' => array, 'csp' => array, 'uploads' => array, ], // Localization 'localization' => [ 'default_locale' => string, 'supported_locales' => array, 'locale_paths' => array, 'fallback_to_default' => boolean, 'date_format' => string, 'time_format' => string, ], ];
Events
Available Events
// Fired when documentation page is accessed DocumentationPageViewed::class; // Fired when documentation section is loaded DocumentationSectionLoaded::class; // Fired when search is performed DocumentationSearchPerformed::class; // Fired when documentation content is cached DocumentationContentCached::class;
Event Listeners
class DocumentationEventSubscriber { public function handlePageView(DocumentationPageViewed $event): void { // Log page view, update analytics, etc. } public function handleSearch(DocumentationSearchPerformed $event): void { // Log search queries, improve search algorithms, etc. } }
Testing
Running Tests
The package includes a comprehensive test suite to ensure reliability and stability:
# Run all tests composer test # Run tests with coverage composer test-coverage # Run specific test categories composer test -- --filter=DocumentationTest composer test -- --filter=SearchTest composer test -- --filter=SecurityTest
Test Categories
Unit Tests
- Markdown processing
- Search indexing
- Content caching
- Configuration validation
Feature Tests
- Page rendering
- Navigation functionality
- Search operations
- Access control
Integration Tests
- Filament panel integration
- Theme compatibility
- Performance benchmarks
- Browser compatibility
Writing Custom Tests
// tests/Feature/CustomDocumentationTest.php class CustomDocumentationTest extends TestCase { use RefreshDatabase; protected function setUp(): void { parent::setUp(); // Create test documentation files $this->createTestDocumentation(); } /** @test */ public function it_loads_custom_documentation() { $user = User::factory()->create(); $response = $this->actingAs($user) ->get('/admin/custom-docs'); $response->assertStatus(200) ->assertSee('Custom Documentation'); } private function createTestDocumentation(): void { $docsPath = resource_path('test-docs'); if (!is_dir($docsPath)) { mkdir($docsPath, 0755, true); } file_put_contents( "{$docsPath}/test-section.md", "# Test Section\n\nThis is test content." ); } }
Performance Benchmarks
Benchmark Results
Based on testing with different documentation sizes:
Documentation Size | Load Time | Search Time | Memory Usage |
---|---|---|---|
Small (< 50 pages) | < 100ms | < 50ms | < 10MB |
Medium (50-200 pages) | < 300ms | < 150ms | < 25MB |
Large (200-500 pages) | < 600ms | < 300ms | < 50MB |
Enterprise (500+ pages) | < 1200ms | < 500ms | < 100MB |
Results may vary based on server configuration and content complexity.
Optimization Recommendations
For Large Documentation Sets
-
Enable aggressive caching:
'performance' => [ 'cache_duration' => 86400, // 24 hours 'preload_adjacent' => true, 'lazy_loading' => true, ],
-
Use database caching for very large sites:
'cache_driver' => 'database', // or 'redis'
-
Implement content pagination:
'ui' => [ 'pagination' => [ 'enabled' => true, 'per_page' => 20, ], ],
For High-Traffic Sites
-
Use Redis for caching:
'cache_driver' => 'redis', 'search' => [ 'index' => [ 'cache_duration' => 86400, 'rebuild_on_change' => false, // Manual rebuilds ], ],
-
Enable CDN for assets:
'performance' => [ 'cdn_url' => 'https://cdn.example.com', 'assets_versioning' => true, ],
Roadmap & Future Features
Version 3.0 (Planned)
New Features
- Visual Editor: WYSIWYG editor for non-technical users
- Comment System: Collaborative documentation with inline comments
- Version Control: Built-in versioning with diff visualization
- AI Integration: AI-powered content suggestions and improvements
- Advanced Analytics: Detailed usage analytics and insights
Enhancements
- Improved Search: Semantic search with ML-powered relevance
- Better Mobile UX: Enhanced mobile experience and offline support
- Plugin System: Extensible architecture for custom functionality
- Multi-tenant Support: Documentation isolation for multi-tenant apps
Contributing to Development
We welcome contributions! Here's how you can help:
Ways to Contribute
- Bug Reports: Report issues with detailed reproduction steps
- Feature Requests: Suggest new features with use cases
- Code Contributions: Submit pull requests with improvements
- Documentation: Help improve documentation and examples
- Testing: Help test new features and report feedback
Development Setup
# Clone the repository git clone https://github.com/eightynine/filament-docs.git cd filament-docs # Install dependencies composer install npm install # Set up test environment cp .env.example .env.testing php artisan key:generate --env=testing # Run tests composer test # Build assets npm run build
Contribution Guidelines
- Follow PSR-12 coding standards
- Write tests for new features
- Update documentation for changes
- Use conventional commits for clear history
- Ensure compatibility with supported versions
Community & Support
Getting Help
Official Channels
- Documentation: This comprehensive guide
- GitHub Issues: Bug reports and feature requests
- GitHub Discussions: Questions and community help
- Discord Server: Real-time community chat (coming soon)
Community Resources
- Example Projects: Sample implementations and use cases
- Video Tutorials: Step-by-step video guides (coming soon)
- Blog Posts: Tips, tricks, and advanced techniques
- Community Packages: Extensions and add-ons
Professional Support
For enterprise customers and complex implementations:
- Consulting Services: Custom implementation assistance
- Priority Support: Fast response times for critical issues
- Training Sessions: Team training and best practices
- Custom Development: Tailored features and integrations
Contact: support@eightynine.dev
Acknowledgments
Core Contributors
- Eighty Nine - Lead Developer and Maintainer
- Community Contributors - Bug fixes, features, and documentation
Special Thanks
- Filament Team - For creating an amazing admin panel framework
- Laravel Community - For the robust foundation and ecosystem
- Open Source Contributors - For dependencies and inspiration
Powered By
- Laravel - The PHP framework for web artisans
- Filament - Elegant admin panels for Laravel
- CommonMark - Markdown parsing
- Alpine.js - Reactive frontend framework
- Tailwind CSS - Utility-first CSS framework
Changelog
Please see CHANGELOG for more information on what has changed recently.
Recent Updates
Version 2.1.0 (Latest)
- โจ Added advanced search with semantic indexing
- ๐จ Enhanced mobile responsive design
- โก Improved performance with better caching
- ๐ Enhanced security with content sanitization
- ๐ Expanded internationalization support
- ๐ฑ Added offline reading capabilities
- ๐ง New Artisan commands for content management
Version 2.0.0
- ๐ Complete rewrite with modern architecture
- ๐ฏ Improved API design and extensibility
- ๐ Added analytics and usage tracking
- ๐จ New customizable themes and layouts
- ๐ Advanced search with highlighting
- ๐ฑ Mobile-first responsive design
Contributing
We love contributions! Here's how you can help make Filament Docs even better:
Types of Contributions
- ๐ Bug Reports: Help us identify and fix issues
- ๐ก Feature Requests: Suggest new features and improvements
- ๐ Documentation: Improve guides, examples, and API docs
- ๐งช Testing: Help test new features and edge cases
- ๐ป Code: Submit pull requests with bug fixes and features
Contribution Process
- Fork the repository on GitHub
- Create a feature branch from
main
- Make your changes with tests and documentation
- Test your changes thoroughly
- Submit a pull request with a clear description
Development Guidelines
- Follow PSR-12 coding standards
- Write comprehensive tests for new features
- Update documentation for any changes
- Use conventional commits for clear history
- Ensure backward compatibility when possible
Please see CONTRIBUTING.md for detailed guidelines.
Security Vulnerabilities
Security is a top priority for Filament Docs. If you discover any security vulnerabilities, please report them responsibly:
Reporting Security Issues
- Email: security@eightynine.dev
- Encryption: Use our PGP key for sensitive information
- Response Time: We aim to respond within 24 hours
Security Best Practices
When using Filament Docs in production:
- Keep Updated: Always use the latest version
- Sanitize Content: Enable content sanitization features
- Access Control: Implement proper user permissions
- HTTPS Only: Use encrypted connections
- Regular Audits: Periodically review access logs
Please review our security policy for complete details.
License
The MIT License (MIT). Please see License File for more information.
License Summary
- โ Commercial Use: Use in commercial projects
- โ Modification: Modify the source code
- โ Distribution: Distribute original or modified versions
- โ Private Use: Use for private/internal projects
- โ ๏ธ Liability: No warranty or liability
- โ ๏ธ Trademark: No trademark rights included
Copyright Notice
Copyright (c) 2024 Eighty Nine
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Made with โค๏ธ by Eighty Nine
โญ Star on GitHub | ๐ Documentation | ๐ Report Bug | ๐ก Request Feature
Building better documentation experiences for Laravel and Filament