How to Use Prismic with Astro: Complete Guide
Step-by-step guide to integrating Prismic with your Astro website.
Prismic is a headless page builder and CMS built around "slices," which are reusable content components that editors can mix and match to build pages. If you have worked with other headless CMS platforms and found the content modeling too rigid, Prismic's slice-based approach will feel refreshing. Paired with Astro, you get a fast static site with content that non-technical editors can manage through a clean visual interface.
The integration works by fetching content from Prismic's API at build time, letting Astro generate static pages from your CMS data. There is no dedicated @prismicio/astro package, so this guide uses Prismic's framework-agnostic JavaScript client (@prismicio/client), which makes the connection simple.
Prerequisites
- Node.js 22.12.0 or higher (Astro 6 raised its minimum runtime; its
enginesfield requiresnode >=22.12.0) - An Astro project (
npm create astro@latest). This guide is written against Astro 6.x. - A Prismic account with a repository created (a free tier is available)
Installation
Install the Prismic client library. As of @prismicio/client v7, all the templating helpers (asText, asHTML, asDate, asLink) and the TypeScript types live inside this single package, so you do not need anything else for fetching and rendering content:
npm install @prismicio/client
Do not install @prismicio/helpers. It was deprecated when its code was merged into @prismicio/client v7. The npm registry now flags it with "Package no longer supported," and importing helpers from it will break on a future major. If you are upgrading an older project, remove @prismicio/helpers and @prismicio/types from your package.json and import everything from @prismicio/client instead.
Configuration
Create a Prismic client file that you can import anywhere in your project:
// src/lib/prismic.ts
import * as prismic from "@prismicio/client";
const repositoryName = import.meta.env.PRISMIC_REPOSITORY;
export const client = prismic.createClient(repositoryName, {
accessToken: import.meta.env.PRISMIC_ACCESS_TOKEN,
});
Add your credentials to .env:
PRISMIC_REPOSITORY=your-repo-name
PRISMIC_ACCESS_TOKEN=your-access-token
You can find the repository name in your Prismic dashboard URL (e.g., your-repo-name.prismic.io). The access token is generated under Settings > API & Security.
Set up your custom types in the Prismic dashboard. For a blog, create a "Blog Post" repeatable type with fields like title (Key Text), content (Rich Text), excerpt (Key Text), and featured_image (Image).
Basic Usage
Fetch all blog posts and render them on an index page:
---
// src/pages/blog/index.astro
import { client } from "../../lib/prismic";
import * as prismic from "@prismicio/client";
import BaseLayout from "../../layouts/BaseLayout.astro";
const posts = await client.getAllByType("blog_post", {
orderings: [{ field: "document.first_publication_date", direction: "desc" }],
});
---
<BaseLayout title="Blog">
<h1>Blog</h1>
{posts.map((post) => (
<article>
<a href={`/blog/${post.uid}`}>
<h2>{prismic.asText(post.data.title)}</h2>
<p>{post.data.excerpt}</p>
</a>
</article>
))}
</BaseLayout>
The helper functions are now namespaced under the same prismic import you use for createClient. The orderings parameter takes an array of { field, direction } objects, where direction is "asc" or "desc", which matches the current getAllByType signature.
For individual post pages, use dynamic routing with getStaticPaths:
---
// src/pages/blog/[slug].astro
import { client } from "../../lib/prismic";
import * as prismic from "@prismicio/client";
import BaseLayout from "../../layouts/BaseLayout.astro";
export async function getStaticPaths() {
const posts = await client.getAllByType("blog_post");
return posts.map((post) => ({
params: { slug: post.uid },
props: { post },
}));
}
const { post } = Astro.props;
const htmlContent = prismic.asHTML(post.data.content);
---
<BaseLayout title={prismic.asText(post.data.title)}>
<article>
<h1>{prismic.asText(post.data.title)}</h1>
{post.data.featured_image?.url && (
<img src={post.data.featured_image.url} alt={post.data.featured_image.alt || ""} />
)}
<div set:html={htmlContent} />
</article>
</BaseLayout>
In v7 the asHTML and asText options are passed as an object rather than positional arguments. The simple calls above need no options, but if you previously wrote asHTML(field, linkResolver, serializer) you now write asHTML(field, { linkResolver, serializer }), and asText(field, separator) becomes asText(field, { separator }).
Because both pages above are pre-rendered with getStaticPaths, no adapter is required. Astro 6 builds to output: 'static' by default, so the Prismic data is fetched once at build time and frozen into HTML.
Working with slices is where Prismic really shines. Each slice maps to a component:
---
// src/components/SliceZone.astro
import TextBlock from "./slices/TextBlock.astro";
import ImageGallery from "./slices/ImageGallery.astro";
import CallToAction from "./slices/CallToAction.astro";
const { slices } = Astro.props;
const components = {
text_block: TextBlock,
image_gallery: ImageGallery,
call_to_action: CallToAction,
};
---
{slices.map((slice) => {
const Component = components[slice.slice_type];
return Component ? <Component slice={slice} /> : null;
})}
Production Tips
Use Prismic's image optimization. Prismic serves images through Imgix, so you can append query parameters for resizing, format conversion, and quality adjustments. Add
?w=800&fm=webpto image URLs for automatic WebP conversion at the right size.Implement preview mode. Prismic supports content previews so editors can see unpublished changes. Set up an API route in Astro that handles the preview token and redirects to the right page with draft content. Preview routes render on demand, so they need
export const prerender = falseand an installed adapter (for example@astrojs/node). Switching one route to on-demand does not change the rest of your build, which stays static.Cache API responses during builds. If you have hundreds of documents, each
getStaticPathscall hits Prismic's API. Use thefetchLinksoption to grab related content in a single query instead of making separate requests for linked documents.Set up webhooks for automatic rebuilds. In Prismic's settings, add a webhook URL pointing to your hosting platform's build trigger (Vercel, Netlify, etc.). Every time content is published, the site rebuilds automatically.
Use TypeScript types for your custom types. The correct tool is prismic-ts-codegen, not the old @prismicio/types-generator name. Install it as a dev dependency (npm install --save-dev prismic-ts-codegen), run npx prismic-ts-codegen init once to create prismicCodegen.config.ts, then run npx prismic-ts-codegen to generate types.generated.ts from your custom type and slice models. The generated file augments @prismicio/client automatically, so client.getAllByType("blog_post") becomes fully typed and field name typos fail at compile time instead of runtime. Re-run the command whenever you edit a model.
Alternatives to Consider
- Contentful if you need a more mature ecosystem with more third-party integrations and a larger community.
- Storyblok if you want a similar visual editing experience with an official Astro integration.
- TinaCMS if you prefer a Git-backed CMS that stores content directly in your repository.
Common Errors and Fixes
"Cannot find module @prismicio/helpers" or deprecation warnings on install. This package is deprecated and was merged into @prismicio/client v7. Remove @prismicio/helpers (and @prismicio/types) from package.json and change every import * as prismicH from "@prismicio/helpers" to import * as prismic from "@prismicio/client". All of asText, asHTML, asDate, asLink, and friends are exported from the client package now.
output: 'hybrid' throws "is an invalid option." The hybrid value was removed in Astro 5 and is still gone in Astro 6. The default is output: 'static', and you opt individual routes into on-demand rendering with export const prerender = false. Use output: 'server' only if you want on-demand by default and want to opt static pages back in with export const prerender = true. Delete any leftover output: 'hybrid' line from astro.config.mjs.
"To render any page on demand, you need to add an adapter." Static pages built with getStaticPaths never trigger this. It appears when a route is on-demand (a Prismic preview endpoint, for example) but no adapter is installed. Run npx astro add node (or your host's adapter) so on-demand routes have a runtime.
asHTML ignores your link resolver or serializer. v7 changed the signature from positional arguments to an options object. asHTML(field, linkResolver, serializer) silently drops those arguments now. Use asHTML(field, { linkResolver, serializer }).
Empty rich text renders as the string [object Object] or nothing. A Prismic rich text field is an array of nodes, not a string. Always pass it through prismic.asHTML(...) (or asText(...)) before placing it in a template, and inject the HTML with Astro's set:html directive rather than interpolating the raw field.
npx @prismicio/types-generator is not found. That package name is outdated. The current generator is prismic-ts-codegen. Install it as a dev dependency and run npx prismic-ts-codegen init followed by npx prismic-ts-codegen.
Published content does not appear on the live site. Astro fetches Prismic at build time, so a publish in Prismic does not change a static site until it rebuilds. Wire a Prismic webhook to your host's deploy hook so every publish triggers a fresh build.
Official Docs and Examples
- Astro CMS guide for Prismic: docs.astro.build/en/guides/cms/prismic
- Astro on-demand rendering and
outputoptions: docs.astro.build/en/guides/on-demand-rendering @prismicio/clientv7 technical reference: prismic.io/docs/technical-reference/prismicio-client/v7@prismicio/clientv7 migration guide (helpers and types removal): prismic.io/docs/prismicio-client-v7-migration-guideprismic-ts-codegenreference: prismic.io/docs/technical-reference/prismic-ts-codegen/v1- Example repo, a real Astro blog starter on Prismic: github.com/a-trost/astro-prismic-blog-starter
- Prismic blog tutorial source repo: github.com/prismicio-community/prismic-blog-tutorial
Wrapping Up
Prismic's slice-based content model and Astro's component-driven architecture are a natural fit. Editors get a visual page builder without touching code, and developers get clean APIs with predictable data structures. The free tier is generous enough for personal projects and small businesses, and the setup is straightforward once you have the client configured. If your project needs a CMS where non-developers can build flexible page layouts, Prismic is a strong choice.
Sources
All package versions and facts verified on 2026-05-29.
- @prismicio/client on the npm registry (v7.21.8)
- @prismicio/helpers on the npm registry (v2.3.9, flagged deprecated: "Package no longer supported")
- astro on the npm registry (v6.4.2)
- @astrojs/node on the npm registry (v10.1.2)
- prismic-ts-codegen on the npm registry (v0.1.30)
- @prismicio/client v7 migration guide
- @prismicio/client v7 unified core library announcement
- @prismicio/client v7 technical reference (createClient, getAllByType, orderings)
- prismic-ts-codegen technical reference
- Astro on-demand rendering docs (output modes, prerender, adapters)
- Astro CMS guide for Prismic
- a-trost/astro-prismic-blog-starter example repo
Related Articles
How to Use Algolia with Astro: Complete Guide
Step-by-step guide to integrating Algolia with your Astro website.
How to Integrate Auth0 with Astro: Complete Guide
Step-by-step guide to integrating Auth0 with your Astro website. Setup, configuration, and best practices.
How to Use AWS Amplify with Astro: Complete Guide
Step-by-step guide to integrating AWS Amplify with your Astro website.