Skip to content
Docent Docs

Getting Started

Configuration

How config/docent.php is organized: sites, shared defaults, and the options you're most likely to change.

Everything about Docent is configured in config/docent.php, published by the installer. The file has two layers. A sites array holds one entry per documentation site, and the top level holds shared defaults that every site inherits. Most applications run a single site, the shipped docs entry, and never think about the second layer. The defaults are production ready, so this page sticks to the options you're most likely to change.

Sites and shared defaults

php
return [
    'default' => 'docs',

    // Shared defaults, inherited by every site.
    'authorization' => [...],
    'search' => [...],
    'theme' => [...],

    'sites' => [
        'docs' => [
            'name' => env('DOCENT_NAME', config('app.name').' Docs'),
            'route' => ['prefix' => 'docs', 'middleware' => ['web']],
            'filesystem' => ['path' => null],
            // ...
        ],
    ],
];

A value resolves in three steps: the site's own entry wins, then the top-level shared value, then the package default. The shared sections are theme, search, ai, insights, content, database, cache, authorization, widget, and seo. Set them once at the top level, and override any of them inside a site entry when one site needs to differ.

The rest never cascade, because they define what a site is: name, description, route, filesystem, admin, navigation, and layouts only take effect inside a site entry.

default names the site used when nothing more specific applies: the widget without a site attribute, and console output outside a request. It must match a key in sites.

Running one documentation site? Everything below happens inside sites.docs or at the shared top level, and you can ignore the machinery. When you want a second site, say public help plus internal admin docs, read multiple sites.

Site name

php
'sites' => [
    'docs' => [
        'name' => env('DOCENT_NAME', config('app.name').' Docs'),
        'description' => env('DOCENT_DESCRIPTION'),
    ],
],

The name shown in the title bar and header. It defaults to your application name with "Docs" tacked on; set DOCENT_NAME to override it. The optional description summarizes the site in its llms.txt file. When it is omitted, Docent writes a neutral description from the site name.

Route

php
// inside sites.docs
'route' => [
    'prefix' => 'docs',
    'domain' => null,
    'middleware' => ['web'],
],

The site is served under prefix (and an optional domain), guarded by middleware. Want the whole site behind authentication? Add auth:

php
'middleware' => ['web', 'auth'],

Now every docs URL runs through your app's auth middleware before Docent renders anything. Combine this with per-page access control for finer-grained rules.

Route names carry the site key: the reader routes for the docs site are docent.docs.home and docent.docs.show, and the same pattern holds for any site you add. Use the keyed names anywhere your application links into the docs.

Filesystem

php
// inside sites.docs
'filesystem' => [
    'path' => null,
],

Where the Markdown lives. For the shipped docs site, null resolves to resource_path('docs'). Point it somewhere else if your docs live outside the default location. Any other site you add must set its path explicitly; docent:check reports a site without one.

Authorization

php
'authorization' => [
    'denied_response' => 404,
],

Shared across sites, overridable per site. This controls what a denied viewer gets when a page's authorize or audience front matter excludes them. The default 404 hides the page's existence entirely. Set 403 to acknowledge the page but forbid it, or use a redirect string to send viewers somewhere else:

php
'denied_response' => 'redirect:/login',

Content

php
'content' => [
    'allow_html' => true,
],

Whether raw HTML authored in repository Markdown is emitted. Repository content is app code that goes through code review, so this defaults to true. Shared across sites.

Rendering

php
'render' => [
    'strict_tokens' => false,
],

How a registered value or link closure that throws is handled. The default substitutes nothing, reports the exception, and lets the rest of the page render, so one closure failing for one reader's session state doesn't cost them the whole document. Set it to true to get the exception instead. Shared across sites, overridable per site. See dynamic content.

php
'share' => [
    'enabled' => false,
    'gate' => 'shareDocentPage',
    'salt' => env('DOCENT_SHARE_SALT'),
    'ttl' => 30,
    'max_ttl' => 90,
    'throttle' => '60,1',
    'login_url' => null,
    'before' => Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
],

Lets a viewer who passes gate hand one page to someone who isn't signed in. Off until you enable it, and gate answers false for everyone until you define it, so nobody can create a link by accident.

ttl is the lifetime offered by default and max_ttl the longest anyone may pick, both in days. Changing salt invalidates every outstanding link. throttle applies only to requests carrying a token that fails to verify, in Laravel's attempts,minutes form. login_url points the "sign in for everything else" line at a specific address; left null it uses your login route, and offers nothing when you have none. before names the middleware the token stands in for, which only needs changing if your guard is neither Laravel's auth nor a subclass of it.

Shared across sites, overridable per site. See share links.

php
'search' => [
    'enabled' => true,
],

Toggles the ⌘K search palette and the _search endpoint. Search runs on the server and respects permissions: results pass through the same authorization as pages, and conditional block content is never indexed. Each site indexes and searches only its own corpus.

Search is ranked rather than exact. Titles and section headings carry the most weight, followed by descriptions, optional keywords, and page text. Docent also ignores common filler words, accepts a partial final word while someone is typing, and tolerates a one-character typo in longer terms. That means a query like "how do I insert a video" can still find a guide that says "embed a video." No external search service or AI provider is involved.

Docent ships with a conservative English stop-word list. Replace it when your help center uses another language, or empty it when every word should count:

php
'search' => [
    'enabled' => true,
    'stop_words' => [],
],

A site whose documentation uses a different language than the rest can override search.stop_words in its own entry. Authors can cover the last bit of vocabulary drift with page-level search.keywords. Keywords influence ranking without being shown to readers or included in snippets.

Use navigation.links for a few destinations people should always be able to reach from the sidebar and mobile menu. Navigation belongs to a site, so this block lives inside the site entry:

php
// inside sites.docs
'navigation' => [
    'default_section' => 'Documentation',
    'links' => [
        ['label' => 'Support', 'icon' => 'lifebuoy', 'url' => 'https://example.com/support'],
        ['label' => 'Setup guide', 'icon' => 'rocket-launch', 'page' => 'getting-started/setup'],
        ['label' => 'Admin console', 'icon' => 'wrench', 'route' => 'admin.dashboard', 'can' => 'admin'],
    ],
    'topbar' => [
        ['label' => 'GitHub', 'icon' => 'github', 'url' => 'https://github.com/acme/acme'],
    ],
],

Each link takes exactly one of url, page, or route. Add can to show it only when the viewer passes that ability. Page links also inherit the page's authorize and audience rules, and they stay inside the compact help widget. External links open in a new tab. Icons may be bundled Heroicon names or public image URLs; an invalid icon is simply omitted and reported by docent:check.

navigation.topbar takes the same link shape but renders as icon buttons on the right side of the top bar, next to the theme toggle. That's the spot readers expect a repository or community link, so Docent bundles a few brand icons alongside the Heroicons: github, discord, slack, x-twitter, and youtube. On phones these move into the navigation drawer with their labels. Top-bar links never appear in the help widget.

Pinned links are navigation aids for people, so they aren't included in llms.txt or other Markdown feeds. See organization for splitting a larger help center into top-level sections.

Cache

php
'cache' => [
    'store' => null,
    'prefix' => 'docent',
],

The store used for parsed ASTs, the navigation skeleton, and the search index. null uses your default cache store. Each site keeps its own cache namespace under this prefix. After any content change, clear it:

bash
php artisan docent:clear

docent:clear bumps a version stamp that's folded into every cache key, so it works with any cache driver, even ones without tag support. On a multi-site install it clears every site; pass --site=docs to clear one.

Theme

The entire theme section gets its own page. See theming for the accent color, logos, fonts, gray palette, and corner radius.