Skip to content
Docent Docs

Getting Started

Share links

Hand one page to someone who isn't signed in, without opening the rest of a gated site.

Gated documentation gets in the way at the moment it matters most. You answer a support ticket with a link to the page that explains the problem, and the recipient lands on a login screen. Or a sales conversation turns on one feature, and the person asking has no account at all.

A share link solves that one case without unpicking your gates. Someone you trust copies a link to a single page, and it opens for whoever has it.

text
https://example.com/docs/billing/invoices?s=fyeQ7mPv9LeKd2

Turning it on

Share links stay off until you enable them and say who may create them:

php
'share' => [
    'enabled' => true,
    'gate' => 'shareDocentPage',
],

The gate is checked with Gate::allows, and an undefined gate answers false for everyone. Leaving it undefined means nobody can create a link, which is the right way for this to fail:

php
Gate::define('shareDocentPage', fn (User $user) => $user->isStaff());

Anyone who passes it gets a share button in the top bar, with the link and a choice of how long it should last. Everyone else sees no button.

What the recipient gets

Who opens the link decides what they see.

A reader who is signed in gets their normal page: full navigation, search, their own :::can blocks, their own resolved values. The token does nothing for them. A link is often sent precisely so a colleague can see something as themselves, so it never downgrades someone who could already read the page.

A reader who is not signed in gets the page on its own, centred, with no navigation, no search, and no assistant. A line at the bottom offers to sign in for everything else, pointing at your login route when you have one.

If the link has expired, or someone has edited the URL, they get your usual login redirect instead, exactly as if they had typed the address themselves.

A shared page answers every authorization question the way it would for a logged-out visitor, whoever created the link. Beyond that, Docent runs none of your registered code on a share request at all. {{ value: }} and {{ link: }} tokens render their registered label, so a reader sees {Account plan} where a signed-in colleague would see Team Plan. <docs-component> blocks render nothing. :::when and :::audience conditions are treated as unsatisfied, and :::can blocks resolve as they would for a guest.

So a share link cannot carry account data, and a resolver you wrote for a signed-in viewer never runs against a reader who has no account. It also means there is nothing to review before you send one, which is why the share panel asks you to confirm nothing.

The cost is that a page built around dynamic values reads thinly once shared. Pages explaining how something works travel well. Pages showing someone their own data do not.

Pages you can't share

A page gated with authorize or audience fails that check as a guest, so its share link returns your denied response rather than the page. That is the gate doing its job: a share token stands in for signing in, not for permission.

The share button still appears on those pages, so it is possible to copy a link that won't open for the person you send it to. Gating the site with route middleware and leaving individual pages ungated avoids the situation entirely.

The token is fourteen characters, carries its own expiry, and is signed against the page's path, so editing the URL to point somewhere else invalidates it. Nothing is stored and there is no table to migrate.

php
'share' => [
    'ttl' => 30,
    'max_ttl' => 90,
    'salt' => env('DOCENT_SHARE_SALT'),
],

ttl is the lifetime offered by default and max_ttl the longest anyone may choose. Changing salt invalidates every outstanding link at once, which is what to reach for if one ends up somewhere you didn't intend.

Docent rate limits requests carrying a token that fails to verify. Requests carrying a working one cost nothing against that limit, so a page full of images still loads normally.

Images and stylesheets

Nothing becomes public. The token satisfies your guard for the shared page and for that page's images, uploads, and stylesheet, each signed for its own path. Everything else refuses it however valid it is: search, the assistant, insights, the widget, llms.txt, the sitemap, and the whole admin panel.

Links inside a shared page still lead to your login wall, which is usually what you want. The recipient reads the page you sent them and is invited to sign in for the rest.

Shared pages carry noindex, nofollow and never appear in the sitemap, so opening one page to a customer doesn't open it to a search engine.

Your existing configuration

Docent places its own middleware ahead of your guard, wherever you wrote auth, so nothing about your route entry changes:

php
'route' => [
    'prefix' => 'docs',
    'middleware' => ['web', 'auth'],
],

The credential stands in for authentication and for nothing else. A can: middleware below your guard still runs, and can still refuse a share request.

If your application authenticates with something that is neither Laravel's auth middleware nor a subclass of it, name that class so Docent knows what it is standing in for:

php
'share' => [
    'before' => App\Http\Middleware\EnsureTenantMember::class,
],

Watching what gets read

Shared reads are recorded under their own surface in insights, so you can see that a link has been opened four hundred times.