initial: four-collection content pipeline for unique.rzen.dev
A small Astro + MDX blog for delightful, daily-use finds. The architecture separates capture from publication and supports reuse: - find/ captured items, hidden from indexes - finds/ editorial superposts referencing find slugs in a grid - reviews/ full-length writeups; can graduate from a find via fromFind - posts/ regular essays Three project-local skills under .claude/skills/ drive the pipeline: daily-finds (capture-only sweep across sources.json), build-finds (draft a thematic superpost), build-review (graduate a find). sources.json carries 47 curated feeds with per-source fetch strategy (webfetch / curl / skip) so Cloudflare-blocked sites and Reddit JSON endpoints are handled deterministically. /sources renders a 3-column card stream with a "Recent finds" cross-reference per source. Seeds: 17 reviews and one superpost referencing 5 finds.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
import { glob } from 'astro/loaders';
|
||||
|
||||
const reviews = defineCollection({
|
||||
loader: glob({ pattern: '**/*.mdx', base: './src/content/reviews' }),
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
subtitle: z.string(),
|
||||
date: z.coerce.date(),
|
||||
category: z.string(),
|
||||
tags: z.array(z.string()).default([]),
|
||||
link: z.string().url().optional(),
|
||||
linkText: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
source: z.string().optional(),
|
||||
fromFind: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const posts = defineCollection({
|
||||
loader: glob({ pattern: '**/*.mdx', base: './src/content/posts' }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
date: z.coerce.date(),
|
||||
category: z.string(),
|
||||
tags: z.array(z.string()).default([]),
|
||||
description: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const find = defineCollection({
|
||||
loader: glob({ pattern: '**/*.mdx', base: './src/content/find' }),
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
subtitle: z.string().optional(),
|
||||
date: z.coerce.date(),
|
||||
link: z.string().url(),
|
||||
linkText: z.string().optional(),
|
||||
source: z.string(),
|
||||
topics: z.array(z.string()).default([]),
|
||||
tags: z.array(z.string()).default([]),
|
||||
description: z.string().optional(),
|
||||
promotedTo: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const finds = defineCollection({
|
||||
loader: glob({ pattern: '**/*.mdx', base: './src/content/finds' }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
date: z.coerce.date(),
|
||||
category: z.string().default('finds'),
|
||||
tags: z.array(z.string()).default([]),
|
||||
description: z.string().optional(),
|
||||
blurb: z.string().optional(),
|
||||
items: z.array(z.string()).min(1),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { reviews, posts, find, finds };
|
||||
Reference in New Issue
Block a user