Laravel Quick Start

Get started with Bytedocs in Laravel applications

Bytedocs for Laravel provides seamless integration with your Laravel application, including K6 performance testing - a feature unique to the Laravel implementation.

Installation

Install via Composer:

composer require idnexacloud/laravel-bytedocs

Run the install command to auto-setup everything:

php artisan bytedocs:install

This will:

  • Publish config file to config/bytedocs.php
  • Publish assets (CSS/JS) to public/bytedocs/
  • Add all ByteDocs environment variables to your .env

That's it! Visit http://localhost:8000/docs and your documentation is ready.

Manual Setup (Alternative)

The package auto-registers and works out of the box with zero configuration. Just install and visit /docs.

Want to customize? Add to your .env:

BYTEDOCS_TITLE="My Laravel API"
BYTEDOCS_VERSION="1.0.0"
BYTEDOCS_DESCRIPTION="My awesome Laravel API"

Or publish the config for advanced customization:

php artisan vendor:publish --provider="ByteDocs\Laravel\ByteDocsServiceProvider" --tag="bytedocs-config"

Auto-Detection

Bytedocs automatically detects:

Routes

// routes/api.php
Route::get('/users/{id}', [UserController::class, 'show']);
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);

All routes are automatically discovered and documented.

FormRequest Validation

class StoreUserRequest extends FormRequest
{
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'age' => 'required|integer|min:0|max:150',
        ];
    }
}

class UserController extends Controller
{
    public function store(StoreUserRequest $request)
    {
        // Bytedocs automatically documents:
        // - All fields from rules()
        // - Required/optional status
        // - Validation rules (min, max, email, etc.)
        // - Types (string, integer, email, etc.)
    }
}

Eloquent Models

class User extends Model
{
    protected $fillable = ['name', 'email', 'age'];
    protected $hidden = ['password'];
    protected $casts = [
        'email_verified_at' => 'datetime',
        'age' => 'integer',
    ];
}

class UserController extends Controller
{
    public function show($id)
    {
        return User::find($id);
        // Bytedocs automatically detects User model structure
    }
}

Resource Responses

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at->toDateTimeString(),
        ];
    }
}

class UserController extends Controller
{
    public function index()
    {
        return UserResource::collection(User::all());
        // Automatically documented with correct schema
    }
}

Configuration

Basic Configuration

Edit config/bytedocs.php:

return [
    'title' => env('BYTEDOCS_TITLE', 'API Documentation'),
    'version' => env('BYTEDOCS_VERSION', '1.0.0'),
    'description' => env('BYTEDOCS_DESCRIPTION', ''),
    'docs_path' => env('BYTEDOCS_DOCS_PATH', '/docs'),
    'auto_detect' => env('BYTEDOCS_AUTO_DETECT', true),
];

Multiple Environments

'base_urls' => [
    [
        'name' => 'Production',
        'url' => env('BYTEDOCS_PRODUCTION_URL', 'https://api.example.com'),
    ],
    [
        'name' => 'Staging',
        'url' => env('BYTEDOCS_STAGING_URL', 'https://staging.example.com'),
    ],
    [
        'name' => 'Local',
        'url' => env('BYTEDOCS_LOCAL_URL', 'http://localhost:8000'),
    ],
],

Authentication

'auth' => [
    'enabled' => env('BYTEDOCS_AUTH_ENABLED', false),
    'type' => env('BYTEDOCS_AUTH_TYPE', 'session'), // session, basic, api_key
    'username' => env('BYTEDOCS_AUTH_USERNAME', 'admin'),
    'password' => env('BYTEDOCS_AUTH_PASSWORD', 'secret'),
    'session_expire' => env('BYTEDOCS_AUTH_SESSION_EXPIRE', 1440), // minutes
],

Exclude Routes

'exclude_paths' => [
    '_ignition',
    'telescope',
    'horizon',
    'sanctum/csrf-cookie',
    'api/health',
],

K6 Performance Testing

Laravel is the only implementation with built-in K6 integration!

Prerequisites

Install K6:

# macOS
brew install k6

# Linux
sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6

# Windows
choco install k6

Running Performance Tests

  1. Via UI: Navigate to any endpoint in /docs
  2. Click "Performance Test" button
  3. Configure test parameters:
    • Virtual Users (VUs)
    • Duration
    • Ramp-up stages
  4. Run and view results

Test Configuration

'k6' => [
    'enabled' => env('BYTEDOCS_K6_ENABLED', true),
    'path' => env('BYTEDOCS_K6_PATH', null), // Auto-detect if null
    'default_vus' => env('BYTEDOCS_K6_DEFAULT_VUS', 10),
    'default_duration' => env('BYTEDOCS_K6_DEFAULT_DURATION', '30s'),
],

Example K6 Test

// Generated by Bytedocs
import http from 'k6/http';
import { sleep, check } from 'k6';

export const options = {
    vus: 10,
    duration: '30s',
    stages: [
        { duration: '10s', target: 10 },
        { duration: '10s', target: 20 },
        { duration: '10s', target: 0 },
    ],
};

export default function() {
    const res = http.get('http://localhost:8000/api/users');

    check(res, {
        'status is 200': (r) => r.status === 200,
        'response time < 500ms': (r) => r.timings.duration < 500,
    });

    sleep(1);
}

Interpreting Results

After test execution, you'll see:

  • Total Requests: Number of requests made
  • Failure Rate: Percentage of failed requests
  • Avg Response Time: Average response duration
  • Max VUs: Peak virtual users
  • Data Transferred: Total data sent/received
  • Duration Percentiles: P95, P99 response times

Artisan Commands

Generate Documentation

php artisan bytedocs:generate

Generates fresh documentation JSON file.

Clear Cache

php artisan bytedocs:clear

Clears documentation cache.

Show Routes

php artisan bytedocs:routes

Lists all detected routes.

Best Practices

1. Use FormRequests

class StorePostRequest extends FormRequest
{
    public function rules()
    {
        return [
            'title' => 'required|string|max:255',
            'content' => 'required|string',
            'published_at' => 'nullable|date',
            'tags' => 'array',
            'tags.*' => 'string',
        ];
    }

    public function messages()
    {
        return [
            'title.required' => 'Post title is required',
            'content.required' => 'Post content cannot be empty',
        ];
    }
}

2. Use API Resources

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'content' => $this->content,
            'author' => new UserResource($this->whenLoaded('author')),
            'tags' => TagResource::collection($this->whenLoaded('tags')),
            'published_at' => $this->published_at?->toDateTimeString(),
            'created_at' => $this->created_at->toDateTimeString(),
        ];
    }
}

3. Add DocBlocks

class UserController extends Controller
{
    /**
     * Get all users
     *
     * Returns a paginated list of all users in the system.
     *
     * @response UserResource[]
     */
    public function index()
    {
        return UserResource::collection(User::paginate());
    }

    /**
     * Create a new user
     *
     * Creates a new user account with the provided information.
     *
     * @param StoreUserRequest $request
     * @response 201 UserResource
     */
    public function store(StoreUserRequest $request)
    {
        $user = User::create($request->validated());
        return new UserResource($user);
    }
}

4. Use Route Groups

Route::prefix('api/v1')->group(function () {
    Route::middleware('auth:sanctum')->group(function () {
        Route::apiResource('users', UserController::class);
        Route::apiResource('posts', PostController::class);
    });
});

Middleware Integration

Custom Middleware

// app/Http/Middleware/ByteDocsAuth.php
class ByteDocsAuth
{
    public function handle($request, Closure $next)
    {
        if ($request->is('docs*')) {
            // Custom authentication logic
            if (!$this->isAuthorized($request)) {
                abort(403);
            }
        }

        return $next($request);
    }
}

Register Middleware

// app/Http/Kernel.php
protected $middlewareGroups = [
    'web' => [
        // ...
        \App\Http\Middleware\ByteDocsAuth::class,
    ],
];

Troubleshooting

Routes Not Appearing

  1. Clear route cache: php artisan route:clear
  2. Clear config cache: php artisan config:clear
  3. Regenerate docs: php artisan bytedocs:generate

K6 Not Found

  1. Verify installation: k6 version
  2. Specify path in config: 'k6' => ['path' => '/usr/local/bin/k6']
  3. Check PATH: Ensure k6 is in system PATH

Performance Issues

  1. Cache documentation: Set 'cache' => true in config
  2. Exclude unnecessary routes: Add to exclude_paths
  3. Disable auto-detect in production: Set 'auto_detect' => false

What's Next?