title | description | type | stub | service | i18nReady |
---|---|---|---|---|---|
Payload CMS & Astro |
Add content to your Astro project using Payload as a CMS |
cms |
true |
Payload CMS |
true |
import { Steps } from '@astrojs/starlight/components';
PayloadCMS is a headless open-source content management system that can be used to provide content for your Astro project.
- 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 MongoDB database - PayloadCMS will ask you for a MongoDB connection string when creating a new project. You can set one up locally or use MongoDBAtlas to host a database on the web for free.
- A PayloadCMS REST API - Create a PayloadCMS project and connect it to your MongoDB database during the setup.
:::note[Choosing a template] During the PayloadCMS installation, you will be asked if you want to use a template.
Choosing any of the available templates at this step (such as 'blog') automatically generates additional collections for you to use. Otherwise, you will need to manually create your PayloadCMS collections. :::
Your Payload project template will contain a file called Posts.ts in src/collections/
. If you did not choose a template during installation that created a content collection for you, you can create a new Payload CMS Collection by adding this configuration file manually. The example below shows this file for a collection called posts
that requires title
, content
, and slug
fields:
import { CollectionConfig } from "payload/types";
const Posts: CollectionConfig = {
slug: "posts",
admin: {
useAsTitle: "title",
},
access: {
read: () => true,
},
fields: [
{
name: "title",
type: "text",
required: true,
},
{
name: "content",
type: "text",
required: true,
},
{
name: "slug",
type: "text",
required: true,
},
],
};
export default Posts;
import Users from "./collections/Users";
import Posts from "./collections/Posts";
export default buildConfig({
serverURL: "http://localhost:4321",
admin: {
user: Users.slug,
},
collections: [Users, Posts],
typescript: {
outputFile: path.resolve(__dirname, "payload-types.ts"),
},
graphQL: {
schemaOutputFile: path.resolve(__dirname, "generated-schema.graphql"),
},
});
```
This will make a new collection called "Posts" appear in your PayloadCMS Dashboard next to the "Users" collection.
-
Enter the "Posts" collection and create a new post. After saving it, you will notice the API URL appear in the bottom right corner.
-
With the dev server running, open
http://localhost:4321/api/posts
in your browser. You should see a JSON file containing the post you have created as an object.{ "docs":[ { "id":"64098b16483b0f06a7e20ed4", "title":"Astro & PayloadCMS Title 🚀", "content":"Astro & PayloadCMS Content", "slug":"astro-payloadcms-slug", "createdAt":"2023-03-09T07:30:30.837Z", "updatedAt":"2023-03-09T07:30:30.837Z" } ], "totalDocs":1, "limit":10, "totalPages":1, "page":1, "pagingCounter":1, "hasPrevPage":false, "hasNextPage":false, "prevPage":null, "nextPage":null }
:::tip
By default, both Astro and PayloadCMS will use port 4321. You might want to change the PayloadCMS port in the src/server.ts
file. Don't forget to update the serverURL
in src/payload.config.ts
as well.
:::
Fetch your PayloadCMS data through your site's unique REST API URL and the route for your content. (By default, PayloadCMS will mount all routes through /api
.) Then, you can render your data properties using Astro's set:html=""
directive.
Together with your post, PayloadCMS will return some top-level metadata. The actual documents are nested within the docs
array.
For example, to display a list of post titles and their content:
---
import HomeLayout from "../layouts/HomeLayout.astro";
const res = await fetch("http://localhost:5000/api/posts") // http://localhost:4321/api/posts by default
const posts = await res.json()
---
<HomeLayout title='Astro Blog'>
{
posts.docs.map((post) => (
<h2 set:html={post.title} />
<p set:html={post.content} />
))
}
</HomeLayout>
Create a blog index page src/pages/index.astro
to list each of your posts with a link to its own page.
Fetching via the API returns an array of objects (posts) that include, among others, the following properties:
title
content
slug
---
import HomeLayout from "../layouts/HomeLayout.astro";
const res = await fetch("http://localhost:5000/api/posts") // http://localhost:4321/api/posts by default
const posts = await res.json()
---
<HomeLayout title='Astro Blog'>
<h1>Astro + PayloadCMS 🚀</h1>
<h2>Blog posts list:</h2>
<ul>
{
posts.docs.map((post) =>(
<li>
<a href={`posts/${post.slug}`} set:html={post.title} />
</li>
))
}
</ul>
</HomeLayout>
Create a page src/pages/posts/[slug].astro
to dynamically generate a page for each post.
---
import PostLayout from "../../layouts/PostLayout.astro"
const {title, content} = Astro.props
// The getStaticPaths() is required for static Astro sites.
// If using SSR, you will not need this function.
export async function getStaticPaths() {
let data = await fetch("http://localhost:5000/api/posts")
let posts = await data.json()
return posts.docs.map((post) => {
return {
params: {slug: post.slug},
props: {title: post.title, content: post.content},
};
});
}
---
<PostLayout title={title}>
<article>
<h1 set:html={title} />
<p set:html={content} />
</article>
</PostLayout>
To deploy your site visit our deployment guide and follow the instructions for your preferred hosting provider.
- Try this Payload CMS & Astro Template.
- Check out Astroad for easy development and VPS deployment with Docker.