feat: add blog with archives, pagination, search, sharing and RSS
- Content collection (one folder per post) with zod schema - /blog, category and tag archives with /sayfa/<n>/ pagination - Post page: breadcrumbs, date badges, share bar, TOC, DIY notice, code copy, license line, prev/next, BlogPosting + BreadcrumbList JSON-LD - Sidebar: Pagefind search, categories, featured fallback, tag cloud - Sätteri HAST plugins for figure/figcaption and external links - Dual-theme Shiki, themed prose, RSS feed, latest posts on home - Three sample posts marked as examples Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
---
|
||||
// Shared layout for /blog/, category and tag archives (all paginated).
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { blog, fmt } from '../../lib/data';
|
||||
import type { Post } from '../../lib/posts';
|
||||
import Container from '../Container.astro';
|
||||
import GridLines from '../GridLines.astro';
|
||||
import SectionHeading from '../SectionHeading.astro';
|
||||
import Pager from './Pager.astro';
|
||||
import PostCard from './PostCard.astro';
|
||||
import Sidebar from './Sidebar.astro';
|
||||
|
||||
export interface Props {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
description: string;
|
||||
/** Posts on this page. */
|
||||
posts: Post[];
|
||||
/** All published posts, for the sidebar. */
|
||||
allPosts: Post[];
|
||||
current: number;
|
||||
total: number;
|
||||
base: string;
|
||||
activeCategory?: string;
|
||||
activeTag?: string;
|
||||
jsonLd?: Record<string, unknown>[];
|
||||
}
|
||||
|
||||
const {
|
||||
eyebrow,
|
||||
title,
|
||||
description,
|
||||
posts,
|
||||
allPosts,
|
||||
current,
|
||||
total,
|
||||
base,
|
||||
activeCategory,
|
||||
activeTag,
|
||||
jsonLd,
|
||||
} = Astro.props;
|
||||
const seoTitle = current > 1 ? fmt(blog.list.pageTitle, { title, n: current }) : title;
|
||||
---
|
||||
|
||||
<BaseLayout title={seoTitle} description={description} jsonLd={jsonLd}>
|
||||
<section class="surface-alt relative overflow-hidden">
|
||||
<GridLines />
|
||||
<Container class="relative py-14 md:py-20">
|
||||
<SectionHeading level={1} eyebrow={eyebrow} title={title} />
|
||||
<p class="mt-4 max-w-2xl text-lg">{description}</p>
|
||||
</Container>
|
||||
</section>
|
||||
|
||||
<Container class="grid gap-12 py-14 lg:grid-cols-[minmax(0,1fr)_20rem]">
|
||||
<div>
|
||||
{posts.length ? (
|
||||
<ul class="flex flex-col gap-8">
|
||||
{posts.map((post, i) => (
|
||||
<li>
|
||||
<PostCard post={post} priority={i === 0} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p class="border-fg/30 border-2 border-dashed p-8 text-center text-lg">{blog.list.empty}</p>
|
||||
)}
|
||||
<Pager current={current} total={total} base={base} />
|
||||
</div>
|
||||
<Sidebar posts={allPosts} activeCategory={activeCategory} activeTag={activeTag} />
|
||||
</Container>
|
||||
</BaseLayout>
|
||||
Reference in New Issue
Block a user