Serve VitePress documentation in your Laravel application with full middleware support, authentication, and role-based access control.
- π 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
- PHP 8.1+
- Laravel 10.x, 11.x, or 12.x
- Node.js 20+ (for building documentation)
| PHP | Laravel 10 | Laravel 11 | Laravel 12 |
|---|---|---|---|
| 8.1 | β | β | β |
| 8.2 | β | β | β |
| 8.3 | β | β | β |
| 8.4 | β | β | β |
| 8.5 | β | β | β |
Install the package via Composer:
composer require laravel-ready/laravel-vitepressRun the installation command:
php artisan vitepress:installThis 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.
// config/vitepress.php
return [
'route' => [
'prefix' => 'docs', // Access at /docs
'middleware' => ['web'],
],
];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.
Require users to be logged in:
'auth' => [
'enabled' => true,
'middleware' => ['auth'],
],Works with spatie/laravel-permission (optional):
'auth' => [
'enabled' => true,
'middleware' => ['auth'],
'roles' => ['admin', 'developer'],
],'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.
Serve documentation from a subdomain:
'route' => [
'domain' => 'docs.example.com',
'prefix' => '',
],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',
],After installation, your documentation is available at:
https://your-app.com/docsuse 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');@if(VitePress::isEnabled() && VitePress::canAccess())
<a href="{{ VitePress::getRouteUrl() }}">Documentation</a>
@endifTo customize the documentation:
php artisan vitepress:publish --stubsThis will publish VitePress source files to resources/docs/.
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.
After making changes, rebuild:
php artisan vitepress:buildJust update your .env file:
VITEPRESS_ROUTE_PREFIX=documentationThen rebuild:
php artisan vitepress:buildThe base URL is automatically read from your .env file - no need to pass environment variables manually.
# 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| Command | Description |
|---|---|
vitepress:install |
Install the package (publishes config and assets) |
vitepress:publish |
Publish specific resources |
vitepress:build |
Build VitePress documentation |
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=3600Add security or custom headers:
'options' => [
'headers' => [
'X-Frame-Options' => 'SAMEORIGIN',
'X-Content-Type-Options' => 'nosniff',
],
],'options' => [
'custom_404' => 'errors.docs-404',
],Enable CORS for API documentation:
'options' => [
'cors_enabled' => true,
],The package includes SPA fallback routing by default. Disable it for traditional page routing:
'options' => [
'spa_fallback' => false,
],composer testPlease see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.