Skip to content

Cosmic & Astro

Add content to your Astro project using Cosmic as a CMS

Cosmic is a headless CMS that provides an admin dashboard to manage content and an API that can integrate with a diverse range of frontend tools.

  1. An Astro project - If you’d like to start with a fresh Astro project, read the installation guide. This guide uses Tailwind CSS for styling.
  2. A Cosmic account and Bucket - Create a free Cosmic account if you don’t have one. After creating your account, you’ll be prompted to create a new empty project. There’s also a Simple Astro Blog template available (this is the same template as the Astro Headless CMS Theme) to automatically import all of the content used in this guide.
  3. Your Cosmic API keys - From your Cosmic dashboard, you will need to locate both the Bucket slug and Bucket read key in order to connect to Cosmic.

Add the Cosmic JavaScript SDK to fetch data from your Cosmic Bucket.

Create a .env file at the root of your Astro project (if it does not already exist). Add both the Bucket slug and Bucket read key available from your Cosmic dashboard as public environment variables.

.env
PUBLIC_COSMIC_BUCKET_SLUG=YOUR_BUCKET_SLUG
PUBLIC_COSMIC_READ_KEY=YOUR_READ_KEY

You can manage your Astro blog’s content using Cosmic and create webhooks to automatically redeploy your website when you update or add new content.

The following instructions assume that you have an Object Type in Cosmic called posts. Each individual blog post is a post that is defined in the Cosmic dashboard with the following Metafields:

  1. Text input - Author
  2. Image - Cover Image
  3. Repeater - Tags
    • Text input - Title
  4. Text area - Excerpt
  5. Rich Text - Content

Using the same data-fetching method as above, import the getAllPosts() query from your script file and await the data. This function provides metadata about each post which can be displayed dynamically.

The example below passes these values to a <Card /> component to display a formatted list of blog posts:

src/pages/index.astro
---
import Card from '../components/Card.astro'
import { getAllPosts } from '../lib/cosmic'
const data = await getAllPosts()
---
<section>
<ul class="grid gap-8 md:grid-cols-2">
{
data.map((post) => (
<Card
title={post.title}
href={post.slug}
body={post.metadata.excerpt}
tags={post.metadata.tags.map((tag) => tag)}
/>
))
}
</ul>
</section>

Generating Individual Blog Posts with Astro

Section titled “Generating Individual Blog Posts with Astro”

To generate an individual page with full content for each blog post, create a dynamic routing page at src/pages/blog/[slug].astro.

This page will export a getStaticPaths() function to generate a page route at the slug returned from each post object. This function is called at build time and generates and renders all of your blog posts at once.

To access your data from Cosmic:

  • Query Cosmic inside of getStaticPaths() to fetch data about each post and provide it to the function.
  • Use each post.slug as a route parameter, creating the URLs for each blog post.
  • Return each post inside of Astro.props, making the post data available to HTML template portion of the page component for rendering.

The HTML markup below uses various data from Cosmic, such as the post title, cover image, and the rich text content (full blog post content). Use set:html on the element displaying the rich text content from Cosmic to render HTML elements on the page exactly as fetched from Cosmic.

src/pages/blog/[slug].astro
---
import { getAllPosts } from '../../lib/cosmic'
import { Image } from 'astro:assets'
export async function getStaticPaths() {
const data = (await getAllPosts()) || []
return data.map((post) => {
return {
params: { slug: post.slug },
props: { post }
}
})
}
const { post } = Astro.props
---
<article class="mx-auto max-w-screen-md pt-20">
<section class="border-b pb-8">
<h1 class="text-4xl font-bold">{post.title}</h1>
<div class="my-4"></div>
<span class="text-sm font-semibold">{post.metadata.author?.title}</span>
</section>
{
post.metadata.cover_image && (
<Image
src={post.metadata.cover_image.imgix_url}
format="webp"
width={1200}
height={675}
aspectRatio={16 / 9}
quality={50}
alt={`Cover image for the blog ${post.title}`}
class={'my-12 rounded-md shadow-lg'}
/>
)
}
<div set:html={post.metadata.content} />
</article>

To deploy your website, visit the deployment guides and follow the instructions for your preferred hosting provider.

You can set up a webhook in Cosmic directly to trigger a redeploy of your site on your hosting platform (e.g. Vercel) whenever you update or add content Objects.

Under “Settings” > “webhooks”, add the URL endpoint from Vercel and select the Object Type you would like to trigger the webhook. Click “Add webhook” to save it.

To set up a webhook in Netlify:

To set up a webhook in Vercel: