/ astro-integrations / How to Use Prismic with Astro: Complete Guide
astro-integrations 8 min read

How to Use Prismic with Astro: Complete Guide

Step-by-step guide to integrating Prismic with your Astro website.

How to Use Prismic with Astro: Complete Guide

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 engines field requires node >=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

  1. 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=webp to image URLs for automatic WebP conversion at the right size.

  2. 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 = false and an installed adapter (for example @astrojs/node). Switching one route to on-demand does not change the rest of your build, which stays static.

  3. Cache API responses during builds. If you have hundreds of documents, each getStaticPaths call hits Prismic's API. Use the fetchLinks option to grab related content in a single query instead of making separate requests for linked documents.

  4. 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

    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.