placeholder til
Astro 7 no longer discovers legacy src/content directories from type: "content" alone. A collection needs an explicit loader that tells Astro where its entries live.
The surprising part is that a production build can still exit successfully. Pages backed by getStaticPaths() may simply generate no detail routes because the collection is empty.
Define the loader
Import glob from astro/loaders, then point it at the collection directory:
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "zod";
const notes = defineCollection({
loader: glob({
base: "./src/content/notes",
pattern: "**/*.{md,mdx}",
}),
schema: z.object({
title: z.string(),
pubDate: z.coerce.date(),
}),
});
Using Zod as a direct dependency also avoids resolving an older transitive copy when multiple integrations depend on different Zod major versions.
Verify generated routes
Type checking confirms that the schema and consumers agree, but it does not prove that entries were loaded. After a content-layer migration, inspect the production build output and confirm that every expected slug was prerendered.
For this portfolio, that meant checking all project and blog detail routes rather than accepting a successful exit code by itself.