Multiple document fields in one collection #361
-
Is it possible to have multiple document fields in a collection? I have a blog collection and would like another
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
Hey! Yep, this will work out of the box. Since you set the Except for the For those, Keystatic will create a folder named after the entry With your code, if you created a post with a slug of
I copied and pasted your exact code in a new project created with the Keystatic CLI, and it worked straight away. The reason the other document field goes into another file is that Markdown/Markdoc/MDX can only have one single Putting the whole serialized rich text in the frontmatter would be very big/ugly. Working with Astro content collectionsI realise that makes things slightly more complex when working with Astro collections — but Astro does have a convention of prefixing files/assets with an underscore. Sharing from a discussion with Ben Holmes from the Astro core team: I’ll also share that we do support colocation with underscore _ directories for relative assets today! This is helpful for referencing image assets and partials from your content. You can also use the index naming to chop this off in the generated slug (ex. blog/post-1/index.md -> blog/post-1). Here’s an example I could imagine to colocate assets on an existing post, and store a set of Markdoc partials alongside:
Alternatively, you can use an underscore on the file name itself rather than using nested directories:
I imagine keystatic could support this approach to allow our existing nested directories feature and use colocated assets. Let me know if there’s more to the story though! TypeScript autocomplete suggestionsPS: Make sure you wrap your whole - blog: {
+ blog: collection({
label: 'Blog',
path: 'src/content/blog/*',
slugField: 'name',
format: {
data: 'yaml',
contentField: 'content',
},
schema: {
name: fields.slug({ name: { label: 'Name' }}),
publishedOn: fields.date({ label: 'Published On' }),
draft: fields.checkbox({
label: 'Draft',
}),
content: fields.document({
label: 'Content',
formatting: true,
links: true,
}),
summary: fields.document({
label: 'Summary',
formatting: true,
links: true,
}),
}
- },
+ }), |
Beta Was this translation helpful? Give feedback.
-
Sorry to resurrect an old thread. I am attempting to do this and can’t to figure it out. With the default folder convention outlined above with content collections, since it doesn’t include any underscores, it seems Astro tries to read the nested mdx files as part of the collection, but fails because they have no front matter and therefore do not validate against the collection schema. Do I have something set up wrong or do the multiple mdx sections not work with content collections? |
Beta Was this translation helpful? Give feedback.
-
I got it to work with mutliple mdx fields. However, I am having trouble with the Astro ZOD validations via My Keystatic Setupexport const keystaticHomepageConfig = singleton({
entryLayout: 'form',
label: 'Homepage',
// format: { contentField: 'body' }, // in this case, we want separate files
path: 'src/content/homepage/',
schema: {
title: fields.text({ label: 'Titel', validation: { isRequired: true } }),
bodyBeforeQuotes: fields.mdx({
label: 'Inhalte oberhalb der Zitate',
components: {
Quotes: keystaticQuoteConfig,
Button: keystaticButtonConfig,
},
options: {
image: {
directory: 'src/content/homepage',
publicPath: '../../content/homepage',
},
},
}),
bodyAfterQuotes: fields.mdx({
label: 'Inhalt unterhalb der Zitate',
components: {
Quotes: keystaticQuoteConfig,
Button: keystaticButtonConfig,
},
options: {
image: {
directory: 'src/content/homepage',
publicPath: '../../content/homepage',
},
},
}),
},
}) Which creates a file structure like this… where index.yaml is only My Astro ZOD definition – this is the part that I have issues with:export const astroHomepageDefinition = defineCollection({
type: 'content',
schema: () =>
z.object({
title: z.string(),
}),
}) My /index.astro page…
const homepageData = await getEntry('homepage', 'index')
const homepageBeforeQuotes = await getEntry('homepage', 'bodybeforequotes')
const homepageAfterQuotes = await getEntry('homepage', 'bodyafterquotes')
const { Content: ContentBeforeQuotes } = await homepageBeforeQuotes.render()
const { Content: ContentAfterQuotes } = await homepageAfterQuotes.render()
---
<Layout>
<HomepageHero />
<Section prose>
<pre>{JSON.stringify(homepageData, undefined, 2)}</pre>
<pre>{JSON.stringify(homepageBeforeQuotes, undefined, 2)}</pre>
<pre>{JSON.stringify(homepageAfterQuotes, undefined, 2)}</pre>
<ContentBeforeQuotes components={{ Button }} />
<h1>TODO QUOTES</h1>
<ContentAfterQuotes components={{ Button }} />
… The issue is…The ZOD validation is applied to all three
My work around is, to change my ZOD validation… – But with this I look strictness that I don't want to loose. export const astroHomepageDefinition = defineCollection({
type: 'content',
schema: () =>
z.object({
- title: z.string(),
+ title: z.string().optional(),
}),
}) Any ideas on what is going on? Maybe some search terms I could use to look for solutions…? |
Beta Was this translation helpful? Give feedback.
Hey!
Yep, this will work out of the box.
Since you set the
content
field as yourcontentField
, the main file generated will contain thatcontent
field in the "body" of the.mdoc
file, and the other fields in the frontmatter at the top.Except for the
summary
and any other eventual document fields.For those, Keystatic will create a folder named after the entry
slug
, and inside there a.mdoc
file named after the field:With your code, if you created a post with a slug of
hello-world
, the output files would be like so:I copied and pasted your exact code in a new project created with the Keystatic C…