knuckleswtf/scribe
Generate human-friendly API docs from your Laravel codebase. Scribe outputs a sleek single-page HTML doc with code samples and “Try It Out”, plus Postman collections and OpenAPI specs. It can extract params from validation/FormRequests and auto-generate sample responses.
Installation:
composer require knuckleswtf/scribe
Publish the configuration:
php artisan vendor:publish --provider="Knuckles\Scribe\ScribeServiceProvider" --tag="scribe-config"
First Run: Generate documentation by running:
php artisan scribe:generate
Access the generated HTML at storage/app/public/scribe/index.html (or your configured output path).
First Use Case:
Base URL: Configure in config/scribe.php:
'base_url' => env('SCRIBE_URL', 'http://localhost:8000'),
Supports Blade syntax (e.g., {{ config('app.url') }}).
Output Path: Defaults to storage/app/public/scribe. Customize via:
'output_path' => storage_path('app/public/scribe'),
Generate Docs:
php artisan scribe:generate
View Docs:
php artisan serve
http://localhost:8000/scribe/index.html.Iterate:
Route Extraction: Scribe automatically discovers all Laravel routes (web, API, and controller-based) and generates documentation for each endpoint.
GET /api/users route will appear in the docs with:
Request/Response Handling:
Form Requests: Extract validation rules and map them to OpenAPI schemas.
// app/Http/Requests/StoreUserRequest.php
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
];
}
Scribe converts these to OpenAPI required: true and type: string fields.
API Resources:
Automatically infers response schemas from Illuminate\Http\Resources\Json\JsonResource:
// app/Http/Resources/UserResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
];
}
Manual Overrides: Use attributes to customize documentation:
use Knuckles\Scribe\Attributes\Group;
use Knuckles\Scribe\Attributes\Deprecated;
#[Group('Users')]
#[Deprecated('Use /api/v2/users instead')]
public function index()
{
// ...
}
Grouping Endpoints:
Use the #[Group] attribute to organize endpoints into logical sections:
#[Group('Admin')]
public function adminDashboard()
{
// ...
}
Adding Descriptions:
Use #[Description] to add markdown-formatted descriptions:
use Knuckles\Scribe\Attributes\Description;
#[Description('Retrieves a paginated list of users. Supports filtering by `role` and `status`.')]
public function index()
{
// ...
}
Custom Examples:
Override example responses via the #[Example] attribute:
use Knuckles\Scribe\Attributes\Example;
#[Example(
status: 200,
body: ['message' => 'User created successfully']
)]
public function store()
{
// ...
}
Authentication:
Scribe supports documenting authenticated endpoints. Configure in config/scribe.php:
'auth' => [
'headers' => [
'Authorization' => 'Bearer {token}',
],
],
Use the #[Auth] attribute to mark endpoints requiring auth:
use Knuckles\Scribe\Attributes\Auth;
#[Auth]
public function sensitiveData()
{
// ...
}
Webhooks:
Document webhook endpoints with #[Webhook]:
use Knuckles\Scribe\Attributes\Webhook;
#[Webhook]
public function handleStripeWebhook()
{
// ...
}
Custom Strategies: Extend Scribe’s behavior by creating custom strategies (e.g., for non-standard request handling):
// app/Scribe/CustomRequestStrategy.php
namespace App\Scribe;
use Knuckles\Scribe\Extractors\Attributes\BodyParam;
use Knuckles\Scribe\Extractors\RequestExtractor;
class CustomRequestStrategy extends RequestExtractor
{
public function extract(): array
{
// Custom logic here
return [];
}
}
Register the strategy in config/scribe.php:
'strategies' => [
\App\Scribe\CustomRequestStrategy::class,
],
Automated Documentation Updates: Add a step to your CI pipeline (e.g., GitHub Actions) to regenerate docs on every push:
# .github/workflows/docs.yml
name: Generate API Docs
on: [push]
jobs:
generate-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- run: composer install -n --prefer-dist
- run: php artisan scribe:generate
- uses: actions/upload-artifact@v3
with:
name: api-docs
path: storage/app/public/scribe/
Deploying Documentation:
Deploy the generated scribe folder to a static hosting service (e.g., Netlify, Vercel) or serve it via your Laravel app.
Local Development:
php artisan scribe:generate --watch
(Watches for route/controller changes and regenerates docs.)Testing:
Collaboration:
storage/app/public/scribe/index.html file with teammates or clients.storage/app/public/scribe/openapi.json) for integration testing.Maintenance:
#[Deprecated] and mark them in the UI.Problem: Scribe misses certain routes (e.g., named routes or dynamic routes).
Solution:
routes/api.php or routes/web.php.Route::get('/users/{user}', [UserController::class, 'show'])->name('users.show');
Debugging:
Run php artisan route:list to verify routes are registered. Use the --verbose flag to check middleware and namespaces.
#[BodyParam]/#[QueryParam] for explicit documentation:
use Knuckles\Scribe\Attributes\BodyParam;
#[BodyParam(name: 'user', type: 'object', attributes: [
new BodyParam(name: 'name', type: 'string', description: 'User name'),
new BodyParam(name: 'roles', type: 'array', description: 'User roles', attributes: [
new BodyParam(name: 'role', type: 'string'),
]),
])]
public function store(Request $request)
{
// ...
}
How can I help you explore Laravel packages today?