Skip to content

Conversation

@matthewp
Copy link
Contributor

Changes

  • Add legacy.collectionsBackwardsCompat?: boolean (defaults to false)
    • When false (default): strict v6 behavior (no old-style collections)
    • When true: allows old-style collections to be defined and processed
  • Restore v5 logic that allows collections without loaders
  • Collections without loaders get type: 'content' by default (was throwing error)
  • Only validate loader presence IF a loader is defined in config
  • Changed from: 'must have loader' → to 'if loader exists, validate it'

Testing

No test changes

Docs

TODO - what should be document outside of the flag?

…ctions migration

PROBLEM
-------
In v5, content collections could be defined without a loader and would work via
automatic backwards compatibility mode (supporting v4-style collections). This
allowed old code to continue working without explicit migration.

In v6 (current next branch), we completely removed this backwards compat layer.
Collections without loaders now throw an error in defineCollection(), and old-style
collections (type: 'content' or type: 'data') are silently skipped during sync.

This creates a harsh upgrade path: users upgrading to v6 get hard errors if they
have legacy collections. They don't realize they're using deprecated patterns
because their code 'just worked' in v5.

SOLUTION
--------
Add a legacy.collectionsBackwardsCompat flag that provides an escape hatch for v6.
This allows projects to opt-in to backwards compatibility while they migrate, and
signals explicitly that they're using deprecated patterns.

IMPLEMENTATION DETAILS
----------------------

1. Config Schema Changes
   File: packages/astro/src/types/public/config.ts
   File: packages/astro/src/core/config/schemas/base.ts

   - Add legacy.collectionsBackwardsCompat?: boolean (defaults to false)
   - When false (default): strict v6 behavior (no old-style collections)
   - When true: allows old-style collections to be defined and processed

2. defineCollection() Logic Restoration
   File: packages/astro/src/content/config.ts

   - Restore v5 logic that allows collections without loaders
   - Collections without loaders get type: 'content' by default (was throwing error)
   - Only validate loader presence IF a loader is defined in config
   - Changed from: 'must have loader' → to 'if loader exists, validate it'

   This means:
   - Old code like: defineCollection({ schema: z.object(...) })
     now works instead of throwing ContentCollectionMissingLoader error
   - Collections get default type: 'content' if not specified

3. Content Layer Processing
   File: packages/astro/src/content/content-layer.ts

   - Check this.#settings.config.legacy?.collectionsBackwardsCompat before syncing
   - If flag is FALSE (default):
     * Skip collections with type: 'content' or type: 'data'
     * Skip collections without loaders
     * Only process loader-based collections (v6 strict mode)

   - If flag is TRUE (backwards compat enabled):
     * Process both loader-based AND old-style collections
     * Old-style collections still need their files to exist in the right location
     * But they work without explicit loader definitions

   - Made all loader access safe with 'loader' in collection guards

MIGRATION PATH
---------------
For projects upgrading to v6 with legacy collections:

1. Add to astro.config.mjs: legacy: { collectionsBackwardsCompat: true }
2. Content will continue working (same as v5)
3. At leisure, migrate collections one-by-one:
   - Add glob() or file() loader
   - Change type: 'content' to type: 'content_layer' (or omit type)
   - Verify it works
4. Remove the legacy flag once all collections are migrated

NOTES
-----
- This is v6-specific. v5 users don't see this flag (it exists but defaults to false)
- The flag name signals intent: 'backwards compat' is deprecated, not a permanent feature
- In Astro 7, we can remove this flag entirely
- This enables a smoother upgrade experience without encouraging long-term reliance
  on legacy patterns
@changeset-bot
Copy link

changeset-bot bot commented Nov 28, 2025

⚠️ No Changeset found

Latest commit: 734ebd4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added pkg: astro Related to the core `astro` package (scope) docs pr labels Nov 28, 2025
@ascorbic
Copy link
Contributor

ascorbic commented Dec 1, 2025

To be clear, this just add a flag for the checks, but it doesn't actually reimplement any backwards-compat that was removed in #14407

@matthewp
Copy link
Contributor Author

matthewp commented Dec 3, 2025

@ascorbic Correct, what I read from the thread was that there was concern that people wouldn't know what they needed to upgrade, so I created #14928 to give them errors when they don't use loaders (in v5) and this was to allow them get the simpleLoader if they don't provide a loader themselves.

I didn't add back any more of the compat because it wasn't clear to me from the thread what backwards compat was desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs pr pkg: astro Related to the core `astro` package (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants