xoshbin / pertuk
A powerful Laravel documentation package with multi-language support, markdown processing, and beautiful UI
Fund package maintenance!
Requires
- php: ^8.4 || ^8.3
- illuminate/contracts: ^11.0||^12.0
- league/commonmark: ^2.0
- spatie/commonmark-shiki-highlighter: ^2.5
- spatie/laravel-package-tools: ^1.16
- spatie/shiki-php: ^2.3
- spatie/yaml-front-matter: ^2.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
README
Pertuk is a powerful Laravel documentation package that provides a complete documentation system with multi-language support, markdown processing, search functionality, and a beautiful, responsive UI.
Features
- ð Premium Markdown: Full CommonMark and GitHub Flavored Markdown support
- ðĻ Shiki Syntax Highlighting: Server-side, VS-Code quality syntax highlighting
- ð Multi-Language Support: Built-in support for multiple locales with RTL handling
- ðŠī Root Locale: Serve a primary language at the docs root with no URL prefix (VitePress/Starlight style)
- ðĒ Versioning Support: Explicit version configuration with a built-in version picker
- ð GitHub Source: Render docs directly from any GitHub repository
- ð Deep Local Search: Full-content indexing via MiniSearch with relevancy scoring
- ð§Đ Interactive Components: Built-in support for Tabs and Accordions in Markdown
- ðĻ Modern UI: Responsive design with interactive sidebar and dark mode
- ðą Mobile Friendly: Optimized for all device sizes
- ðïļ Auto Table of Contents: Automatic TOC generation from headings
- ðū Intelligent Caching: High-performance document rendering and caching
- ð§ Breadcrumbs: Automatic breadcrumb navigation
- ð·ïļ Front Matter Support: YAML front matter for metadata
- ðĄ Admonitions: Support for tip, warning, and danger callouts
- ð Pre-rendering: Artisan command to pre-render documentation for maximum speed
Quick Start
- Install the package:
composer require xoshbin/pertuk
- Publish the assets (JS and CSS):
php artisan vendor:publish --tag="pertuk-assets"
- (Optional) Publish the config:
php artisan vendor:publish --tag="pertuk-config"
-
Create your docs directory and add a markdown file.
-
Visit your docs at
/docs.
- Customization: Publish the views to customize the layout and markup:
php artisan vendor:publish --tag="pertuk-views"
- (Optional) Pre-render documentation for performance:
php artisan pertuk:build
Configuration
return [ // Root folder for documentation files (local source). 'root' => base_path('docs'), // Source driver: 'local' (default) or 'github'. 'source' => env('PERTUK_SOURCE', 'local'), // Per-driver configuration. 'sources' => [ 'local' => [ 'root' => env('PERTUK_DOCS_LOCAL_ROOT'), ], 'github' => [ 'repo' => env('PERTUK_DOCS_REPO'), 'branch' => env('PERTUK_DOCS_BRANCH', 'main'), 'path' => env('PERTUK_DOCS_PATH', 'docs'), 'token' => env('PERTUK_DOCS_TOKEN'), 'cache_path' => storage_path('app/pertuk/github'), ], ], // Locale configuration â mirrors VitePress/Starlight conventions. // The 'root' key designates the primary locale whose files live flat // at the docs root with no URL prefix. Secondary locales keep /{code}/. // Omit 'root' to use classic locale-prefixed mode (docs/en/, docs/ar/). 'locales' => [ 'root' => ['label' => 'English', 'lang' => 'en', 'dir' => 'ltr'], 'ar' => ['label' => 'Ø§ŲØđØąØĻŲØĐ', 'lang' => 'ar', 'dir' => 'rtl'], 'ckb' => ['label' => 'ÚĐŲØąØŊÛ (ØģÛØąØ§ŲÛ)', 'lang' => 'ckb', 'dir' => 'rtl'], ], // Explicit version list. Empty = no versioning. // e.g. ['v1.0', 'v2.0'] 'versions' => [], // Default sort order when front matter 'order' is missing. 'default_order' => 1000, // Excluded files or folders (relative to root) for file listing. 'exclude_directories' => [ '.DS_Store', 'README.md', ], // Cache TTL (seconds) for parsed HTML & metadata. 'cache_ttl' => 3600, // Enable or disable the documentation system. 'enabled' => true, // Route prefix for documentation. 'route_prefix' => 'docs', // Route name prefix. 'route_name_prefix' => 'pertuk.docs.', // Route middleware. 'middleware' => ['web'], // GitHub Repo & Branch for "Edit on GitHub" links. 'github_repo' => env('PERTUK_GITHUB_REPO', 'username/repo'), 'github_branch' => env('PERTUK_GITHUB_BRANCH', 'main'), 'github_path' => null, // Assets directory (relative to documentation root). 'assets_path' => 'assets', // External links. 'github_url' => env('PERTUK_GITHUB_URL', ''), 'discord_url' => env('PERTUK_DISCORD_URL', ''), ];
Directory Structures
Root locale (flat) â recommended for single-language or GitHub-sourced repos
Inspired by VitePress and Starlight. One locale is designated root in config â its files live directly at the docs root with no subdirectory or URL prefix. Secondary locales keep their /{code}/ prefix.
docs/
âââ explanation/
â âââ introduction.md â /docs/explanation/introduction
âââ how-to/
â âââ publishing.md â /docs/how-to/publishing
âââ tutorials/
â âââ quick-start.md â /docs/tutorials/quick-start
âââ ar/
âââ explanation/
âââ introduction.md â /docs/ar/explanation/introduction
Config:
'locales' => [ 'root' => ['label' => 'English', 'lang' => 'en', 'dir' => 'ltr'], 'ar' => ['label' => 'Ø§ŲØđØąØĻŲØĐ', 'lang' => 'ar', 'dir' => 'rtl'], ],
Classic locale-prefixed â all locales in subdirectories
Omit the root key. Every locale, including the primary one, lives in its own subdirectory. This is the legacy behaviour and continues to work unchanged.
docs/
âââ en/
â âââ getting-started.md â /docs/en/getting-started
âââ ar/
âââ getting-started.md â /docs/ar/getting-started
Config:
'locales' => [ 'en' => ['label' => 'English', 'lang' => 'en', 'dir' => 'ltr'], 'ar' => ['label' => 'Ø§ŲØđØąØĻŲØĐ', 'lang' => 'ar', 'dir' => 'rtl'], ],
Versioned structure
Add version directories above the locale layout. Declare versions explicitly in config â no automatic directory scanning.
docs/
âââ v1.0/
â âââ getting-started.md â /docs/v1.0/getting-started (root locale)
â âââ ar/
â âââ getting-started.md â /docs/v1.0/ar/getting-started
âââ v2.0/
âââ getting-started.md â /docs/v2.0/getting-started
Config:
'locales' => [ 'root' => ['label' => 'English', 'lang' => 'en', 'dir' => 'ltr'], 'ar' => ['label' => 'Ø§ŲØđØąØĻŲØĐ', 'lang' => 'ar', 'dir' => 'rtl'], ], 'versions' => ['v1.0', 'v2.0'],
Monolingual (single language, no locale UI)
Configure only a root locale with no secondary entries. The language picker is hidden automatically.
docs/
âââ getting-started.md â /docs/getting-started
âââ reference/
âââ api.md â /docs/reference/api
Config:
'locales' => [ 'root' => ['label' => 'English', 'lang' => 'en', 'dir' => 'ltr'], ], 'versions' => [],
GitHub Source
Pertuk can render markdown stored in a GitHub repository instead of the local filesystem. Set PERTUK_SOURCE=github and configure the repo, branch, and path. The package syncs the full directory tree into storage/app/pertuk/github/ during pertuk:build and falls back to on-demand single-file fetches at runtime.
PERTUK_SOURCE=github PERTUK_DOCS_REPO=Xoshbin/asyar-launcher PERTUK_DOCS_BRANCH=main PERTUK_DOCS_PATH=docs # Optional â required for private repos, recommended to avoid the 60/hr anonymous rate limit. PERTUK_DOCS_TOKEN=ghp_xxx
The GitHub source works with all directory structures above â including root locale (flat) layouts. Run php artisan pertuk:build as part of your deploy to sync changes.
Migrating from the old locale config
If you are upgrading from a version that used supported_locales, default_locale, rtl_locales, and locale_labels, replace them with the unified locales map. No files need to move if you omit the root key.
// Before 'supported_locales' => ['en', 'ar'], 'default_locale' => 'en', 'rtl_locales' => ['ar'], 'locale_labels' => ['en' => 'English', 'ar' => 'Ø§ŲØđØąØĻŲØĐ'], // After (classic prefix mode â no files to move) 'locales' => [ 'en' => ['label' => 'English', 'lang' => 'en', 'dir' => 'ltr'], 'ar' => ['label' => 'Ø§ŲØđØąØĻŲØĐ', 'lang' => 'ar', 'dir' => 'rtl'], ], 'versions' => [],
Also replace exclude_versions with an explicit versions array â list only the versions you want to expose.
If you published the vendor views (php artisan vendor:publish --tag="pertuk-views"), re-publish them to get the updated templates, or replace any route('pertuk.docs.show', ['locale' => ..., 'slug' => ...]) calls with \Xoshbin\Pertuk\Support\PertukUrl::doc($slug).
Front Matter
--- title: "Getting Started" order: 1 --- # Getting Started Your content here...
Interactive Components (Alpine.js)
Tabs
<x-pertuk-tabs> <x-pertuk-tab name="PHP"> ```php echo "Hello World";
console.log("Hello World");```
Accordion
<x-pertuk-accordion> <x-pertuk-accordion-item title="Can I customize the design?"> Yes! Publish the views to match your brand. </x-pertuk-accordion-item> </x-pertuk-accordion>
Admonitions
::: tip This is a helpful tip. ::: ::: warning Be careful with this setting. ::: ::: danger This action cannot be undone. :::
Assets & Images
Place images in an assets/ directory at the docs root and reference them with relative paths:

Pertuk rewrites these paths to /docs/assets/filename.png automatically.
Directory conflict warning: Do not create a physical public/docs directory. In Nginx, physical directories take precedence over Laravel routes, causing 403 Forbidden errors.
Performance
Pre-render all documentation to cache during deployment:
php artisan pertuk:build
Testing
composer test
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
License
The MIT License (MIT). Please see License File for more information.
