> For the complete documentation index, see [llms.txt](https://docs.opensoutheners.com/oss/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opensoutheners.com/oss/laravel-apiable/documentation-generator/customising-stubs.md).

# Customising Stubs

Customise the Markdown templates used for documentation generation.

The Markdown exporter compiles its output from Blade templates called **stubs**. Two stubs ship with the package. You can publish them to your application and modify them freely — the command always prefers your published version over the package default.

## Publishing stubs

```bash
php artisan vendor:publish --tag=apiable-stubs
```

This copies the bundled stubs into your application:

```
stubs/
└── apiable/
    └── docs/
        ├── protocol.mdx   ← Tailwind Protocol MDX template
        └── plain.md       ← Plain Markdown template
```

## Stub resolution order

When the Markdown exporter runs it checks for a user-published stub **first**:

1. `{base_path}/stubs/apiable/docs/{stub}.{ext}` — your published stub (takes priority)
2. Package bundled stub — used when no published stub is found

If neither location has the requested stub, the command throws a `RuntimeException` with a hint to run `vendor:publish`.

{% hint style="info" %}
You only need to publish the stubs you want to customise. If you publish only `plain.md`, the `protocol` stub will continue to use the package version.
{% endhint %}

## Blade compilation

Stubs are compiled with **Laravel Blade**, so any Blade directive is available:

```blade
@foreach ($resource['endpoints'] as $endpoint)
    ## {{ $endpoint['title'] }}
    @if (!empty($endpoint['auth']))
    > Authentication required
    @endif
@endforeach
```

Each stub receives a single `$resource` variable — a plain PHP array with the complete data for one resource group.

## `$resource` array shape

```php
[
    // Human-readable group name (from #[DocumentedResource(name: '...')])
    'name' => 'Posts',

    // Group description (from #[DocumentedResource(description: '...')])
    'description' => 'Manage blog posts',

    // Fully-qualified Eloquent model class, or null if #[EndpointResource] is absent
    'modelClass' => 'App\\Models\\Post',

    // Array of endpoint arrays (one per documented controller action)
    'endpoints' => [
        [
            // Route URI without leading slash
            'uri' => 'posts',

            // HTTP method in uppercase
            'method' => 'GET',

            // Endpoint title (from #[DocumentedEndpointSection(title: '...')] or PHPDoc)
            'title' => 'List Posts',

            // Endpoint description (from attribute or PHPDoc first paragraph)
            'description' => 'Returns a paginated list of published posts.',

            // Auth scheme detected from middleware, or null for unauthenticated routes
            'auth' => [
                'type'       => 'bearer',        // 'bearer' or 'basic'
                'middleware' => 'auth:sanctum',  // the matched middleware name
            ],

            // Query parameters collected from *QueryParam attributes
            'queryParams' => [
                [
                    // Full query string key as it appears in the URL
                    'key'         => 'filter[title][like]',

                    // Param kind: filter | sort | include | fields | appends | search
                    'kind'        => 'filter',

                    // Description from the attribute's $description parameter
                    'description' => 'Filter by title (partial match)',

                    // Comma-separated allowed values, or '*' for any value
                    'values'      => '*',

                    // Whether the parameter is required (always false for query params)
                    'required'    => false,
                ],
                [
                    'key'         => 'sort',
                    'kind'        => 'sort',
                    'description' => 'Sort by creation date',
                    'values'      => 'created_at,-created_at',
                    'required'    => false,
                ],
                [
                    'key'         => 'include',
                    'kind'        => 'include',
                    'description' => 'Include related resources',
                    'values'      => 'tags,author',
                    'required'    => false,
                ],
                [
                    'key'         => 'fields[post]',
                    'kind'        => 'fields',
                    'description' => 'Sparse fieldset for posts',
                    'values'      => 'title,body,published_at',
                    'required'    => false,
                ],
                [
                    'key'         => 'appends[post]',
                    'kind'        => 'appends',
                    'description' => 'Append computed reading time',
                    'values'      => 'reading_time',
                    'required'    => false,
                ],
            ],
        ],
    ],
]
```

## Example: minimal plain stub

```blade
# {{ $resource['name'] }}

{{ $resource['description'] }}

@foreach ($resource['endpoints'] as $endpoint)

---

## {{ $endpoint['title'] }}

@if (!empty($endpoint['auth']))
> **Requires authentication** ({{ $endpoint['auth']['type'] }})
@endif

{{ $endpoint['description'] }}

`{{ $endpoint['method'] }}` `/{{ $endpoint['uri'] }}`

@if (!empty($endpoint['queryParams']))
| Parameter | Description |
|-----------|-------------|
@foreach ($endpoint['queryParams'] as $param)
| `{{ $param['key'] }}` | {{ $param['description'] ?: '—' }} |
@endforeach
@endif

@endforeach
```

{% hint style="warning" %}
After modifying a stub run `php artisan apiable:docs` to regenerate your documentation files. Blade views compiled from stubs are not cached between runs — the exporter passes `deleteCachedView: true` to `Blade::render()`.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.opensoutheners.com/oss/laravel-apiable/documentation-generator/customising-stubs.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
