Astro Crash Course #9 - Content Collections (with Markdown)
Chapters7
Switch from a single JSON file to per-book markdown files to store review content with proper structure.
Switching from JSON to Markdown content with Astro’s glob loader unlocks scalable, per-book pages while keeping the same collection API you already use.
Summary
Net Ninja’s Astro Crash Course #9 shows how to migrate a content collection from a single JSON source to multiple Markdown files. By placing book data in separate Markdown files under content/books and using front matter for metadata, the author demonstrates that Astro’s collections API remains consistent across data sources. The key change is replacing the file loader with the glob loader to fetch all MD files, letting Astro automatically derive IDs from file names. This approach scales better for long-form content like book reviews, where each entry deserves its own page. The lesson also highlights organizing data types with dedicated subfolders (e.g., books, blogs) to prevent mixing content. Finally, Net Ninja points out that the content’s front matter defines the schema while the Markdown body holds the rich text, and shows how to wire the ID into the book links for detail pages. The example also notes that while the detail pages aren’t yet created, the routing works and the hrefs correctly reference /books/{id}.
Key Takeaways
- Replace the file loader with astro/loaders glob in content.config to load multiple Markdown files from source/content/books.
- Base path for glob is set to 'source/content/books' and the pattern '*.MD' ensures every Markdown file is loaded automatically.
- IDs are derived from file names (without the .md extension) when using Markdown data sources, so the 'id' field in front matter is unnecessary.
- Front matter must still define book metadata (title, author, summary, rating) exactly as before; content blocks live in the Markdown body.
- Anchor hrefs for each book card can be dynamically constructed as /books/{id} by outputting the auto-generated ID in a template string.
- Organizing data into subfolders (e.g., books vs. blogs) prevents cross-type data mixing and keeps the content pipeline tidy.
- Previewing requires creating the individual book pages later, but the navigation structure and IDs are correctly wired now.
Who Is This For?
Essential viewing for Astro developers migrating from a JSON-backed content model to Markdown-backed collections, especially for building scalable, multi-page content like book reviews.
Notable Quotes
"The only thing missing is the ID property. And the reason we don't need that when we're using multiple markdown files for a data source is because the file name of each markdown file is going to be automatically used by Astro as the ID."
—Explains why IDs aren’t needed in front matter when using markdown files—the ID comes from the file name.
"So this loader now loads all the content from all those files and processes the data in the same unified way."
—Describes switching to the glob loader to aggregate multiple Markdown files.
"The file function only loads a single file. But now we've got multiple markdown files that we need to load data from."
—Clarifies the reason for replacing the file loader with glob.
"And we'll see exactly how to access the markdown content later on."
—Indicates there’s more to learn about accessing Markdown content beyond metadata.
Questions This Video Answers
- How do I switch a content collection from a JSON source to Markdown-backed files in Astro?
- What is astro/loaders glob and how do I use it to load multiple Markdown files?
- How are IDs assigned when using Markdown files in Astro collections?
- How should I structure content folders in Astro to avoid mixing data types like books and blogs?
- How do I construct dynamic links to detail pages for each Markdown entry in Astro?
AstroAstro Content CollectionsMarkdown front matterastro/loaders globdata organization in Astrodynamic routes with generated IDscontent.configbook reviewsfrontend links for detail pages
Full Transcript
All right then, my friends. In the last lesson, we saw how to define a content collection where the data source was a JSON file. But I think for something like a book review site, a markdown file for each review would be better suited rather than trying to stuff a load of review content into a single JSON file because eventually each book is going to have its own page with a lot of content on it. And in a markdown file, we can structure that content with things like headings, lists, line breaks, quotations, and so on. So in this lesson, we're going to restructure the collections we defined so that it queries markdown files instead of the single JSON file.
And the good thing is we won't need to update any of the code in the components where we use the collection because Astro unifies how we use collections no matter where the data source is behind the collections API. So it doesn't matter that we'll be using markdown files instead of JSON. The way we access the collection from a component remains the same. And the only thing we need to do is really update where we define the collection itself. So then I've already created a new books folder inside the content folder. And inside that I've put a few markdown files which by the way you can grab from the course files repo if you want to use the same stuff.
And the names of these files are just the book titles. Now I've put them inside a books folder because that way if in the future I've got another kind of data like blogs or whatever else then they won't all get mixed up with each other. And each type of data can all have its own subfolder. So if we take a look at one of these files, then at the top you can see we've got some front matter where we define all those same book properties, the book metadata. So these are the properties as the same ones that we had in the JSON file, the title, the author, the summary, the rating.
The only thing missing is the ID property. And the reason we don't need that when we're using multiple markdown files for a data source is because the file name of each markdown file is going to be automatically used by Astro as the ID. So we don't need to manually add it here. [gasps] Anyway, below the front matter is a load of content with headings list and all that jazz. And all of this is AI generated by the way which is why it doesn't make much sense. So then we have the markdown content. And now all we need to do is update the collection we defined inside the content.config config file.
And we only need to change two things. First, we need to update the loader because the file function only loads a single file. But now we've got multiple markdown files that we need to load data from. So we should replace the file function with a different one called glob, which we also need to import from astro/loaders. And we can also delete the other import as well, the file one. Now the globe function allows us to supply a base path for the data which is going to be the books folder and then we also supply a file pattern so Astro can find all the relevant files in that base folder which match that pattern and it's going to load them.
Okay. So as the argument to this glob function then we pass in an object and we'll add the base property first which is where we supply that base folder path which is source slashcontent/books and then after that we'll add in the pattern property and the pattern of the files we want to source is going to be an asterisk and then MD. So this says find any file no matter what the file name is that ends in MD. So this loader now loads all the content from all those files and processes the data in the same unified way.
The only other thing we need to do is remove the ID property from the schema because that's no longer in the schema. And instead the ID is automatically pulled from the file name minus the MD extension. And by the way, we don't need to add anything to the schema for the content itself in the markdown file only for the properties in the front matter. And we'll see exactly how to access the markdown content later on. For now, before we preview this, I just want to do one more thing, and that is to use the autogenerate ids as hrefs in the link for each book.
So, if we open the book card component, we should see an empty anchor tag for a user to click on when they want to read more about this review. Right? I just want to quickly add the ID to this href. So to do that we'll make this dynamic by using curly braces. Then inside that I'll add back ticks to make a template string. And the first part of this path is going to be forward/books. Then another forward slash. Then we'll output the ID using a dollar sign and curly braces which is how we output a variable inside a template string.
Then book ID. And notice this time the ID is not attached to the data, right? It's added to the entry object directly. All right. So all of the books are still there. So this is working and if we now click on one of these links look at the page we go to for/books/assassin apprentice. So it's taking that ID the file name and using it in the href where we output that ID which is good. Now currently we get a 404 page much like we would for any of the others if we click on them because we don't have pages for this book's details yet.
But at least this functionality of the anchor tag is
More from Net Ninja
Get daily recaps from
Net Ninja
AI-powered summaries delivered to your inbox. Save hours every week while staying fully informed.









