Skip to content

Commit 7ed75db

Browse files
authored
Merge pull request #13 from nemanjam/feature/content-layer
Content layer migration
2 parents 70298d2 + 8c23dbd commit 7ed75db

File tree

12 files changed

+68
-29
lines changed

12 files changed

+68
-29
lines changed

astro.config.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ export default defineConfig({
2121
site: SITE_URL,
2222
trailingSlash: 'ignore',
2323
env: envSchema,
24-
legacy: {
25-
collections: true,
26-
},
2724
// default
2825
compressHTML: true,
2926
server: { port: 3000 },

docs/working-notes/todo4.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,9 @@ astro v5
2828

2929
migrate gallery to astro components
3030
migrate content collections to content layer, restructure folder with slug to contain images
31+
------------
32+
// content layer
33+
git checkout -b feature/content-layer
3134

35+
id, slug, decoupled with my custom type Post[], Project[], from CollectionEntry<T>
3236
```

src/constants/collections.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import { DEFAULT_METADATA } from '@/constants/metadata';
33
import DefaultPostHeroImage from '@/assets/images/default/default-post-hero-image.jpg';
44
import DefaultProjectHeroImage from '@/assets/images/default/default-project-hero-image.jpg';
55

6+
export const BASE_FOLDERS = {
7+
POST: 'src/content/post',
8+
PROJECT: 'src/content/project',
9+
} as const;
10+
611
export const COLLECTIONS = {
712
POST: 'post',
813
PROJECT: 'project',

src/content/config.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import { defineCollection } from 'astro:content';
2+
import { glob } from 'astro/loaders';
23

3-
import { postSchema } from '../schemas/post';
4-
import { projectSchema } from '../schemas/project';
4+
import { postSchema } from '@/schemas/post';
5+
import { projectSchema } from '@/schemas/project';
6+
import { BASE_FOLDERS } from '@/constants/collections';
7+
8+
const { POST, PROJECT } = BASE_FOLDERS;
59

610
export const postCollection = defineCollection({
11+
loader: glob({ pattern: '**/*.mdx', base: POST }),
712
schema: postSchema,
8-
type: 'content',
913
});
1014

1115
export const projectCollection = defineCollection({
16+
loader: glob({ pattern: '**/*.mdx', base: PROJECT }),
1217
schema: projectSchema,
13-
type: 'content',
1418
});
1519

1620
// _schemas folder in collections will be included in type

src/modules/common.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,10 @@ export const getPublishedOrUpdatedDate = ({
6565

6666
return result;
6767
};
68+
69+
/*------------------------- for content layer -----------------------*/
70+
71+
export const idToSlug = <T extends { id: unknown }>(item: T): T & { slug: T['id'] } => ({
72+
...item,
73+
slug: item.id,
74+
});

src/modules/post/common.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { getAllEntries } from '@/modules/common';
1+
import { render } from 'astro:content';
2+
3+
import { getAllEntries, idToSlug } from '@/modules/common';
24
import { COLLECTIONS } from '@/constants/collections';
35

46
import type { Post, PostCollection } from '@/types/post';
@@ -10,18 +12,24 @@ export const getPostsWithReadingTimeFromPosts = async (
1012
posts: PostCollection[]
1113
): Promise<Post[]> => {
1214
const readingTimePromises = posts.map(async (post) => {
13-
const { remarkPluginFrontmatter } = await post.render();
15+
const { remarkPluginFrontmatter } = await render(post);
1416
const { readingTime } = remarkPluginFrontmatter;
1517
return { readingTime };
1618
});
1719
const readingTimes = await Promise.all(readingTimePromises);
1820

1921
// other frontmatter props are in post.data...
2022
// readingTimes is in post.readingTimes
21-
const postsWithReadingTime = posts.map((post, index) => ({ ...post, ...readingTimes[index] }));
22-
return postsWithReadingTime;
23+
const postsWithReadingTimeAndSlug = posts
24+
.map((post, index) => ({ ...post, ...readingTimes[index] }))
25+
.map(idToSlug);
26+
return postsWithReadingTimeAndSlug;
2327
};
2428

25-
/** Prefer over getAllPosts() */
29+
/**
30+
* Prefer over getAllPosts()
31+
* From this point Post[] instead of CollectionEntry<'post'>[].
32+
* My custom type with slug, readingTime, etc.
33+
*/
2634
export const getAllPostsWithReadingTime = async (): Promise<Post[]> =>
2735
getPostsWithReadingTimeFromPosts(await getAllPosts());

src/modules/project.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
import { getAllEntries } from '@/modules/common';
1+
import { getAllEntries, idToSlug } from '@/modules/common';
22
import { COLLECTIONS } from '@/constants/collections';
33

4+
import type { Project } from '@/types/project';
5+
46
/*-------------------------------- getAllProjects ------------------------------*/
57

6-
export const getAllProjects = () => getAllEntries(COLLECTIONS.PROJECT);
8+
/**
9+
* From this point Project[] instead of CollectionEntry<'project'>[].
10+
* My custom type with slug, etc.
11+
*/
12+
export const getAllProjects = (): Promise<Project[]> =>
13+
getAllEntries(COLLECTIONS.PROJECT).then((entries) => entries.map(idToSlug));

src/pages/blog/[slug].astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
import { Image } from 'astro:assets';
3+
import { render } from 'astro:content';
34
45
import { getAllPostsWithReadingTime } from '@/modules/post/common';
56
import { getRandomPosts } from '@/modules/post/random';
@@ -39,7 +40,7 @@ export async function getStaticPaths() {
3940
return paths;
4041
}
4142
42-
const { data, render, readingTime, randomPosts } = Astro.props;
43+
const { data, readingTime, randomPosts } = Astro.props;
4344
const {
4445
draft,
4546
title,
@@ -57,7 +58,7 @@ const {
5758
const { slug } = Astro.params;
5859
const { pathname } = Astro.url;
5960
60-
const { Content, headings: postHeadings } = await render();
61+
const { Content, headings: postHeadings } = await render(Astro.props);
6162
const headings = getHeadingsForTableOfContents(postHeadings);
6263
6364
const postMetaProps = {

src/pages/projects/[...page].astro

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { CONFIG_CLIENT } from '@/config/client';
66
import { getPageMetadata } from '@/utils/metadata';
77
import { pickPaginationPropsFromPage } from '@/utils/pagination';
88
9-
import type { ProjectCollection } from '@/types/project';
9+
import type { Project } from '@/types/project';
1010
import type { GetStaticPathsOptions, Page } from 'astro';
1111
1212
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
13-
const sortedProjects = await getAllProjects();
13+
const sortedProjects: Project[] = await getAllProjects();
1414
const pageSize = CONFIG_CLIENT.PAGE_SIZE_POST_CARD;
1515
1616
const pagination = paginate(sortedProjects, { pageSize });
@@ -19,7 +19,7 @@ export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
1919
}
2020
2121
type Props = {
22-
page: Page<ProjectCollection>;
22+
page: Page<Project>;
2323
};
2424
2525
const { page } = Astro.props;

src/pages/projects/[slug].astro

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,30 @@
11
---
2+
import { render } from 'astro:content';
3+
24
import { getAllProjects } from '@/modules/project';
3-
import Project from '@/layouts/Project.astro';
5+
import ProjectLayout from '@/layouts/Project.astro';
46
import Share from '@/components/Share.astro';
57
import { ROUTES } from '@/constants/routes';
68
import { CONFIG_CLIENT } from '@/config/client';
79
import { getOpenGraphImagePath } from '@/libs/api/open-graph/image-path';
810
911
import type { Metadata } from '@/types/common';
12+
import type { Project } from '@/types/project';
1013
1114
const { SITE_URL } = CONFIG_CLIENT;
1215
1316
export async function getStaticPaths() {
14-
const sortedProjects = await getAllProjects();
17+
const sortedProjects: Project[] = await getAllProjects();
1518
16-
const paths = sortedProjects.map((page) => ({
17-
params: { slug: page.slug },
18-
props: { page },
19+
const paths = sortedProjects.map((project) => ({
20+
params: { slug: project.slug },
21+
props: { ...project },
1922
}));
2023
2124
return paths;
2225
}
2326
24-
const { data, render } = Astro.props.page;
27+
const { data } = Astro.props;
2528
const { pathname } = Astro.url;
2629
const { slug } = Astro.params;
2730
@@ -36,10 +39,10 @@ const shareProps = {
3639
url: `${SITE_URL}${ROUTES.PROJECTS}${slug}`,
3740
};
3841
39-
const { Content } = await render();
42+
const { Content } = await render(Astro.props);
4043
---
4144

42-
<Project {metadata}>
45+
<ProjectLayout {metadata}>
4346
<Content />
4447
<Share {...shareProps} />
45-
</Project>
48+
</ProjectLayout>

0 commit comments

Comments
 (0)