+15
-1
src/content.config.ts
+15
-1
src/content.config.ts
···
1
1
import { glob } from 'astro/loaders';
2
2
import { defineCollection, z } from 'astro:content';
3
+
import { image } from './utils';
3
4
4
5
const blog = defineCollection({
5
6
// Load Markdown and MDX files in the `src/content/blog/` directory.
···
19
20
}),
20
21
});
21
22
22
-
export const collections = { blog };
23
+
const gallery = defineCollection({
24
+
loader: image('./src/content/gallery'),
25
+
schema: ({ image }) => z.object({
26
+
title: z.string(),
27
+
artist: z.string(),
28
+
alt: z.string(),
29
+
path: z.string(),
30
+
image: image(),
31
+
width: z.number(),
32
+
height: z.number()
33
+
}),
34
+
});
35
+
36
+
export const collections = { blog, gallery };
src/content/gallery/Michigan_in_the_Summer.png
src/content/gallery/Michigan_in_the_Summer.png
This is a binary file and will not be displayed.
+56
src/layouts/GalleryPost.astro
+56
src/layouts/GalleryPost.astro
···
1
+
---
2
+
import type { CollectionEntry } from "astro:content";
3
+
import { Head, Footer, Navigation } from "@/components/organisms";
4
+
import { Image } from "astro:assets";
5
+
import SpeedInsights from "@vercel/speed-insights/astro";
6
+
import Analytics from "@vercel/analytics/astro";
7
+
8
+
type Props = CollectionEntry<"gallery">["data"];
9
+
10
+
const { title, alt, image, width, height } = Astro.props;
11
+
---
12
+
13
+
<html lang="en">
14
+
<head>
15
+
<Head title={title} description={alt} />
16
+
<style>
17
+
article {
18
+
display: flex;
19
+
flex-direction: column;
20
+
width: 100%;
21
+
gap: 1rem;
22
+
}
23
+
24
+
h1 {
25
+
margin-bottom: 0;
26
+
}
27
+
28
+
img {
29
+
height: 100%;
30
+
width: 100%;
31
+
object-fit: contain;
32
+
}
33
+
</style>
34
+
</head>
35
+
36
+
<body data-theme="dark">
37
+
<Navigation />
38
+
<main>
39
+
<article>
40
+
<h1>{title}</h1>
41
+
<a href={image.src}>
42
+
<Image
43
+
src={image}
44
+
alt={alt}
45
+
width={width}
46
+
height={height}
47
+
/>
48
+
</a>
49
+
<p>{alt}</p>
50
+
</article>
51
+
<Footer />
52
+
<SpeedInsights />
53
+
<Analytics />
54
+
</main>
55
+
</body>
56
+
</html>
+22
src/pages/gallery/[...slug].astro
+22
src/pages/gallery/[...slug].astro
···
1
+
---
2
+
import { type CollectionEntry, getCollection } from "astro:content";
3
+
import BlogPost from "@/layouts/BlogPost.astro";
4
+
import { render } from "astro:content";
5
+
import GalleryPost from "@/layouts/GalleryPost.astro";
6
+
7
+
export async function getStaticPaths() {
8
+
const gallery = await getCollection("gallery");
9
+
return gallery.map((image) => ({
10
+
params: {
11
+
slug: image.data.title.toLowerCase().replaceAll(" ", "-"),
12
+
},
13
+
props: image,
14
+
}));
15
+
}
16
+
type Props = CollectionEntry<"gallery">;
17
+
18
+
const post = Astro.props;
19
+
const { Content } = await render(post);
20
+
---
21
+
22
+
<GalleryPost {...post.data} />
+55
src/pages/gallery/index.astro
+55
src/pages/gallery/index.astro
···
1
+
---
2
+
import {
3
+
Head,
4
+
Footer,
5
+
Navigation,
6
+
BlogPreviewCard,
7
+
} from "@/components/organisms";
8
+
import { SITE_TITLE, SITE_DESCRIPTION } from "@/consts";
9
+
import { getCollection } from "astro:content";
10
+
import SpeedInsights from "@vercel/speed-insights/astro";
11
+
import Analytics from "@vercel/analytics/astro";
12
+
13
+
const gallery = await getCollection("gallery");
14
+
---
15
+
16
+
<!doctype html>
17
+
<html lang="en">
18
+
<head>
19
+
<Head title={SITE_TITLE} description={SITE_DESCRIPTION} />
20
+
<style>
21
+
main > section {
22
+
width: 100%;
23
+
}
24
+
25
+
main > section > ul {
26
+
display: flex;
27
+
flex-direction: column;
28
+
gap: 2rem;
29
+
list-style: none;
30
+
padding: 0;
31
+
}
32
+
</style>
33
+
</head>
34
+
<body data-theme="dark">
35
+
<Navigation />
36
+
<main>
37
+
<h1>Gallery</h1>
38
+
<section>
39
+
{
40
+
gallery.length !== 0 && (
41
+
<ul>
42
+
{gallery.map((image) => (
43
+
<li>{image}</li>
44
+
))}
45
+
</ul>
46
+
)
47
+
}
48
+
{gallery.length === 0 && <h2>There are no images yet! 😢</h2>}
49
+
</section>
50
+
</main>
51
+
<Footer />
52
+
<SpeedInsights />
53
+
<Analytics />
54
+
</body>
55
+
</html>