Skip to content

Commit 1dc4ce0

Browse files
authored
Migrate to Astro 5 content layer API (#1687)
Fixes: #1611 Following https://docs.astro.build/en/guides/upgrade-to/v5/#updating-existing-collections, changes of the same type are grouped into commits - turn off legacy.collections and define `src/content.config.ts`. Previously we were getting the content config autogenerated by directory. This is technically still available as a deprecated feature, but it wouldn't work for us anyway because it only globs on md/mdx files ``` Auto-generating collections for folders in "src/content/" that are not defined as collections. This is deprecated, so you should define these collections yourself in "src/content.config.ts". The following collections have been auto-generated: blog, community, download, explore, landing, landing-features, learning-manuals, menus, research, sponsors, teams ``` ``` 08:35:29 [WARN] [glob-loader] No files found matching "**/*{.md,.mdx},!**/_*/**/*{.md,.mdx},!**/_*{.md,.mdx}" in directory "src/content/community" 08:35:29 [WARN] [glob-loader] No files found matching "**/*{.md,.mdx},!**/_*/**/*{.md,.mdx},!**/_*{.md,.mdx}" in directory "src/content/explore" 08:35:29 [WARN] [glob-loader] No files found matching "**/*{.md,.mdx},!**/_*/**/*{.md,.mdx},!**/_*{.md,.mdx}" in directory "src/content/landing" 08:35:29 [WARN] [glob-loader] No files found matching "**/*{.md,.mdx},!**/_*/**/*{.md,.mdx},!**/_*{.md,.mdx}" in directory "src/content/menus" 08:35:29 [WARN] [glob-loader] No files found matching "**/*{.md,.mdx},!**/_*/**/*{.md,.mdx},!**/_*{.md,.mdx}" in directory "src/content/sponsors" 08:35:29 [WARN] [glob-loader] No files found matching "**/*{.md,.mdx},!**/_*/**/*{.md,.mdx},!**/_*{.md,.mdx}" in directory "src/content/research" ``` - replace slug with id. Did not do the same for `src/pages/community/teams/[...slug].astro` because it wasn't strictly necessary and the example in the migration guide has an example with `[slug]` in the filename getting populated from a collection entry in `getStaticPaths` - Switch to the new render() function. > Entries no longer have a render() method, as they are now serializable plain objects. Instead, import the render() function from astro:content. - Manually sort collections when necessary. Previously we were relying on collection entries being sorted lexicographically from the directory, but this behavior has now changed. Except for blog entries which are already being sorted by date, we explicitly sort lexicographically (using [`localeCompare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) because [array sort wants a comparator function that returns negative, 0 or positive to indicate order](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) > Sort order of generated collections is non-deterministic and platform-dependent. This means that if you are calling getCollection(), the order in which entries are returned may be different than before. If you need a specific order, you must sort the collection entries yourself. --------- Co-authored-by: Albert Chae <[email protected]>
1 parent c0b1510 commit 1dc4ce0

File tree

12 files changed

+100
-32
lines changed

12 files changed

+100
-32
lines changed

astro.config.mjs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ export default defineConfig({
2626
start_url: "/",
2727
}
2828
})],
29-
legacy: {
30-
collections: true, // TODO: migrate to Content Layer API
31-
},
3229
markdown: {
3330
shikiConfig: {
3431
theme: syntaxTheme,

src/components/pages/blog/BlogListEntry.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const { post } = Astro.props;
55
---
66

77
<article
8-
data-category={post.slug.split('/')[0]}
8+
data-category={post.id.split('/')[0]}
99
class="font-light"
1010
aria-hidden="false"
1111
>

src/components/pages/download/DownloadAccordion.astro

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
---
2-
import { getCollection } from 'astro:content';
2+
import { getCollection, render } from 'astro:content';
33
44
const { family = 'nix' } = Astro.props;
55
const accordionId = `download-${family}-accordion`;
66
7-
let downloadOptions = (await getCollection('download')).filter(
8-
(option) => option.data.family === family,
9-
);
7+
let downloadOptions = (await getCollection('download'))
8+
.sort((a, b) => a.id.localeCompare(b.id))
9+
.filter((option) => option.data.family === family);
1010
---
1111

1212
<div id={accordionId} class="download-accordion">
1313
<div class="download-accordion-menu">
1414
{
1515
downloadOptions.map(async (option) => {
16-
const { Content } = await option.render();
16+
const { Content } = await render(option);
1717
const needsInstallInfix =
1818
option.data.family === 'nix' && option.data.platform !== 'more';
1919
const optionId = `${option.data.family}-${needsInstallInfix ? 'install-' : ''}${option.data.platform}`;

src/content.config.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { defineCollection, z } from 'astro:content';
2+
import { glob } from 'astro/loaders';
3+
4+
const blog = defineCollection({
5+
loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: './src/content/blog' }),
6+
});
7+
8+
const community = defineCollection({
9+
loader: glob({ pattern: '**/[^_]*.yaml', base: './src/content/community' }),
10+
});
11+
12+
const download = defineCollection({
13+
loader: glob({
14+
pattern: '**/[^_]*.{md,mdx}',
15+
base: './src/content/download',
16+
}),
17+
});
18+
19+
const explore = defineCollection({
20+
loader: glob({ pattern: '**/[^_]*.yaml', base: './src/content/explore' }),
21+
});
22+
23+
const landing = defineCollection({
24+
loader: glob({ pattern: '**/[^_]*.yaml', base: './src/content/landing' }),
25+
});
26+
27+
const landingFeatures = defineCollection({
28+
loader: glob({
29+
pattern: '**/[^_]*.{md,mdx}',
30+
base: './src/content/landing-features',
31+
}),
32+
});
33+
34+
const learningManuals = defineCollection({
35+
loader: glob({
36+
pattern: '**/[^_]*.{md,mdx}',
37+
base: './src/content/learning-manuals',
38+
}),
39+
});
40+
41+
const menus = defineCollection({
42+
loader: glob({ pattern: '**/[^_]*.yaml', base: './src/content/menus' }),
43+
});
44+
45+
// TODO get `research` from astro collection instead of hardcoded json
46+
47+
const sponsors = defineCollection({
48+
loader: glob({ pattern: '**/[^_]*.yaml', base: './src/content/sponsors' }),
49+
});
50+
51+
const teams = defineCollection({
52+
loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: './src/content/teams' }),
53+
});
54+
55+
export const collections = {
56+
blog,
57+
community,
58+
download,
59+
explore,
60+
landing,
61+
landingFeatures,
62+
learningManuals,
63+
menus,
64+
sponsors,
65+
teams,
66+
};

src/lib/utils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import MarkdownIt from 'markdown-it';
33
export function generatePathFromPost(post, attachBlog = true) {
44
const postDate = new Date(post.data.date);
55
return `/${attachBlog ? 'blog/' : ''}${
6-
post.slug.split('/')[0] +
6+
post.id.split('/')[0] +
77
'/' +
88
postDate.getFullYear() +
99
'/' +
10-
post.slug.split('/').pop().split('_').pop()
10+
post.id.split('/').pop().split('_').pop()
1111
}`;
1212
}
1313

src/pages/blog/[category].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export async function getStaticPaths() {
1010
const blogEntries = await getCollection('blog');
1111
1212
const filteredEntries = blogEntries.reduce((groups, entry) => {
13-
const category = entry.slug.split('/')[0];
13+
const category = entry.id.split('/')[0];
1414
if (!groups[category]) {
1515
groups[category] = {
1616
params: {

src/pages/blog/[category]/[year].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export async function getStaticPaths() {
1010
const blogEntries = await getCollection('blog');
1111
1212
const filteredEntries = blogEntries.reduce((groups, entry) => {
13-
const category = entry.slug.split('/')[0];
13+
const category = entry.id.split('/')[0];
1414
const postYear = new Date(entry.data.date).getFullYear();
1515
if (!groups[category + postYear]) {
1616
groups[category + postYear] = {

src/pages/blog/[category]/[year]/[id].astro

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
import { getCollection } from 'astro:content';
2+
import { getCollection, render } from 'astro:content';
33
import Container from '../../../../components/layout/Container.astro';
44
import PageHeader from '../../../../components/layout/PageHeader.astro';
55
import Layout from '../../../../layouts/Layout.astro';
@@ -8,16 +8,16 @@ export async function getStaticPaths() {
88
const blogEntries = await getCollection('blog');
99
return blogEntries.map((entry) => ({
1010
params: {
11-
category: entry.slug.split('/')[0],
11+
category: entry.id.split('/')[0],
1212
year: new Date(entry.data.date).getFullYear(),
13-
id: entry.slug.split('/').pop().split('_').pop(),
13+
id: entry.id.split('/').pop().split('_').pop(),
1414
},
1515
props: { entry },
1616
}));
1717
}
1818
1919
const { entry } = Astro.props;
20-
const { Content } = await entry.render();
20+
const { Content } = await render(entry);
2121
---
2222

2323
<Layout title=`${entry.data.title} | Blog`>

src/pages/community.astro

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import Layout from '../layouts/Layout.astro';
1616
const meetups = await getEntry('community', 'meetups');
1717
const teams = await getCollection('teams');
1818
19+
teams.sort((a, b) => a.id.localeCompare(b.id));
20+
1921
const nixcons = [
2022
{
2123
title: 'NixCon 2024 - Berlin',
@@ -422,7 +424,7 @@ import nixosFoundationLogo from '../assets/image/nixos-foundation-logo.svg';
422424
teams.map((team) => (
423425
<li class="flex grow basis-72 flex-col items-center gap-2 text-center text-white md:items-start md:text-left [&>a]:inline-block">
424426
<img
425-
src={`/images/teams/${team.slug.split('_')[1]}.svg`}
427+
src={`/images/teams/${team.id.split('_')[1]}.svg`}
426428
alt={`${team.data.name} Logo`}
427429
class="h-24"
428430
/>
@@ -432,7 +434,7 @@ import nixosFoundationLogo from '../assets/image/nixos-foundation-logo.svg';
432434
</p>
433435
<Button
434436
color="green"
435-
href={'/community/teams/' + team.slug.split('_')[1]}
437+
href={'/community/teams/' + team.id.split('_')[1]}
436438
>
437439
Read more
438440
</Button>
@@ -461,9 +463,7 @@ import nixosFoundationLogo from '../assets/image/nixos-foundation-logo.svg';
461463
<ul class="mx-auto mt-2 list-disc pl-8 md:w-72 md:pl-10">
462464
{
463465
teams
464-
.filter(
465-
(team) => team.slug.split('_')[1] === 'foundation-board',
466-
)[0]
466+
.find((team) => team.id.split('_')[1] === 'foundation-board')
467467
.data.members.map((member) => (
468468
<li class="mb-1">
469469
{member.name}

src/pages/community/teams/[...slug].astro

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
import { getCollection } from 'astro:content';
2+
import { getCollection, render } from 'astro:content';
33
44
import Container from '../../../components/layout/Container.astro';
55
import PageHeader from '../../../components/layout/PageHeader.astro';
@@ -9,13 +9,13 @@ import Layout from '../../../layouts/Layout.astro';
99
export async function getStaticPaths() {
1010
const teamEntries = await getCollection('teams');
1111
return teamEntries.map((entry) => ({
12-
params: { slug: entry.slug.split('_')[1] },
12+
params: { slug: entry.id.split('_')[1] },
1313
props: { entry },
1414
}));
1515
}
1616
1717
const { entry } = Astro.props;
18-
const { Content } = await entry.render();
18+
const { Content } = await render(entry);
1919
---
2020

2121
<Layout title={entry.data.name}>

0 commit comments

Comments
 (0)