laravel-vitepress maintained by laravel-ready
Laravel VitePress
Serve VitePress documentation in your Laravel application with full middleware support, authentication, and role-based access control.
✨ Features
- 🚀 Pre-built VitePress documentation (no build step required in production)
- 🔐 Laravel authentication and authorization integration
- 🛡️ Middleware support for route protection
- 👥 Role and permission-based access control (compatible with Spatie Laravel Permission)
- ⚙️ Fully configurable routing
- 📦 Easy installation and publishing
- 🎨 Customizable views and layouts
- 🔒 Path traversal protection
- 🔐 Protected storage by default (docs stored outside
public/to enforce auth) - 💾 Cache control headers
- 🌐 Multi-domain support
📋 Requirements
- PHP 8.1+
- Laravel 10.x, 11.x, or 12.x
- Node.js 20+ (for building documentation)
📊 Support Matrix
| PHP | Laravel 10 | Laravel 11 | Laravel 12 |
|---|---|---|---|
| 8.1 | ✅ | ❌ | ❌ |
| 8.2 | ✅ | ✅ | ❌ |
| 8.3 | ✅ | ✅ | ✅ |
| 8.4 | ✅ | ✅ | ✅ |
| 8.5 | ❌ | ❌ | ✅ |
📦 Installation
Install the package via Composer:
composer require laravel-ready/laravel-vitepress
Run the installation command:
php artisan vitepress:install
This will publish:
- Configuration file to
config/vitepress.php - Pre-built documentation assets to
storage/app/vitepress/docs(protected by default)
Visit /docs in your browser to see your documentation.
⚙️ Configuration
Basic Setup
// config/vitepress.php
return [
'route' => [
'prefix' => 'docs', // Access at /docs
'middleware' => ['web'],
],
];
Storage Location
By default, documentation is stored in storage/ to prevent direct file access and ensure authentication is enforced. For public documentation without auth, you can store in public/:
'assets' => [
// 'storage' = protected (default), 'public' = directly accessible
'storage' => 'storage',
'path' => 'vitepress/docs',
],
Important: If you use authentication (auth.enabled = true), keep storage set to 'storage'. Otherwise users can bypass auth by accessing files directly at /vitepress/docs/index.html.
With Authentication
Require users to be logged in:
'auth' => [
'enabled' => true,
'middleware' => ['auth'],
],
With Role-Based Access
Works with spatie/laravel-permission (optional):
'auth' => [
'enabled' => true,
'middleware' => ['auth'],
'roles' => ['admin', 'developer'],
],
With Permission-Based Access
'auth' => [
'enabled' => true,
'middleware' => ['auth'],
'permissions' => ['view-documentation'],
],
Note: Role and permission checks use
hasAnyRole()andhasAnyPermission()methods from Spatie Laravel Permission. If the package is not installed, these checks are automatically skipped. The package works without Spatie - you can use basic auth or custom gates instead.
Custom Domain
Serve documentation from a subdomain:
'route' => [
'domain' => 'docs.example.com',
'prefix' => '',
],
Custom Gate
Define a custom gate for complex authorization:
// In AuthServiceProvider
Gate::define('view-documentation', function ($user) {
return $user->hasActiveSubscription();
});
// config/vitepress.php
'auth' => [
'enabled' => true,
'gate' => 'view-documentation',
],
🚀 Usage
Accessing Documentation
After installation, your documentation is available at:
https://your-app.com/docs
Using the Facade
use LaravelReady\VitePress\Facades\VitePress;
// Check if VitePress is enabled
if (VitePress::isEnabled()) {
// ...
}
// Get the documentation URL
$url = VitePress::getRouteUrl();
// Check if current user can access docs
if (VitePress::canAccess()) {
// Show documentation link
}
// Get configuration
$config = VitePress::getConfig();
$prefix = VitePress::getConfig('route.prefix');
In Blade Templates
@if(VitePress::isEnabled() && VitePress::canAccess())
<a href="{{ VitePress::getRouteUrl() }}">Documentation</a>
@endif
🎨 Customization
Publishing VitePress Source
To customize the documentation:
php artisan vitepress:publish --stubs
This will publish VitePress source files to resources/docs/.
Configuration Files
The VitePress config is split into two files:
| File | Purpose | Editable? |
|---|---|---|
.vitepress/config.mts |
Package-managed (base URL, dotenv) | No |
.vitepress/config.docs.mts |
Your customizations (title, nav, sidebar) | Yes |
Edit config.docs.mts to customize your documentation. Don't edit config.mts - it contains package logic that reads from your .env file.
Building Documentation
After making changes, rebuild:
php artisan vitepress:build
Changing Route Prefix
Just update your .env file:
VITEPRESS_ROUTE_PREFIX=documentation
Then rebuild:
php artisan vitepress:build
The base URL is automatically read from your .env file - no need to pass environment variables manually.
Publishing Other Resources
# Publish configuration only
php artisan vitepress:publish --config
# Publish assets only
php artisan vitepress:publish --assets
# Publish views only
php artisan vitepress:publish --views
# Publish everything
php artisan vitepress:publish --all
# Publish everything (force overwrite, useful when package needs updating etc.)
php artisan vitepress:publish --all --force
🛠️ Artisan Commands
| Command | Description |
|---|---|
vitepress:install |
Install the package (publishes config and assets) |
vitepress:publish |
Publish specific resources |
vitepress:build |
Build VitePress documentation |
🔧 Environment Variables
VITEPRESS_ENABLED=true
VITEPRESS_ROUTE_PREFIX=docs
VITEPRESS_DOMAIN=
VITEPRESS_AUTH_ENABLED=false
VITEPRESS_ALLOWED_ROLES=admin,developer
VITEPRESS_ALLOWED_PERMISSIONS=view-docs
VITEPRESS_GATE=
VITEPRESS_STORAGE=storage
VITEPRESS_ASSETS_PATH=vitepress/docs
VITEPRESS_CACHE_ENABLED=true
VITEPRESS_CACHE_MAX_AGE=3600
🔬 Advanced Usage
Custom Headers
Add security or custom headers:
'options' => [
'headers' => [
'X-Frame-Options' => 'SAMEORIGIN',
'X-Content-Type-Options' => 'nosniff',
],
],
Custom 404 Page
'options' => [
'custom_404' => 'errors.docs-404',
],
CORS Support
Enable CORS for API documentation:
'options' => [
'cors_enabled' => true,
],
SPA Fallback
The package includes SPA fallback routing by default. Disable it for traditional page routing:
'options' => [
'spa_fallback' => false,
],
🧪 Testing
composer test
📝 Changelog
Please see CHANGELOG for more information on what has changed recently.
🤝 Contributing
Please see CONTRIBUTING for details.