Docs
Darkmatter is a CMS for Astro content collections. Open any Astro project in Darkmatter and you’ll get access to an easy-to-use interface for managing each content collection that’s dynamically generated from collection’s Zod schema.
Getting started
- Download and install Darkmatter.
- Click “Open Project” button in the welcome window that shows on first start.
- Point to the root folder of your Astro project. Make sure dependencies are installed.
- Start managing content inside your content collections.
There’s no configuration or additional setup needed to start writing content with Darkmatter.
Collection schemas
Darkmatter generates a custom UI for each content collection by scanning its Zod schema.
Zod field types
Darkmatter recognizes and generates inputs for these Zod types:
String
Use zod.string()
to define a single-line text input.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
schema: zod.object({
title: zod.string(),
}),
});
export const collections = { examples };
This field is saved as:
---
title: Example
---
Number
Use zod.number()
to define a number input.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
schema: zod.object({
order: zod.number(),
}),
});
export const collections = { examples };
This field is saved as:
---
order: 28
---
Boolean
Use zod.boolean()
to define a switch.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
schema: zod.object({
featured: zod.boolean(),
}),
});
export const collections = { examples };
This field is saved as:
---
featured: true
---
Date
Use zod.date()
to define a date input. Since most often Astro websites work with calendar dates, zod.date()
is saved in YYYY-MM-DD
format (e.g. 2023-01-26). If you need to save hours, minutes and seconds, use dateTime()
.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
schema: zod.object({
date: zod.date(),
}),
});
export const collections = { examples };
This field is saved as:
---
date: 2023-05-21
---
Enum
Use zod.enum()
to define a select input with a list of allowed values.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
schema: zod.object({
section: zod.enum(["Breaking news", "Morning show", "Other"]),
}),
});
export const collections = { examples };
This field is saved as:
---
section: Breaking news
---
Object
Use zod.object()
to group relevant fields into an object.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
author: zod.object({
name: zod.string(),
avatarUrl: zod.string().url(),
}),
});
export const collections = { examples };
This field is saved as:
---
author:
name: Jane Hopper
avatarUrl: https://jane.com/me.jpg
---
Array
Use zod.array()
to define a list of fields that can be added or removed by the user.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
tags: zod.array(zod.string()),
});
export const collections = { examples };
This field is saved as:
---
tags:
- Breaking
- Economy
---
Union
Use zod.union()
to define a field, which type can be changed by the user.
import { z as zod, defineCollection } from "astro:content";
const examples = defineCollection({
keywords: zod.string().or(zod.array(zod.string())),
});
export const collections = { examples };
This field is saved as:
---
keywords: breaking, economy
---
Union field shows a dropdown where you can switch between field types.
This field is saved as:
---
keywords:
- breaking
- economy
---
Astro field types
In addition to Zod types, Darkmatter also supports schema types provided by Astro:
Collection reference
Use reference()
exported by astro:content
module to define a field, which references an entry in any content collection.
import { defineCollection, reference, z as zod } from "astro:content";
const posts = defineCollection({
schema: zod.object({
category: reference("category"),
}),
});
const categories = defineCollection({
type: "data",
schema: zod.object({
name: zod.string(),
}),
});
export const collections = { posts, categories };
Given there are categories with name
equal to “Economy”, “Startups” and “Indie hackers”, Darkmatter will show the following dropdown to reference one of these categories:
Since “Indie hackers” entry’s file name is indie-hackers.json
, this union field will be saved as:
---
category: indie-hackers
---
Image
Use image()
to define a file input, which allows user to select an image.
import { defineCollection, z as zod } from "astro:content";
const examples = defineCollection({
schema: ({ image }) => {
return zod.object({
image: image(),
});
},
});
export const collections = { examples };
User can click on the “Choose File” button to open a native dialog to pick an image or they can drag & drop an image from anywhere. Once image is added, Darkmatter will copy it to src/assets/[collection name]/[entry name]
folder (it will be created it if doesn’t exist) and save the field as a path to the copied image.
---
coverImage: ../../assets/examples/example/image.png
---
Custom Darkmatter types
Darkmatter also provides a few custom types that aren’t covered by Zod or Astro: text and date time. To use them in your Astro project, install darkmatter
package first:
npm install darkmatter
Text
Use text()
exported from darkmatter
package to define a multi-line text input. It works exactly the same way as zod.string()
and returns the same ZodString
instance. The only difference is how Darkmatter displays such field in the UI.
import { defineCollection, z as zod } from "astro:content";
import { text } from "darkmatter";
const examples = defineCollection({
schema: zod.object({
description: text(),
}),
});
export const collections = { examples };
This field is saved as:
---
description: This is a multi-line text field
---
Date time
Use dateTime()
exported from darkmatter
package to define a date time input. It works exactly the same as zod.date()
and returns the same ZodDate
instance. The only difference is date time input allows user to set the time, in addition to the date.
import { defineCollection, z as zod } from "astro:content";
import { dateTime } from "darkmatter";
const examples = defineCollection({
schema: zod.object({
timestamp: dateTime(),
}),
});
export const collections = { examples };
This field is saved as:
---
timestamp: 2023-05-21T06:41:00.000Z
---
Note that timestamp is saved in UTC and not in your timezone.