Astro 4.14 is out now! This release includes the first experimental release of the Content Layer API, our new super-flexible solution for managing content in Astro projects, support for Intellisense inside content files, and more.
This release includes the following highlights:
- Experimental: Content Layer API
- Experimental: Intellisense inside content files
- Deprecate support for dynamic
prerender
values - New
injectTypes
integration API - Support for metastrings in the Code component
To upgrade an existing project, use the automated @astrojs/upgrade
CLI tool. Alternatively, upgrade manually by running the upgrade command for your package manager:
# Recommended:npx @astrojs/upgrade
# Manual:npm install astro@latestpnpm upgrade astro --latestyarn upgrade astro --latest
Experimental: Content Layer API
In Astro 2.0 we introduced Content Collections, a powerful way to manage local content in Astro projects. While this has helped hundreds of thousands of developers build content-driven sites with Astro, we’ve heard your feedback that you want more flexibility and power in managing your content. We’re excited to announce the experimental release of the next generation of content collections in Astro: the Content Layer API.
The new Content Layer API builds upon content collections, taking them beyond local files in src/content/
and allowing you to fetch content from anywhere, including remote APIs. These new collections work alongside your existing content collections, and you can migrate them to the new API at your own pace. We think you’ll want to soon, because they have lots of advantages, but there’s no rush – the existing collections will continue to work as they always have.
Performance
The Content Layer API is the first step in scaling Astro to support fast builds for sites with tens or hundreds of thousands of pages. The new API is designed to be more efficient and performant in the way it loads content. It caches content locally to avoid the need to keep hitting APIs and has dramatically improved handling of local Markdown and MDX files. This benchmark shows the performance when building a site with 10,000 pages on a Macbook Air M1:
Astro 4.13 | Astro 4.14 (Content Layer) | |||
---|---|---|---|---|
Markdown | Build Time | 136.29s | 25.96s | 5.3x faster |
Memory | 763.50MB | 276.22MB | 64% less | |
MDX | Build Time | 129.82s | 66.70s | 1.9x faster |
Memory | 897.91MB | 674.39MB | 25% less |
We plan to continue improving the performance of the Content Layer API in future releases, including adding support for a SQLite backend to handle even larger sites.
Getting started
To try out the new Content Layer API, enable it in your Astro config:
import { defineConfig } from 'astro/config';
export default defineConfig({ experimental: { contentLayer: true }})
You can then create collections in your src/content/config.ts
using the Content Layer API.
Loading your content
The core of the new Content Layer API is the loader, a function that fetches content from a source and caches it in a local data store. Astro 4.14 ships with built-in glob()
and file()
loaders to handle your local Markdown, MDX, Markdoc, and JSON files:
// src/content/config.tsimport { defineCollection, z } from 'astro:content';import { glob } from 'astro/loaders';
const blog = defineCollection({ // The ID is a slug generated from the path of the file relative to `base` loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }), schema: z.object({ title: z.string(), description: z.string(), publishDate: z.coerce.date(), })});
export const collections = { blog };
You can then use the content in your site:
---import { getEntry, render } from 'astro:content';
const post = await getEntry('blog', Astro.params.slug);
const { Content } = await render(entry);---
<Content />
Creating a loader
You’re not restricted to the built-in loaders – we hope you’ll try building your own. You can fetch content from anywhere and return an array of entries:
// src/content/config.tsconst countries = defineCollection({ loader: async () => { const response = await fetch("https://restcountries.com/v3.1/all"); const data = await response.json(); // Must return an array of entries with an id property, // or an object with IDs as keys and entries as values return data.map((country) => ({ id: country.cca3, ...country, })); }, // optionally add a schema to validate the data and make it type-safe for users // schema: z.object...});
export const collections = { countries };
For more advanced loading logic, you can define an object loader. This allows incremental updates and conditional loading while also giving full access to the data store. It also allows a loader to define its own schema, including generating it dynamically based on the source API. See the the Content Layer API RFC for more details.
Sharing your loaders
Loaders are better when they’re shared! You can create a module that exports a loader and publish it to npm, and then anyone can use it on their site. Tag your packages with the keyword astro-loader
so they can be found. We’re excited to see what the community comes up with! To get started, take a look at some examples. Here’s how to load content using an RSS/Atom feed loader:
// src/content/config.tsimport { defineCollection } from "astro:content";import { feedLoader } from "@ascorbic/feed-loader";
const podcasts = defineCollection({ loader: feedLoader({ url: "https://feeds.99percentinvisible.org/99percentinvisible", }),});
export const collections = { podcasts };
Learn more
To find out more about using the Content Layer API, check out the Content Layer RFC and share your feedback.
Experimental: Intellisense inside content files
Astro 4.14 introduces experimental support for Intellisense inside the frontmatter of your content. This feature helps you write content files more efficiently by providing completions, validation, hover information, and more for frontmatter keys and values. These tools are based on your content schemas, and available directly in your editor.
This feature is available in VS Code and other editors that support the Language Server Protocol for Markdown, MDX, and Markdoc files.
To enable content file intellisense, add the following to your Astro config:
import { defineConfig } from 'astro';
export default defineConfig({ experimental: { contentIntellisense: true }})
and in VS Code, enable the astro.content-intellisense
setting. For other editors, pass contentIntellisense: true
to the initialization parameters of the Astro language server.
{ "astro.content-intellisense": true}
This feature currently only works in the editor and will be enabled in astro check
in a future release.
Deprecate support for dynamic prerender
values
In order to improve our bundling and tree-shaking capabilities, Astro 4.14 deprecates support for using dynamic values for the prerender
option in your Astro pages.
This feature can now be replaced with the new astro:route:setup
hook in Astro integrations, which allows you to dynamically control the prerendering of specific pages.
--- export const prerender = import.meta.env.PROD;---
// astro.config.mjsimport { defineConfig } from 'astro/config';
export default defineConfig({ integrations: [setPrerender()],});
function setPrerender() { return { name: 'set-prerender', hooks: { 'astro:route:setup': ({ route }) => { if (route.component.endsWith('/blog/[slug].astro')) { route.prerender = true; } }, }, };}
New injectTypes
integration API
Type generation has become all the rage in recent years, and Astro is no exception! We use type generation pretty extensively for features like Astro DB and Content Collections (or the new Content Layer API).
Thanks to @florian-lefebvre, Astro integrations can now join the fun with the new injectTypes
integration API! This API allows integrations to inject types into the user’s project, making it easier to provide type definitions for your integration’s features.
// my-integration/index.jsexport default { name: 'my-integration', 'astro:config:done': ({ injectTypes }) => { injectTypes({ filename: "types.d.ts", content: "declare module 'virtual:my-integration' {}" }) }};
For more information on this feature, check out the Astro integration API documentation.
Support for metastrings in the Code component
Astro 4.14 adds support for the meta
attribute in the Code
component. This attribute simulates using properties on code blocks in Markdown, for example ```js astro=cool
, which can then be used by Shiki transformers to apply custom transformations to the code block.
---import { Code } from "astro:components";import { transformerMetaHighlight } from '@shikijs/transformers';---<Code code={code} lang="js" transformers={[transformerMetaHighlight()]} meta="{1,3}" />
Thanks to @jcayzac for this contribution!
Bug Fixes and Special Thanks
As we do, Astro 4.14 includes more bug fixes and smaller improvements that couldn’t make it into this post! Check out the full release notes to learn more.
Thanks to Sarah Rainsberger (@sarah11918), Yan (@yanthomasdev), Bjorn Lu (@bluwy) and everyone else who contributed to this release.