feat: ause astro collection to type safe data fetching

This commit is contained in:
Ruidy 2025-01-01 21:54:00 +01:00
parent edb5d23348
commit 5acac485c7
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
10 changed files with 52 additions and 28 deletions

View file

@ -1,5 +1,4 @@
---
layout: "../../layouts/BlogPostLayout.astro"
title: My first blog post
description: This is my first blog post
pubDate: 2024-12-30

View file

@ -1,5 +1,4 @@
---
layout: "../../layouts/BlogPostLayout.astro"
title: My Second Blog Post
author: Astro Learner
description: "After learning some Astro, I couldn't stop!"

View file

@ -1,5 +1,4 @@
---
layout: "../../layouts/BlogPostLayout.astro"
title: My Third Blog Post
author: Astro Learner
description: "I had some challenges, but asking in the community really helped!"

View file

@ -1,5 +1,4 @@
---
layout: "../../layouts/BlogPostLayout.astro"
title: My Fourth Blog Post
author: Astro Learner
description: "This post will show up on its own!"

19
src/content.config.ts Normal file
View file

@ -0,0 +1,19 @@
import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
loader: glob({ pattern: "**/[^_]*.md", base: "./src/blog" }),
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
author: z.string(),
tags: z.array(z.string()),
image: z.object({
url: z.string(),
alt: z.string(),
}),
}),
});
export const collections = { blog };

View file

@ -4,7 +4,7 @@ const { frontmatter } = Astro.props;
---
<BaseLayout pageTitle={frontmatter.title}>
<p>Published on: {frontmatter.pubDate.toString().slice(0, 10)}</p>
<p>Published on: {frontmatter.pubDate.toLocaleDateString()}</p>
<p><em>{frontmatter.description}</em></p>
<p>Written by: {frontmatter.author}</p>
<img src={frontmatter.image.url} alt={frontmatter.image.alt} width="500" />

View file

@ -2,12 +2,11 @@
import "../styles/global.css";
import BaseLayout from "../layouts/BaseLayout.astro";
import BLogPost from "../components/BLogPost.astro";
import { getCollection } from "astro:content";
const pageTitle = "Blog posts";
const allPosts = Object.values(
import.meta.glob("./posts/*.md", { eager: true }),
);
const allPosts = await getCollection("blog");
---
<BaseLayout pageTitle={pageTitle}>
@ -16,7 +15,7 @@ const allPosts = Object.values(
<ul>
{
allPosts.map((post: any) => (
<BLogPost url={post.url} title={post.frontmatter.title} />
<BLogPost url=`blog/${post.id}/` title={post.data.title} />
))
}
</ul>

View file

@ -0,0 +1,19 @@
---
import { getCollection, render } from "astro:content";
import BlogPostLayout from "../../layouts/BlogPostLayout.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.id },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
<BlogPostLayout frontmatter={post.data}>
<Content />
</BlogPostLayout>

View file

@ -1,18 +1,13 @@
---
import { getCollection } from "astro:content";
import BLogPost from "../../components/BLogPost.astro";
import BaseLayout from "../../layouts/BaseLayout.astro";
export async function getStaticPaths() {
const posts = Object.values(
import.meta.glob("../posts/*.md", { eager: true }),
);
const tags = [
...new Set(posts.flatMap((post: any) => post.frontmatter.tags)),
];
return tags.map((tag: any) => {
const filteredPosts = posts.filter((post: any) =>
post.frontmatter.tags?.includes(tag),
);
const posts = await getCollection("blog");
const tags = [...new Set(posts.flatMap((post) => post.data.tags))];
return tags.map((tag) => {
const filteredPosts = posts.filter((post) => post.data.tags?.includes(tag));
return { params: { tag }, props: { posts: filteredPosts } };
});
}
@ -25,8 +20,8 @@ const { posts } = Astro.props;
<p>Posts tagged with {tag}</p>
<ul>
{
posts.map((post: any) => (
<BLogPost url={post.url} title={post.frontmatter.title} />
posts.map((post) => (
<BLogPost url=`/blog/${post.id}` title={post.data.title} />
))
}
</ul>

View file

@ -1,13 +1,9 @@
---
import { getCollection } from "astro:content";
import BaseLayout from "../../layouts/BaseLayout.astro";
const tags = [
...new Set(
Object.values(import.meta.glob("../posts/*.md", { eager: true })).flatMap(
(post: any) => post.frontmatter.tags,
),
),
];
const posts = await getCollection("blog");
const tags = [...new Set(posts.flatMap((post) => post.data.tags))];
---
<BaseLayout pageTitle="Tags">