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,33 @@
|
||||
import { defineCollection } from 'astro:content';
|
||||
import { glob } from 'astro/loaders';
|
||||
import { z } from 'astro/zod';
|
||||
|
||||
// One folder per post: src/content/blog/<slug>/index.md(x) + its images.
|
||||
const blog = defineCollection({
|
||||
loader: glob({
|
||||
pattern: '**/index.{md,mdx}',
|
||||
base: './src/content/blog',
|
||||
generateId: ({ entry }) => entry.replace(/\/index\.mdx?$/, ''),
|
||||
}),
|
||||
schema: ({ image }) =>
|
||||
z
|
||||
.object({
|
||||
title: z.string().max(70),
|
||||
description: z.string().min(50).max(160),
|
||||
pubDate: z.coerce.date(),
|
||||
updatedDate: z.coerce.date().optional(),
|
||||
category: z.string(), // must exist in src/data/categories.json (checked in lib/posts.ts)
|
||||
tags: z.array(z.string()).default([]),
|
||||
cover: image().optional(),
|
||||
coverAlt: z.string().optional(),
|
||||
featured: z.boolean().default(false),
|
||||
diy: z.boolean().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
})
|
||||
.refine((d) => !d.cover || !!d.coverAlt, {
|
||||
message: 'coverAlt is required when cover is set',
|
||||
path: ['coverAlt'],
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog };
|
||||
Reference in New Issue
Block a user