Astro
Ghost & Astro
Ghost & Astro
}
:::tip
Read more about [using environment variables](/en/guides/environment-variables/) and `.env` files in Astro.
:::
Your root directory should now include these new files:
<FileTree title="Project Structure">
- src/
- **env.d.ts**
- **.env**
- astro.config.mjs
- package.json
</FileTree>
### Installing dependencies
To connect with Ghost, install the official content API wrapper [`@tryghost/content-api`](https://www.npmjs.com/package/@tryghost/content-api) using the command below for your preferred package manager, and optionally, a helpful package containing type definitions if you are using TypeScript:
<PackageManagerTabs>
<Fragment slot="npm">
```shell
npm install @tryghost/content-api
npm install --save @types/tryghost__content-api
Making a blog with Astro and Ghost
With the setup above, you are now able to create a blog that uses Ghost as the CMS.
Prerequisites
- A Ghost blog
- An Astro project integrated with the Ghost content API - See integrating with Astro for more details on how to set up an Astro project with Ghost.
This example will create an index page that lists posts with links to dynamically-generated individual post pages.
Fetching Data
You can fetch your site's data with the Ghost content API package.
First, create a ghost.ts file under a lib directory.
Initialize an API instance with the Ghost API using the API key from the Ghost dashboard's Integrations page.
// Create API instance with site credentials
Displaying a list of posts
The page src/pages/index.astro will display a list of posts, each with a description and link to its own page.
Import ghostClient() in the Astro frontmatter to use the posts.browse() method to access blog posts from Ghost. Set limit: all to retrieve all posts.
---
const posts = await ghostClient.posts
.browse({
limit: 'all',
})
.catch((err) => {
console.error(err);
});
---
Fetching via the content API returns an array of objects containing the properties for each post such as:
title- the title of the posthtml- the HTML rendering of the content of the postfeature_image- the source URL of the featured image of the postslug- the slug of the post
Use the posts array returned from the fetch to display a list of blog posts on the page.
---
const posts = await ghostClient.posts
.browse({
limit: 'all',
})
.catch((err) => {
console.error(err);
});
---
<html lang="en">
<head>
<title>Astro + Ghost 👻</title>
</head>
<body>
{
posts.map((post) => (
<a href={`/post/${post.slug}`}>
<h1> {post.title} </h1>
</a>
))
}
</body>
</html>
Generating pages
The page src/pages/post/[slug].astro dynamically generates a page for each post.
Import ghostClient() to access blog posts using posts.browse() and return a post as props to each of your dynamic routes.
---
});
return posts.map((post) => {
return {
params: {
slug: post.slug,
},
props: {
post: post,
},
};
});
}
const { post } = Astro.props;
---
Create the template for each page using the properties of each post object.
---
});
return posts.map((post) => {
return {
params: {
slug: post.slug,
},
props: {
post: post,
},
};
});
}
const { post } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<title>{post.title}</title>
</head>
<body>
<img src={post.feature_image} alt={post.title} />
<h1>{post.title}</h1>
<p>{post.reading_time} min read</p>
<Fragment set:html={post.html} />
</body>
</html>
:::note
<Fragment /> is a built-in Astro component which allows you to avoid an unnecessary wrapper element. This can be especially useful when fetching HTML from a CMS (e.g. Ghost or WordPress).
:::
Publishing your site
To deploy your site visit our deployment guide and follow the instructions for your preferred hosting provider.
Community Resources
:::note[Have a resource to share?] If you found (or made!) a helpful video or blog post about using Ghost with Astro, add it to this list! :::