Flotiq CMS x Astro


2025 - 04 - 07
Flotiq CMS x Astro

Using Astro with headless CMSs is a breeze. I will show you several examples of those CMSs in the upcoming weeks. We're starting with Flotiq. Let's dive in!

What is Flotiq

Flotiq is a fascinating Polish headless CMS. I discovered it somewhat accidentally when Paulina wrote to me on LinkedIn asking about DevRel-related stuff.

I decided to give it a try and I liked it. It has all the features that a headless CMS needs:

What do I enjoy about it?

When I tried Flotiq for the first time, it felt simple. I didn't have to read docs to achieve things that most of this CMS will be doing (and let's remember users use CMSs differently than us, developers).

The process of creating a definition is straightforward. There are enough content types to build almost anything you want (including block editor, markdown, text fields, lists, relations, etc). Content creation it's was OK too (although there is room for improvement).

Using the API was also straightforward - so connecting everything with Astro was a breeze.

I also enjoyed the Favorite option in the admin panel. It allows you to star pages in the admin panel that you use more often and have them listed under favorites. A really neat and helpful thing.

Webhooks are also nice - they are very useful if you want to automate some things.

Forms - you can create embeddable form for each post type and put them on your website - that's a really useful feature.

What could be done better?

While I enjoyed a lot about Flotiq, some things could be polished a bit more.

I said that the interface didn't cause me any problems and that's true. But I feel there is room for improvement. Maybe hiding some things would be a good idea (eg API documentation link - most users won't even use it). I'm not saying it's bad - it just can be better.

There are two plugins that IMO should be part of the core - Slugs and Singular. There is no explanation why they aren't. Apart from the fact that on the free tier, you can only use one, the fact of using plugins might force you to bump your plan.

What I also miss are more options when designing a post type page. For example, adding inputs in columns, having tabs to group content etc. I think that Statamic is a very good example here.

Please, add a possibility to close the bar that says "You've reached your free plan limit! Upgrade now to keep everything running smoothly". I know, I installed a plugin 😄

Mapping data

What we want to create in the end is a very simple blog that consists of:

We'll later connect it to Astro's default blog theme.

To achieve this we'll need to go to the Definition Builder, select Add Content Type Definition, and name it Blog Post.

Next, we have to add all the required fields:

After doing this, you need to go to Plugins, install the Slugs plugin, and configure it by selecting a proper content type, selecting title as source field and slug as a target field.

Now it's time to connect this with Astro 🚀

Connecting to Astro

We're going to use the default Astro Blog template. While it's not robust and full of features it's perfect for our example.

First, install the latest version of Astro and select the blog template.

Flotiq has a neat SDK, and installing it will be the first step, to do so, first visit the Flotiq admin panel and copy the API key (if you're building a static site, use the read-only).

Now open or create .env file and add:

FLOTIQ_API_KEY=<paste your key>

and run:

npm install flotiq-api-ts

Next step is to update the src/content.config.ts:

import { defineCollection, z } from 'astro:content';

import { FlotiqApi } from "flotiq-api-ts";

const blog = defineCollection({
	loader: async () => {
		const flotiq = new FlotiqApi(import.meta.env.FLOTIQ_API_KEY);
		const posts = await flotiq.BlogpostAPI.list();

		return posts.data.map((post) => ({
			...post,
			id: post.slug,
			pubDate: post.internal?.publishedAt,
			updatedDate: post.internal?.updatedAt,
		}));
	},
	
	schema: z.object({
		id: z.string(),
		title: z.string(),
		description: z.string(),
		pubDate: z.coerce.date(),
		updatedDate: z.coerce.date(),
		heroImage: z.string().optional(),
		content: z.string(),
	}),
});

export const collections = { blog };

This way we won't have to touch other parts of the code(almost) and just map variables accordingly.

Time to take care of displaying content and hero images.

Showing imported Markdown

Displaying Markdown, which got imported from an API is not as simple as it might be. To do so, you'll need to install

npm install @astropub/md 

and correct the config a bit:

import markdownIntegration from '@astropub/md'
export default defineConfig({
	integrations: [markdownIntegration()],
});

The last part you'll need to add is:

---
import { Markdown } from '@astropub/md'
---

<Markdown of={ post.data.content} />

to pages/blog/[...slug].astro

Images

The default Astro Blog theme handles images in a rather simple way - it just shows the images as they are by passing the URL. And while it works, we can(and should) do better. That's why we'll use the <Image /> component to optimize the images.

But before we do, we need to change our content config a bit:

return posts.data.map((post) => ({
	...post,
	id: post.slug,
	pubDate: post.internal?.publishedAt,
	updatedDate: post.internal?.updatedAt,
	heroImage: post.heroImage[0]?.url ? 'https://api.flotiq.com' + post.heroImage[0]?.url : undefined,
}));

This is necessary because the Image requires the full URL to the image.

Next, because we need to optimize images coming from the outside, we need to open our Astro config file again and add:

export default defineConfig({
    // other stuff goes here
	image: {
		domains: ["api.flotiq.com"],
	}
});

The last step is to edit BlogPost.astro component and index.astro page. In both cases you need to add:

import { Image } from 'astro:assets';

in the frontmatter part and replacing the <img src... with <Image src... (rest of parameters stay the same).

Summary

We did it - we connected Flotiq with Astro. It wasn't difficult, right?

Thanks to Content Layer API connecting and changing CMSs in Astro is simpler than ever.

Subscribe to my newsletter and stay updated.
Get an weekly email with news from around the web
Get updated about new blog posts
No spam

Share your thoughts


All Articles
Share