# Content Routing

Configure docsLoader, docsSchema, docsBase, slugs, and generated routes.

import { FileTree } from '@prosefly/astro-components';

Dahlia routes are built from two inputs:

- The content collection entry IDs produced by `docsLoader`
- The public route prefix configured with `docsBase`

Keep routing decisions here. Locale directories and UI translation behavior are
covered in [Internationalization](/docs/configuration/i18n/).

## Collection Setup

The default loader reads MDX files from `src/content/docs`:

```ts
import { defineCollection } from 'astro:content';
import { docsLoader, docsSchema } from '@prosefly/astro-theme-dahlia/content';

const docs = defineCollection({
  loader: docsLoader(),
  schema: docsSchema(),
});

export const collections = { docs };
```

Without i18n, `src/content/docs/installation.mdx` has the entry ID
`installation`, and `src/content/docs/references/configuration.mdx` has the
entry ID `references/configuration`.

<FileTree>

- src
  - content
    - docs
      - index.mdx `/`
      - installation.mdx `/installation/`
      - references
        - configuration.mdx `/references/configuration/`

</FileTree>

For localized docs, `locales.*.directory` is relative to `src/content/docs`.
It strips the locale directory before Dahlia matches sidebar string items and
autogenerated directories. See
[Internationalization](/docs/configuration/i18n/#directory-mapping).

## Custom Loader Base

`docsLoader()` defaults to `src/content/docs`, but it still accepts `base` when
you intentionally want a different collection root.

```ts
const docs = defineCollection({
  loader: docsLoader({
    base: './src/content',
  }),
  schema: docsSchema(),
});
```

With this setup, `src/content/docs/en/installation.mdx` has the entry ID
`docs/en/installation`, while `src/content/index.mdx` has the entry ID `index`.
For most sites, keep the default loader and create non-docs pages with Astro's
normal `src/pages` routing.

## Docs Base

`docsBase` controls where Dahlia injects the page, Markdown, and search routes.
The default is `/`, matching Starlight's route model: `src/content/docs` is the
content collection root, not a public URL prefix.

With the default `docsBase: '/'` and the default loader:

| Entry ID | Page URL | Markdown URL |
| --- | --- | --- |
| `index` | `/` | `/index.md` |
| `installation` | `/installation/` | `/installation.md` |
| `references/configuration` | `/references/configuration/` | `/references/configuration.md` |

The search index follows the same base. With the default route base, it is
available at `/search.json`.

Set `docsBase` when the project also has a marketing site, app routes, or other
pages outside the documentation.

```json title="theme.config.json"
{
  "docsBase": "/docs"
}
```

With `docsBase: '/docs'` and the default loader:

| Entry ID | Page URL | Markdown URL |
| --- | --- | --- |
| `index` | `/docs/` | `/docs/index.md` |
| `installation` | `/docs/installation/` | `/docs/installation.md` |
| `references/configuration` | `/docs/references/configuration/` | `/docs/references/configuration.md` |

The prefixed search index is `/docs/search.json`.

## LLMs Files

Dahlia generates `/llms.txt` by default. It lists the default locale docs as
Markdown links, grouped by sidebar section.

Disable the route with:

```json title="theme.config.json"
{
  "llms": false
}
```

Generate a full-text companion at `/llms-full.txt` with:

```json title="theme.config.json"
{
  "llms": {
    "full": true
  }
}
```

`/llms.txt` and `/llms-full.txt` are site-level discovery files, so they do not
move under `docsBase`.

## Site Homepage

The docs collection `index` entry always renders at the current `docsBase`.
With the default `docsBase: '/'`, `src/content/docs/index.mdx` is the site
homepage. With `docsBase: '/docs'`, the same entry renders at `/docs/`.

For a custom marketing homepage, keep the site homepage outside the docs
collection and create it with Astro's normal file-based routing.

<FileTree iconSet="vscode-icons">

- src/
  - pages/
    - index.astro          -> /
  - content/
    - docs/
      - index.mdx          -> /docs/
      - installation.mdx   -> /docs/installation/

</FileTree>

You can reuse Dahlia page primitives on custom pages:

```astro
---
import {
  BaseLayout,
  PageSection,
  SiteFooter,
  SiteHeader,
} from '@prosefly/astro-theme-dahlia/layouts';
---

<BaseLayout title="Home">
  <SiteHeader currentPath="/" />
  <main>
    <PageSection>
      <h1>Product documentation</h1>
    </PageSection>
  </main>
  <SiteFooter />
</BaseLayout>
```

For a docs-only site, keep the default `docsBase: '/'` and put the docs
homepage at `src/content/docs/index.mdx`.

<FileTree>

- src
  - content
    - docs
      - index.mdx docs homepage at `/`
      - installation.mdx `/installation/`

</FileTree>

## Slug Overrides

Use frontmatter `slug` when a page needs a public path that differs from its
entry ID:

```md
---
title: CLI Reference
slug: reference/cli
---
```

With `docsBase: '/docs'`, that page renders at `/docs/reference/cli/` and
`/docs/reference/cli.md`.

Slug overrides affect public URLs. Sidebar ownership still depends on entry IDs,
so `docsNav` should reference the content entry, not the slug override.

## Schema Extensions

Use `docsSchema({ extend })` when a project needs additional frontmatter fields:

```ts
import { z } from 'astro/zod';

const docs = defineCollection({
  loader: docsLoader(),
  schema: docsSchema({
    extend: z.object({
      product: z.string().optional(),
    }),
  }),
});
```

The extension is merged into the base Dahlia docs schema. Existing Dahlia fields
such as `title`, `sidebar`, `tableOfContents`, `template`, `pagefind`, and
`draft` remain available.
