Files
twenty/packages/twenty-website/keystatic.config.ts
Baptiste Devessier f5195433f3 Configure Keystatic for release images (#10889)
- Add validation for the `release` field of the releases collection
  - The `release` must follow semver format
- The `slug` matches the `release` by default and must follow semver
format, too
- Order the releases properly
- `0.10.0` appears before `0.3.0`; I made the comparison against
`0000.0010.0000` and `0000.0003.0000`
- Set up images for release's contents
- Refactor the release notes of the version `0.43.0` to be editable in
Keystatic; it will serve as an example

## Demo



https://github.com/user-attachments/assets/d82851e9-11e7-4e27-b645-cf86a93d77bf
2025-03-18 12:45:51 +01:00

81 lines
2.2 KiB
TypeScript

import { collection, config, fields } from '@keystatic/core';
import { wrapper } from '@keystatic/core/content-components';
export default config({
storage: {
kind: 'github',
repo: {
owner: 'twentyhq',
name: 'twenty',
},
pathPrefix: 'packages/twenty-website',
},
collections: {
developers: collection({
label: 'Technical documentation',
slugField: 'title',
path: 'src/content/developers/**',
format: { contentField: 'content' },
schema: {
title: fields.slug({ name: { label: 'Title' } }),
icon: fields.text({ label: 'Icon' }),
image: fields.text({ label: 'Image' }),
info: fields.text({ label: 'Info' }),
content: fields.mdx({
label: 'Content',
components: {
ArticleEditContent: wrapper({
label: 'ArticleEditContent',
schema: {},
}),
},
}),
},
}),
releases: collection({
label: 'Releases',
slugField: 'release',
path: 'src/content/releases/*',
format: { contentField: 'content' },
schema: {
release: fields.slug({
name: {
label: 'Release',
validation: {
pattern: {
regex: /^\d+\.\d+\.\d+$/,
message: 'The release must be in the format major.minor.patch',
},
},
},
slug: {
generate: (name) => name,
validation: {
pattern: {
regex: /^\d+\.\d+\.\d+$/,
message: 'The release must be in the format major.minor.patch',
},
},
},
}),
// TODO: Define the date with a normalized format
Date: fields.text({ label: 'Date' }),
content: fields.mdx({
label: 'Content',
options: {
image: {
directory: 'public/images/releases',
publicPath: '/images/releases/',
},
},
}),
},
parseSlugForSort: (slug) => {
const [major, minor, patch] = slug.split('.');
return `${major.padStart(4, '0')}.${minor.padStart(4, '0')}.${patch.padStart(4, '0')}`;
},
}),
},
});