komal.nakrani
Browse Themes
ThemesCategoriesDocsBlogTips & Tricks
Content & MDX••By Komal Nakrani

Fix: Legacy Content Config File Found in Astro

Astro's 'Legacy content config file found' means src/content/config.ts must move to src/content.config.ts, with a loader on every collection. Steps and gotchas.

#Astro#Errors#Content Collections#Upgrade

Astro shows “Legacy content config file found” when your project still has src/content/config.ts, the location used before the Content Layer API. The message tells you exactly what to do: move the file to src/content.config.ts and “ensure each collection has a loader defined.” It usually appears right after upgrading an older project to a current Astro version.

Key Takeaways

  • Move src/content/config.ts to src/content.config.ts (one level up, new name).
  • Fix the relative imports inside it after the move.
  • Add a loader to every collection.
  • Update slug → id and entry.render() → render(entry) across pages.

Step 1: move the file

git mv src/content/config.ts src/content.config.ts

The file is now one folder higher, so relative imports inside it change:

- import { site } from '../data/site';
+ import { site } from './data/site';

Step 2: add loaders

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

const blog = defineCollection({
  loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
  schema: z.object({
    title: z.string(),
    pubDate: z.coerce.date(),
  }),
});

export const collections = { blog };

Without this you’ll get the next error in the chain: Content collection is missing a loader.

Step 3: update pages

  export async function getStaticPaths() {
    const posts = await getCollection('blog');
-   return posts.map((post) => ({ params: { slug: post.slug }, props: { post } }));
+   return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
  }

- const { Content } = await post.render();
+ const { Content } = await render(post);

Add render to the import from astro:content. Search the project for .slug and .render( to catch every use.

Step 4: regenerate types

npx astro sync

Then npx astro check to surface remaining type errors.

If you can’t migrate yet

Setting legacy.collectionsBackwardsCompat: true in astro.config.mjs keeps the old location and API working temporarily. Use it to unblock a deploy, and schedule the migration.

Check your ids didn’t change

Legacy collections derived slugs differently in some cases, for example from a slug frontmatter field. Compare built URLs before and after (npm run build lists them) and add redirects for any that moved.

The Astro content collections guide has the full migration checklist. The official steps are in the Astro v6 upgrade guide.

FAQ

Can I keep the config in JavaScript instead of TypeScript?

Yes. src/content.config.js and .mjs work too. TypeScript gives you better editor feedback.

Do my Markdown files have to move?

No. Only the config file moves. Point each glob() loader’s base at wherever the content lives.