diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-03 10:56:21 +0300 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-03 10:56:21 +0300 |
| commit | 456cf011b36de91c9936994b1fa45703adcd309b (patch) | |
| tree | 8e60daf998f731ac50d100fa490eaecae1168042 /src/pages/posts | |
Initial fork of chrismwilliams/astro-theme-cactus theme
Diffstat (limited to 'src/pages/posts')
| -rw-r--r-- | src/pages/posts/[...page].astro | 125 | ||||
| -rw-r--r-- | src/pages/posts/[...slug].astro | 24 |
2 files changed, 149 insertions, 0 deletions
diff --git a/src/pages/posts/[...page].astro b/src/pages/posts/[...page].astro new file mode 100644 index 0000000..495fc7b --- /dev/null +++ b/src/pages/posts/[...page].astro @@ -0,0 +1,125 @@ +--- +import type { CollectionEntry } from "astro:content"; +import Pagination from "@/components/Paginator.astro"; +import PostPreview from "@/components/blog/PostPreview.astro"; +import { getAllPosts, getUniqueTags, groupPostsByYear } from "@/data/post"; +import PageLayout from "@/layouts/Base.astro"; +import { collectionDateSort } from "@/utils/date"; +import type { GetStaticPaths, Page } from "astro"; +import { Icon } from "astro-icon/components"; + +export const getStaticPaths = (async ({ paginate }) => { + const MAX_POSTS_PER_PAGE = 10; + const MAX_TAGS = 7; + const allPosts = await getAllPosts(); + const uniqueTags = getUniqueTags(allPosts).slice(0, MAX_TAGS); + return paginate(allPosts.sort(collectionDateSort), { + pageSize: MAX_POSTS_PER_PAGE, + props: { uniqueTags }, + }); +}) satisfies GetStaticPaths; + +interface Props { + page: Page<CollectionEntry<"post">>; + uniqueTags: string[]; +} + +const { page, uniqueTags } = Astro.props; + +const meta = { + description: "Read my collection of posts and the things that interest me", + title: "Posts", +}; + +const paginationProps = { + ...(page.url.prev && { + prevUrl: { + text: "← Previous Page", + url: page.url.prev, + }, + }), + ...(page.url.next && { + nextUrl: { + text: "Next Page →", + url: page.url.next, + }, + }), +}; + +const groupedByYear = groupPostsByYear(page.data); +const descYearKeys = Object.keys(groupedByYear).sort((a, b) => +b - +a); +--- + +<PageLayout meta={meta}> + <div class="mb-6 flex items-center gap-3"> + <h1 class="title">Posts</h1> + <a class="text-accent" href="/rss.xml" target="_blank"> + <span class="sr-only">RSS feed</span> + <Icon aria-hidden="true" class="h-6 w-6" focusable="false" name="mdi:rss" /> + </a> + </div> + <div class="grid sm:grid-cols-[3fr_1fr] sm:gap-x-8 sm:gap-y-16"> + <div> + { + descYearKeys.map((yearKey) => ( + <section aria-labelledby={`year-${yearKey}`}> + <h2 id={`year-${yearKey}`} class="title text-lg"> + <span class="sr-only">Posts in</span> + {yearKey} + </h2> + <ul class="mt-5 mb-16 space-y-6 text-start"> + {groupedByYear[yearKey]?.map((p) => ( + <li class="grid gap-2 sm:grid-cols-[auto_1fr] sm:[&_q]:col-start-2"> + <PostPreview post={p} /> + </li> + ))} + </ul> + </section> + )) + } + <Pagination {...paginationProps} /> + </div> + { + !!uniqueTags.length && ( + <aside> + <h2 class="title mb-4 flex items-center gap-2 text-lg"> + Tags + <svg + aria-hidden="true" + class="h-6 w-6" + fill="none" + stroke="currentColor" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="1.5" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M0 0h24v24H0z" fill="none" stroke="none" /> + <path d="M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z" /> + <path d="M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116" /> + <path d="M6 9h-.01" /> + </svg> + </h2> + <ul class="flex flex-wrap gap-2"> + {uniqueTags.map((tag) => ( + <li> + <a class="cactus-link flex items-center justify-center" href={`/tags/${tag}/`}> + <span aria-hidden="true">#</span> + <span class="sr-only">View all posts with the tag</span> + {tag} + </a> + </li> + ))} + </ul> + <span class="mt-4 block sm:text-end"> + <a class="hover:text-link" href="/tags/"> + View all <span aria-hidden="true">→</span> + <span class="sr-only">blog tags</span> + </a> + </span> + </aside> + ) + } + </div> +</PageLayout> diff --git a/src/pages/posts/[...slug].astro b/src/pages/posts/[...slug].astro new file mode 100644 index 0000000..ca9c491 --- /dev/null +++ b/src/pages/posts/[...slug].astro @@ -0,0 +1,24 @@ +--- +import { render } from "astro:content"; +import { getAllPosts } from "@/data/post"; +import PostLayout from "@/layouts/BlogPost.astro"; +import type { GetStaticPaths, InferGetStaticPropsType } from "astro"; + +// if you're using an adaptor in SSR mode, getStaticPaths wont work -> https://docs.astro.build/en/guides/routing/#modifying-the-slug-example-for-ssr +export const getStaticPaths = (async () => { + const blogEntries = await getAllPosts(); + return blogEntries.map((post) => ({ + params: { slug: post.id }, + props: { post }, + })); +}) satisfies GetStaticPaths; + +type Props = InferGetStaticPropsType<typeof getStaticPaths>; + +const { post } = Astro.props; +const { Content } = await render(post); +--- + +<PostLayout post={post}> + <Content /> +</PostLayout> |
