Astro
Kontent.ai & Astro
Kontent.ai & Astro
readonly KONTENT_PREVIEW_API_KEY: string; }
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 Astro with your Kontent.ai project, install the [Kontent.ai TypeScript SDK](https://github.com/kontent-ai/delivery-sdk-js):
<PackageManagerTabs>
<Fragment slot="npm">
```shell
npm install @kontent-ai/delivery-sdk
Next, create a new file called kontent.ts in the src/lib/ directory of your Astro project.
:::note Read more on getting environment variables in Astro. :::
This implementation creates a new DeliveryClient object using credentials from the .env file.
:::note[Previews]
The previewApiKey is optional. When used, you can configure each query to the Delivery API endpoint to return the latest versions of content items regardless of their state in the workflow. Otherwise, only published items are returned.
:::
Finally, the root directory of your Astro project should now include these new files:
Fetching data
The DeliveryClient is now available to all components. To fetch content, use the DeliveryClient and method chaining to define your desired items. This example shows a basic fetch of blog posts and renders their titles in a list:
---
const blogPosts = await deliveryClient
.items()
.type("blogPost")
.toPromise()
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<ul>
{blogPosts.data.items.map(blogPost => (
<li>{blogPost.elements.title.value}</li>
))}
</ul>
</body>
</html>
You can find more querying options in the Kontent.ai documentation.
Making a blog with Astro and Kontent.ai
With the setup above, you are now able to create a blog that uses Kontent.ai as the source of content.
Prerequisites
Kontent.ai project - For this tutorial, using a blank project is recommended. If you already have some content types in your content model, you may use them, but you will need to modify the code snippets to match your content model.
Astro project configured for content fetching from Kontent.ai - see above for more details on how to set up an Astro project with Kontent.ai
Setting up content model
In Kontent.ai, navigate to Content model and create a new content type with the following fields and values:
- Name: Blog Post
- Elements:
- Text field
- Name: Title
- Element Required: yes
- Rich text field
- Name: Teaser
- Element Required: yes
- Allowed in this element: only check Text
- Rich text field
- Name: Content
- Element Required: yes
- Date & time field
- Name: Date
- URL slug field
- Name: URL slug
- Element Required: yes
- Auto-generate from: select "Title"
- Text field
Then, click on Save Changes.
Creating content
Now, navigate to Content & assets tab and create a new content item of type Blog Post. Fill the fields using these values:
- Content item name: Astro
- Title: Astro is amazing
- Teaser: Astro is an all-in-one framework for building fast websites faster.
- Content: You can use JavaScript to implement the website functionality, but no client bundle is necessary.
- Date & time: select today
- URL slug: astro-is-amazing
When you're finished, publish the blog post using the Publish button at the top.
Note: Feel free to create as many blog posts as you like before moving to the next step.
Generating content model in TypeScript
Next, you'll generate TypeScript types out of your content model.
:::note This step is optional but provides a much better developer experience and allows you to discover potential problems at build time rather than at runtime. :::
First, install the Kontent.ai JS model generator, ts-node, and dotenv:
Then, add the following script to package.json:
{
...
"scripts": {
...
"regenerate:models": "ts-node --esm ./generate-models.ts"
},
}
Because the types require structural information about your project that is not available in the public API, you also need to add a Content Management API key to the .env file. You can generate the key under Environment settings -> API keys -> Management API.
KONTENT_ENVIRONMENT_ID=YOUR_ENVIRONMENT_ID
KONTENT_PREVIEW_API_KEY=YOUR_PREVIEW_API_KEY
KONTENT_MANAGEMENT_API_KEY=YOUR_MANAGEMENT_API_KEY
Finally, add the script generate-models.ts that configures the model generator to generate the models:
const blogPosts = await deliveryClient
.items<BlogPost>
.type(contentTypes.blog_post.codename)
.toPromise()
---
If you skipped the model generation, you can also use an untyped object and string literal to define the type:
const blogPosts = await deliveryClient
.items()
.type("blogPost")
.toPromise()
The fetch call will return a response object which contains a list of all blog posts in data.items. In the HTML section of the Astro page, you can use the map() function to list the blog posts:
---
const blogPosts = await deliveryClient
.items<BlogPost>
.type(contentTypes.blogPost.codename)
.toPromise()
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<h1>Blog posts</h1>
<ul>
{blogPosts.data.items.map(blogPost => (
<li>
<a href={`/blog/${blogPost.elements.url_slug.value}/`} title={blogPost.elements.title.value}>
{blogPost.elements.title.value}
</a>
</li>
))}
</ul>
</body>
</html>
Generating individual blog posts
The last step of the tutorial is to generate detailed blog post pages.
Static site generation
In this section, you'll use the Static (SSG) Mode with Astro.
First, create a file [slug].astro in /src/pages/blog/ which needs to export a function getStaticPaths that collects all data from the CMS:
---
try {
const data = await deliveryClient
.items<BlogPost>()
.equalsFilter(contentTypes.blog_post.elements.url_slug.codename, slug ?? '')
.type(contentTypes.blog_post.codename)
.limitParameter(1)
.toPromise()
blogPost = data.data.items[0]
} catch (error) {
return Astro.redirect('/404')
}
---
If you're not using generated types, you can instead use string literals to define the content item type and the filtered element codename:
const data = await deliveryClient
.items()
.equalsFilter("url_slug", slug ?? '')
.type("blog_post")
.limitParameter(1)
.toPromise()
Lastly, add the HTML code to render the blog post. This part is the same as with static generation:
---
const { slug } = Astro.params
let blogPost: BlogPost;
try {
const data = await deliveryClient
.items<BlogPost>()
.equalsFilter(contentTypes.blog_post.elements.url_slug.codename, slug ?? '')
.type(contentTypes.blog_post.codename)
.limitParameter(1)
.toPromise()
blogPost = data.data.items[0]
} catch (error) {
return Astro.redirect('/404')
}
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{blogPost.elements.title.value}</title>
</head>
<body>
<article>
<h1>{blogPost.elements.title.value}</h1>
<Fragment set:html={blogPost.elements.teaser.value} />
<Fragment set:html={blogPost.elements.content.value} />
<time>{new Date(blogPost.elements.date.value ?? '')}</time>
</body>
</html>
Publishing your site
To deploy your website, visit the deployment guides and follow the instructions for your preferred hosting provider.
Rebuild on Kontent.ai changes
If your project is using Astro's default static mode, you will need to set up a webhook to trigger a new build when your content changes. If you are using Netlify or Vercel as your hosting provider, you can use its webhook feature to trigger a new build from Kontent.ai events.
Netlify
To set up a webhook in Netlify:
Under the Continuous Deployment tab, find the Build hooks section and click on Add build hook.
Provide a name for your webhook and select the branch you want to trigger the build on. Click on Save and copy the generated URL.
Vercel
To set up a webhook in Vercel:
Under the Git tab, find the Deploy Hooks section.
Provide a name for your webhook and the branch you want to trigger the build on. Click Add and copy the generated URL.
Adding a webhook to Kontent.ai
In the Kontent.ai app, go to Environment settings -> Webhooks. Click on Create new webhook and provide a name for your new webhook. Paste in the URL you copied from Netlify or Vercel and select which events should trigger the webhook. By default, for rebuilding your site when published content changes, you only need Publish and Unpublish events under Delivery API triggers. When you're finished, click on Save.
Now, whenever you publish a new blog post in Kontent.ai, a new build will be triggered and your blog will be updated.