SEO & Discoverability
Keel exposes three discoverability endpoints at runtime: /sitemap.xml, /robots.txt, and /llms.txt.
They are generated from route registration and the shared docs registry, so there is no separate static file to maintain.
Mark a public page for sitemap inclusion
Router::get() supports an optional third argument for route options. Use ['sitemap' => true]
when registering a real public content page.
public function get(string $uri, callable|array $action, array $options = []): void
{
$this->addRoute('GET', $uri, $action, $options);
}
Example route registration from routes/web.php:
$router->get('/', [WelcomeController::class, 'index'], ['sitemap' => true]);
$router->get('/docs', [DocsController::class, 'index'], ['sitemap' => true]);
$router->get('/login', [AuthController::class, 'showLogin'], ['sitemap' => true]);
Once flagged, the page is returned by Router::publicPages(), and appears in /sitemap.xml
automatically with no extra file edits.
Runtime endpoints
$router->get('/sitemap.xml', [SitemapController::class, 'index']);
$router->get('/robots.txt', [RobotsController::class, 'index']);
$router->get('/llms.txt', [LlmsTxtController::class, 'index']);
SitemapControllerbuilds XML fromAPP_URL+Router::publicPages()+ expanded docs slugs.RobotsControllerbuildsDisallowprefixes from registered protected routes/middleware.LlmsTxtControlleroutputs docs links from the same shared docs registry used by the docs sidebar.
Important behavior notes
- Only explicitly flagged GET routes are sitemap-eligible.
- Parameterized docs routes are expanded to real slugs instead of emitting
/docs/{slug}. - Protected app routes (dashboard/settings/api/admin) are excluded from public discovery output.