[feat] Update codebase to optimize images and use content collections

This commit is contained in:
JasterV 2025-06-02 14:12:35 +02:00
commit 03c99121b4
10 changed files with 135 additions and 104 deletions

View file

@ -0,0 +1,17 @@
---
interface Props {
date: Date;
}
const { date } = Astro.props;
---
<time datetime={date.toISOString()}>
{
date.toLocaleDateString("en-us", {
year: "numeric",
month: "short",
day: "numeric",
})
}
</time>

View file

@ -1,44 +0,0 @@
---
import type { BlogPost } from "../types/BlogPost.ts";
interface Props {
post: BlogPost;
}
const { post } = Astro.props;
---
<article class="post-card">
<time datetime={post.frontmatter.pubDate}>
{post.frontmatter.pubDate.slice(0, 10)}
</time>
<h2>
<a href={post.url} rel="bookmark">
{post.frontmatter.title}
</a>
</h2>
</article>
<style>
time {
color: var(--text-color-light);
padding-bottom: 1rem;
}
h2 {
margin-bottom: 0.5rem;
}
.post-card {
display: flex;
width: 100%;
flex-direction: column;
align-items: start;
border: 1px solid var(--text-color);
padding: 1rem;
}
a {
text-decoration: none;
}
</style>

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

@ -0,0 +1,15 @@
import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
loader: glob({ base: "./src/content/blog", pattern: "**/*.{md,mdx}" }),
// Type-check frontmatter using a schema
schema: ({ image }) =>
z.object({
title: z.string(),
pubDate: z.coerce.date(),
image: image(),
}),
});
export const collections = { blog };

View file

@ -1,10 +1,7 @@
--- ---
layout: ../../layouts/PostLayout.astro
title: "First time posting here" title: "First time posting here"
pubDate: 2024-01-20 pubDate: 2024-01-20
image: image: "./assets/me.png"
url: "/images/me.png"
alt: "Just me hanging out"
--- ---
So this is my first post in here, I'm quite excited :D So this is my first post in here, I'm quite excited :D

View file

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Before After
Before After

View file

@ -1,28 +1,24 @@
--- ---
import type { Frontmatter } from "../types/BlogPost.ts"; import { type CollectionEntry } from "astro:content";
import BaseLayout from "./BaseLayout.astro"; import BaseLayout from "./BaseLayout.astro";
import backgroundImage from "@assets/blog-bg.jpg"; import backgroundImage from "@assets/blog-bg.jpg";
import FormattedDate from "@components/FormattedDate.astro";
import { Image } from "astro:assets";
interface Props { type Props = CollectionEntry<"blog">["data"];
frontmatter: Frontmatter;
}
const { frontmatter } = Astro.props; const { title, pubDate, image } = Astro.props;
--- ---
<BaseLayout backgroundImage={backgroundImage}> <BaseLayout backgroundImage={backgroundImage}>
<article> <article>
<header> <header>
<img <Image src={image} width="90" alt="Header pic" />
src={frontmatter.image?.url}
width="90"
alt={frontmatter.image?.alt}
/>
<div> <div>
<h1 class="post-title">{frontmatter.title}</h1> <h1 class="post-title">{title}</h1>
<time datetime={frontmatter.pubDate} <div class="date">
>{frontmatter.pubDate.slice(0, 10)}</time <FormattedDate date={pubDate} />
> </div>
</div> </div>
</header> </header>
<main class="post-content"> <main class="post-content">
@ -46,7 +42,7 @@ const { frontmatter } = Astro.props;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
} }
time { .date {
color: var(--text-color-light); color: var(--text-color-light);
} }

View file

@ -1,27 +0,0 @@
---
import type { BlogPost } from "../types/BlogPost.ts";
import PostCard from "@components/PostCard.astro";
import Layout from "@layouts/BaseLayout.astro";
import backgroundImage from "@assets/blog-bg.jpg";
const posts = Object.values(
import.meta.glob<BlogPost>("../pages/posts/*.md", { eager: true }),
);
---
<Layout title="Blog" , backgroundImage={backgroundImage}>
<div class="post-cards">
{posts.map((post) => <PostCard post={post} />)}
</div>
</Layout>
<style>
.post-cards {
display: flex;
flex-direction: column;
gap: 1rem;
margin: 1rem 0rem;
align-items: center;
justify-content: center;
}
</style>

View file

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

View file

@ -0,0 +1,66 @@
---
import Layout from "@layouts/BaseLayout.astro";
import backgroundImage from "@assets/blog-bg.jpg";
import { type CollectionEntry, getCollection } from "astro:content";
import FormattedDate from "@components/FormattedDate.astro";
type PostEntry = CollectionEntry<"Blog">;
const posts: PostEntry[] = await getCollection("blog");
const sortedPosts = posts.sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
---
<Layout title="Blog" , backgroundImage={backgroundImage}>
<div class="post-cards">
{
sortedPosts.map((post) => (
<article class="post-card">
<div class="date">
<FormattedDate date={post.data.pubDate} />
</div>
<h2>
<a href={`/blog/${post.id}`} rel="bookmark">
{post.data.title}
</a>
</h2>
</article>
))
}
</div>
</Layout>
<style>
.post-cards {
display: flex;
flex-direction: column;
gap: 1rem;
margin: 1rem 0rem;
align-items: center;
justify-content: center;
}
.post-card {
display: flex;
width: 100%;
flex-direction: column;
align-items: start;
border: 1px solid var(--text-color);
padding: 1rem;
}
.date {
color: var(--text-color-light);
padding-bottom: 1rem;
}
h2 {
margin-bottom: 0.5rem;
}
a {
text-decoration: none;
}
</style>

View file

@ -1,14 +0,0 @@
import type { MarkdownInstance } from "astro";
export interface Image {
url: string;
alt?: string;
}
export interface Frontmatter {
title: string;
pubDate: string;
image?: Image;
}
export type BlogPost = MarkdownInstance<Frontmatter>;