# Content Routing

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

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

Lotus 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-lotus/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/components/icon.mdx` has the entry ID
`components/icon`.

<FileTree>

- src
  - content
    - docs
      - index.mdx `/`
      - installation.mdx `/installation/`
      - components
        - icon.mdx `/components/icon/`

</FileTree>

For localized docs, `locales.*.directory` is relative to `src/content/docs`.
It strips the locale directory before Lotus 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 Lotus 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` |
| `components/icon` | `/components/icon/` | `/components/icon.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.

```ts
export default defineLotusConfig({
  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` |
| `components/icon` | `/docs/components/icon/` | `/docs/components/icon.md` |

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

## 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.

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

You can reuse Lotus page primitives on custom pages:

```astro
---
import {
  BaseLayout,
  PageSection,
  SiteFooter,
  SiteHeader,
} from '@prosefly/astro-theme-lotus/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`.

```txt
src/content/
  docs/
    index.mdx            -> /
    installation.mdx     -> /installation/
```

<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 `sidebars` 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 Lotus docs schema. Existing Lotus fields
such as `title`, `sidebar`, `tableOfContents`, `template`, `pagefind`, and
`draft` remain available.
