#Content collection with array of subfiles

4 messages · Page 1 of 1 (latest)

ocean barn
#

So basically I'm making a personal writing website similar to something like fimfiction to display a bunch of my work. Collections are generated with Astro's content collections then props can be passed around and reused in differnet places.

my current problem is that I want to make a collection for episodic stories that contain an array of chapters. I was going to just have all chapters of a story in the same file, with one file acting as information for the episodic props and the rest each representing a story. But it seems I can't easily load in subfiles or use a filter because that can only be done after all the collections have been generated?(I have no clue what I'm doing)

So it looks like I either use something like fs and parse it all in from path but then I believe I lose the ability to use props? Or I can do it properly later after the collection has been generated but then I would just want to immediately staple that over or modify the previous collection so it could replace it and I could move it around everywhere.

dark micaBOT
#

Hi @ocean barn. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

In Astro, you can handle episodic stories with multiple chapters by using a combination of references in your schema and filtering during queries. You do not need to use fs manually; instead, you can leverage Astro's built-in content collection features to keep your data structured and type-safe.

1. Structure with References

The most scalable way to handle this is to have a collection for "Stories" (metadata) and a collection for "Chapters." You can link them by defining a reference in your schema.

When you query a story, you can then query for all chapters that belong to that story.

// src/content.config.ts
import { defineCollection, reference } from 'astro:content';
import { glob } from 'astro/loaders';

const stories = defineCollection({
  loader: glob({ pattern: '**/index.md', base: './src/content/stories' }),
  // Information for episodic props (title, description, etc.)
});

const chapters = defineCollection({
  loader: glob({ pattern: '**/chapter-*.md', base: './src/content/stories' }),
  schema: ({ image }) => z.object({
    title: z.string(),
    // Link this chapter to a specific story
    story: reference('stories'),
  }),
});

2. Querying and Filtering Subfiles

You mentioned being unable to use a filter because collections are generated later. In Astro, you query collections inside your .astro components or pages. You can use getCollection() with a filter to "staple" your chapters to your story at the time of rendering [Querying Collections].

For a specific story page, you can retrieve all related chapters like this:

---
// src/pages/stories/[slug].astro
import { getEntry, getCollection } from 'astro:content';

const { slug } = Astro.params;
const story = await getEntry('stories', slug);
#

// Filter the chapters collection to find only chapters for this story
const storyChapters = await getCollection('chapters', ({ data }) => {
return data.story.id === story.id;
});

<h1>{story.data.title}</h1>
<ul>
{storyChapters.map(chapter => (
<li>{chapter.data.title}</li>
))}
</ul>


### 3. Using Nested Data Files
If you prefer keeping everything in one file (like a single JSON or YAML file containing an array of chapters), you can use the `parser` function with the `file()` loader [[parser function](<https://docs.astro.build/en/guides/content-collections/#parser-function>)]. This allows you to treat a single nested JSON document as a collection, though for long-form writing, the `glob` approach above is generally better for performance and organization.

### Summary of options:
*   **The "Proper" way:** Use `reference` in your schema to link chapters to stories. Query and filter them in your Astro components using `getCollection()` [[Querying Collections](<https://web.archive.org/web/20241122154805/https://docs.astro.build/en/guides/content-collections/#querying-collections>)].
*   **The Single-File way:** If your story metadata and chapters are in one large JSON file, use the `parser` option in the `file()` loader to extract the specific arrays you need [[Nested .json documents](<https://docs.astro.build/en/guides/content-collections/#nested-json-documents>)].

The knowledge sources do not explicitly mention a way to "modify" a collection permanently after it is generated; instead, you are encouraged to use the querying and filtering methods to shape the data as needed for your UI.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------