Build A Custom Static Site with Headless Ghost + Astro
Learn how to create a site using Ghost as a headless CMS and build a completely custom front-end with the Astro web framework
Astro is an all-in-one web framework for building fast, content-focused websites.
A full working example with Casper theme can be found here.
Prerequisites
You will need a Ghost instance (remotely or locally) to source content and get site related credentials.
Create a new Astro site with the following command:
# npm
npm create astro@latest
# yarn
yarn create astro
Getting Started
Install the Ghost Content API helper:
yarn add @tryghost/content-api @tryghost/helpers
The next step is to get the API URL
and Content API Key
of the Ghost site.
- Go to your "Settings" page in Ghost admin
- Under "Advanced" section, click on "Integrations"
- Scroll down and click on "Add Custom Integrations"
- Enter a meaning name and retrieve the credentials
Create an .env.local
file in the root directory and add the following:
Update the .gitignore
file as well by replacing with the following
Create a helper client by using the environment variables. Use import.meta.env
to reference the variables.
Import aliases
Astro supports import aliases that you define in your tsconfig.json
& jsconfig.json
paths configuration.
Querying Data
The Ghost API provides 5 types of nodes:
- Post
- Page
- Author
- Tag
- Settings
The Ghost content API helper library has different methods for each node type. All the methods are shown in the Javascript documentation.
To see the contents of the response for each type of node, refer to the API endpoints documentation.
Using the helper from before, you can query the node of type post
like so:
Build the layout component
Using the settings API, we can build a Layout
component that mirrors our Ghost blog settings
Now we can use the Layout
component in our pages:
Dynamic routes with props
To set dynamic routes in Astro, create a file using [bracket]
notation and export a getStaticPaths
function that specifies the paths to be pre-rendered. You can pass props to each path as well, which saves us from fetching separately.
Site Settings
You can fetch the site settings like so:
Astro allows us to share state between components using nanostores (instead of context providers in React or Vue). To access these settings in other parts of the site, create a nanostores atom at store/settings.ts
:
And then use it in our components:
Formatting post dates
The dates of a post, such as post.published_at
, is returned as a date timestamp e.g. 2019-11-26T02:43:13.000+00:00
.
We can output the published date as “Aug 29, 2022” using the Intl API:
<footer class="post-card-meta">
{
post.published_at && (
<div class="post-card-meta-date">
{new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
}).format(new Date(post.published_at))}
</div>
)
}
</footer>
Alternatively, there are date/time utility libraries such as moment.js or date-fns to achieve similar results.