Skip to content

Commit

Permalink
[Content Collections] update to new slug changes (#2435)
Browse files Browse the repository at this point in the history
* update to new slug changes

* Update src/pages/en/guides/content-collections.mdx

Co-authored-by: Sarah Rainsberger <[email protected]>

Co-authored-by: Sarah Rainsberger <[email protected]>
  • Loading branch information
FredKSchott and sarah11918 authored Jan 23, 2023
1 parent fbccd92 commit f796771
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 63 deletions.
63 changes: 9 additions & 54 deletions src/pages/en/guides/content-collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -236,20 +236,16 @@ defineCollection({

Every content entry generates a URL-friendly `slug` property from its file `id`. The slug is used to query the entry directly from your collection. It is also useful when creating new pages and URLs from your content.

To customize the generated `slug` value, you can manually override Astro's default behavior by providing a `slug()` function in `defineCollection()`. Whatever value you return from this function will be used as the new `slug` property for each entry.
You can override an entry's generated slug by adding your own `slug` property to the file frontmatter. This is similar to the "permalink" feature of other web frameworks. `"slug"` is a special, reserved property name that is not allowed in your custom collection `schema` and will not appear in your entry's `data` property.

```ts {4-6}
// Example: Override the default entry slug with a custom value.
const blogCollection = defineCollection({
slug: ({ id, defaultSlug }) => {
return myCustomSlugProcessor(id) || defaultSlug;
},
});
```md {3}
---
title: My Blog Post
slug: my-custom-slug/supports/slashes
---
Your blog post content here.
```

For performance reasons, the `slug()` function does not have access to your content's body or frontmatter data. If you need these values to generate your slug, you should do that directly inside the `src/pages` Astro component responsible for rendering your content. See [Generating custom routes](#generating-custom-routes) for more details.


## Querying Collections

Astro provides two functions to query a collection and return one (or more) content entries: [`getCollection()`](/en/reference/api-reference/#getcollection) and [`getEntryBySlug()`](/en/reference/api-reference/#getentrybyslug).
Expand Down Expand Up @@ -349,9 +345,9 @@ const { Content, headings } = await entry.render();

## Generating Routes from Content

Because content collections live outside of the `src/pages/` directory, it's up to you to create [dynamic routes](/en/core-concepts/routing/#dynamic-routes) that will render your content and any collection entries to HTML.
Content collections are stored outside of the `src/pages/` directory. You will need to create a new [dynamic route](/en/core-concepts/routing/#dynamic-routes) to generate HTML pages from your collection entries. Your dynamic route will map the incoming request param (ex: `Astro.params.slug` in `src/pages/blog/[slug].astro`) to fetch the correct entry inside a collection.

The way that you generate routes in Astro depends on your build [`output`](/en/reference/configuration-reference/#output) mode: 'static' (the default) or 'server' (for SSR).
The exact method for generating routes will depend on your build [`output`](/en/reference/configuration-reference/#output) mode: 'static' (the default) or 'server' (for SSR).

### Building for static output (default)

Expand Down Expand Up @@ -400,47 +396,6 @@ const { Content } = await entry.render();
<Content />
```

### Generating custom routes

The `slug()` function in `defineCollection()` lets you customize how a content entry `slug` value is created. However, this function does not have access to any frontmatter.

You can still create custom URLs from your content frontmatter inside the `getStaticPaths()` function, when building for static output. For example, to create a custom URL for each blog post based on its `permalink` frontmatter property, you could do the following:

```astro "entry.data.permalink"
---
// src/pages/posts/[slug].astro
// 1. Query the collection and generate a new path for each entry,
// based on its "permalink" frontmatter property.
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.data.permalink || entry.data.slug },
props: { entry },
}));
}
// 2. When its time to render, you can get the entry directly from the prop.
const { entry } = Astro.props;
---
```

If you are building for server output (SSR), you would do a similar lookup of the entire collection on every request to find your matching entry. However this is not recommended for large collections, where loading the entire collection on every request may slow down your page response time.

```astro "entry.data.permalink"
---
// src/pages/posts/[slug].astro
import { getEntryBySlug } from 'astro:content';
// 1. Get the slug from the incoming server request
const { slug } = Astro.params;
// 2. Query and filter the entire collection
const blogEntries = await getCollection('blog', (entry) => {
return (entry.data.permalink || entry.slug) === slug;
});
// 3. (Optional) render the entry to HTML in the template
const { Content } = await entry.render();
---
<h1>{entry.data.title}</h1>
<Content />
```

## Modifying Frontmatter with Remark

Expand Down
11 changes: 2 additions & 9 deletions src/pages/en/reference/api-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,6 @@ const blog = defineCollection({
title: z.string(),
permalink: z.string().optional(),
}),
slug({ id, data, defaultSlug, body }) {
return data.permalink ?? defaultSlug;
}
});

// Expose your defined collection to Astro
Expand All @@ -738,13 +735,9 @@ This function accepts the following properties:

**Type:** `TSchema extends ZodType`

`schema` is an optional Zod object to configure the type and shape of document frontmatter for a collection. Each object value must use [a Zod validator](https://github.com/colinhacks/zod).

#### `slug()`

**Type:** `(entry: { defaultSlug: string } & Omit<CollectionEntry, 'slug'>) => string | undefined`
`schema` is an optional Zod object to configure the type and shape of document frontmatter for a collection. Each value must use [a Zod validator](https://github.com/colinhacks/zod).

`slug()` is an optional function to override the default entry slug generated by Astro. This function receives the `defaultSlug`, entry `id`, unparsed document `body`, and `data` parsed by your configured schema, if any.
[See the `Content Collection` guide](/en/guides/content-collections/#defining-a-collection-schema) for example usage.

### `getCollection()`

Expand Down

0 comments on commit f796771

Please sign in to comment.