# Pages and URLs

In a collection loaded with minidocs’ `glob`, every file is a page. This page covers how files become page ids and URLs, and where the route files that render them go.

## Page ids

A page id is the file’s path relative to the `base` of `glob`, without the extension. An `index` file stands for its directory:

| File                 | Page id          |
| -------------------- | ---------------- |
| `index.mdx`          | `index`          |
| `hello.mdx`          | `hello`          |
| `guides/index.mdx`   | `guides`         |
| `guides/sidebar.mdx` | `guides/sidebar` |

Wherever a page id is expected, such as `page()` in the document tree or `toHref()` below, it is autocompleted, and a wrong id is a type error.

### Directories in parentheses

Directories with names in parentheses, such as `(basics)`, only organize files and are left out of page ids:

| File                        | Page id        |
| --------------------------- | -------------- |
| `(start)/index.mdx`         | `index`        |
| `(start)/install.mdx`       | `install`      |
| `guides/(basics)/links.mdx` | `guides/links` |

### Multilingual sites

With `i18n` set in your Astro config, the first level of directories in a collection is the locale, such as `zh/hello.mdx` and `en/hello.mdx`. Page ids leave the locale out, so both are `hello`.

### Leaving pages out

Leave out pages you don’t want to publish, such as drafts, with the `filter` option of `glob`:

```ts
glob({
  base: './src/content/docs',
  pattern: '**/*.{md,mdx}',
  prefix: 'docs',
  filter: (entry) => !entry.data.draft,
});
```

`filter` receives entries of the collection after the schema has parsed them, so `entry.data` is the frontmatter. Pages it leaves out never enter the collection: their ids are not autocompleted, and links to them fail the build. To preview drafts in the dev server and leave them out of builds, write `import.meta.env.DEV || !entry.data.draft`.

> [!WARNING]
> **Leave pages out in filter, not after getCollection**
>
> `getCollection('docs').filter(...)` only changes the entries you get back, while types and link checks still treat those pages as existing.

## URLs

A page’s URL has three parts: the locale, the collection’s `prefix` and the page id. With `prefix` set to `docs`:

| Page id          | URL                     | `en` on a multilingual site |
| ---------------- | ----------------------- | --------------------------- |
| `index`          | `/docs/`                | `/en/docs/`                 |
| `hello`          | `/docs/hello/`          | `/en/docs/hello/`           |
| `guides/sidebar` | `/docs/guides/sidebar/` | `/en/docs/guides/sidebar/`  |

Without `prefix`, pages sit at the root of the site. On a multilingual site, the locale segment follows the `i18n` setting in your Astro config, and the default locale usually has none. `base` and trailing slashes follow your Astro config too.

To get a page’s URL in code, use `toHref`:

```ts
toHref('docs', 'guides/sidebar'); // '/docs/guides/sidebar/'
toHref('docs', 'guides/sidebar', 'en'); // multilingual sites pass the locale
```

The first argument is the collection name. To link to another page in your content, write its file path, see [Links in Content](/en/docs/guides/links.md).

## Route files

The route file that renders a collection goes in the folder its `prefix` names, so files mirror URLs:

| Site            | Route file                                   |
| --------------- | -------------------------------------------- |
| Single-language | `src/pages/docs/[...slug].astro`             |
| Multilingual    | `src/pages/[...locale]/docs/[...slug].astro` |

Every page from `listPages` carries its route parameters as `page.params`, ready for `getStaticPaths`:

```ts
export function getStaticPaths() {
  return pages.map((page) => ({ params: page.params, props: page }));
}
```

The parameters are `{ slug }` on single-language sites and `{ locale, slug }` on multilingual sites. The `slug` of the collection’s home page (`index`) is `undefined`, and so is the `locale` of the default locale when it has no locale segment.

If the route file is not in the folder `prefix` names, pages are generated at the wrong URLs. The build fails and lists the pages that were not generated.
