Building a mini CMS with Astro and TypeScript
My goal is to build a template for Astro that works as a composable and flexible mini CMS β designed for those who want something lightweight and easy to extend, without relying on too many external libraries.
The result of my experiments is this: simple and somewhat limited in some aspects, but I believe the code can be extended to fit the needs of each project.

.webp)
.webp)
Itβs becoming increasingly common to rely on multiple JavaScript packages to solve small tasks, but I believe a minimalist approach can also be powerful. Fewer dependencies mean less maintenance and more control over the project.
I think code generators are awesome. A good example is ShadCN, where components can be easily copied and pasted β a big part of why it has become so popular. I believe we could bring that same copy-paste logic to CMSs: instead of depending on numerous external packages, it would be more composable and flexible to have the code directly integrated, while keeping things relatively simple.
How do I define a collection?
// collections/brands.ts
import { z } from "zod";
import { brand } from "astro:db";
import type { Collection } from "@/types/collections";
const brandSchema = z.object({
id: z.string().optional(),
slug: z.string(),
name: z.string().min(1),
description: z.string().optional(),
website: z.string().optional(),
});
export const brandsCollection = {
label: "Brands",
table: brand,
schema: brandSchema,
fieldMap: [
{
field: "id",
fieldComponent: "text-field",
label: "ID",
},
{
field: "name",
fieldComponent: "text-field",
required: true,
label: "Brand Name",
},
{
field: "description",
fieldComponent: "textarea-field",
label: "Description",
placeholder: "Optional brand description",
},
{
field: "slug",
fieldComponent: "text-field",
required: true,
label: "Slug",
placeholder: "brand-slug",
},
{
field: "website",
fieldComponent: "url-field",
label: "Website",
placeholder: "https://example.com",
},
],
} satisfies Collection<typeof brandSchema>;