Strapi & Astro
Strapi is an open-source, customizable, headless CMS.
Integrating with Astro
Section titled Integrating with AstroThis guide will build a wrapper function to connect Strapi with Astro.
Prerequisites
Section titled PrerequisitesTo get started, you will need to have the following:
- An Astro project - If you don’t have an Astro project yet, our Installation guide will get you up and running in no time.
- A Strapi CMS server - You can set up a Strapi server on a local environment.
Adding the Strapi URL in .env
Section titled Adding the Strapi URL in .envTo add your Strapi URL to Astro, create a .env
file in the root of your project (if one does not already exist) and add the following variable:
STRAPI_URL="http://127.0.0.1:1337" # or use your IP address
Restart the dev server to use this environment variable in your Astro project.
If you would like to have IntelliSense for your environment variable, you can create a env.d.ts
file in the src/
directory and configure ImportMetaEnv
like this:
interface ImportMetaEnv { readonly STRAPI_URL: string;}
Your root directory should now include the new file(s):
Directorysrc/
- env.d.ts
- .env
- astro.config.mjs
- package.json
Creating the API wrapper
Section titled Creating the API wrapperCreate a new file at src/lib/strapi.ts
and add the following wrapper function to interact with the Strapi API:
interface Props { endpoint: string; query?: Record<string, string>; wrappedByKey?: string; wrappedByList?: boolean;}
/** * Fetches data from the Strapi API * @param endpoint - The endpoint to fetch from * @param query - The query parameters to add to the url * @param wrappedByKey - The key to unwrap the response from * @param wrappedByList - If the response is a list, unwrap it * @returns */export default async function fetchApi<T>({ endpoint, query, wrappedByKey, wrappedByList,}: Props): Promise<T> { if (endpoint.startsWith('/')) { endpoint = endpoint.slice(1); }
const url = new URL(`${import.meta.env.STRAPI_URL}/api/${endpoint}`);
if (query) { Object.entries(query).forEach(([key, value]) => { url.searchParams.append(key, value); }); } const res = await fetch(url.toString()); let data = await res.json();
if (wrappedByKey) { data = data[wrappedByKey]; }
if (wrappedByList) { data = data[0]; }
return data as T;}
This function requires an object with the following properties:
endpoint
- The endpoint you are fetching.query
- The query parameters to add to the end of URLwrappedByKey
- Thedata
key in the object that wraps yourResponse
.wrappedByList
- A parameter to “unwrap” the list returned by Strapi, and return only the first item.
Optional: Creating the Article interface
Section titled Optional: Creating the Article interfaceIf you are using TypeScript, create the following Article interface to correspond to the Strapi content types at src/interfaces/article.ts
:
export default interface Article { id: number; attributes: { title: string; description: string; content: string; slug: string; createdAt: string; updatedAt: string; publishedAt: string; };}
You can modify this interface, or create multiple interfaces, to correspond to your own project data.
Directorysrc/
Directoryinterfaces/
- article.ts
Directorylib/
- strapi.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
Displaying a list of articles
Section titled Displaying a list of articles-
Update your home page
src/pages/index.astro
to display a list of blog posts, each with a description and a link to its own page. -
Import the wrapper function and the interface. Add the following API call to fetch your articles and return a list:
src/pages/index.astro ---import fetchApi from '../lib/strapi';import type Article from '../interfaces/article';const articles = await fetchApi<Article[]>({endpoint: 'articles', // the content type to fetchwrappedByKey: 'data', // the key to unwrap the response});---The API call requests data from
http://localhost:1337/api/articles
and returnsarticles
: an array of json objects representing your data:[{id: 1,attributes: {title: "What's inside a Black Hole",description: "Maybe the answer is in this article, or not...",content: "Well, we don't know yet...",slug: "what-s-inside-a-black-hole",createdAt: "2023-05-28T13:19:46.421Z",updatedAt: "2023-05-28T13:19:46.421Z",publishedAt: "2023-05-28T13:19:45.826Z"}},// ...] -
Using data from the
articles
array returned by the API, display your Strapi blog posts in a list. These posts will link to their own individual pages, which you will create in the next step.src/pages/index.astro ---import fetchApi from '../lib/strapi';import type Article from '../interfaces/article';const articles = await fetchApi<Article[]>({endpoint: 'articles?populate=image',wrappedByKey: 'data',});---<!DOCTYPE html><html lang="en"><head><title>Strapi & Astro</title></head><body><main><ul>{articles.map((article) => (<li><a href={`/blog/${article.attributes.slug}/`}>{article.attributes.title}</a></li>))}</ul></main></body></html>