Blog

Publish blog posts with rich content, featured images, excerpts, and SEO metadata. Posts support multiple locales and are served via the public API with pagination.

How Blog Posts Work

Blog posts are created in the CMS dashboard with a rich content editor. Each post has a slug, title, excerpt, optional featuredImage, and author name.

The list endpoint returns posts without the full content body (just metadata and excerpt), making it efficient for index pages. Fetch a single post by slug to get the full content.

Fetching Blog Posts

List recent posts
const res = await fetch(
  `${CMS_URL}/api/public/blog?limit=10`,
  { headers: { "x-api-key": CMS_API_KEY } }
);
const { posts, total, hasMore } = await res.json();
Fetch a single post
const res = await fetch(
  `${CMS_URL}/api/public/blog/${slug}`,
  { headers: { "x-api-key": CMS_API_KEY } }
);
const post = await res.json();
// post.content contains the full rich content

Building a Blog Index

Example: Blog listing page
async function BlogIndex() {
  const res = await fetch(
    `${process.env.CMS_URL}/api/public/blog?limit=10`,
    {
      headers: { "x-api-key": process.env.CMS_API_KEY! },
      next: { revalidate: 60 },
    }
  );
  const { posts, hasMore } = await res.json();

  return (
    <div>
      {posts.map((post) => (
        <article key={post.slug}>
          {post.featuredImage && (
            <img src={post.featuredImage} alt={post.title} />
          )}
          <h2><a href={`/blog/${post.slug}`}>{post.title}</a></h2>
          <p>{post.excerpt}</p>
          <span>{post.author}</span>
        </article>
      ))}
      {hasMore && <a href="/blog?page=2">Load more</a>}
    </div>
  );
}

Next Steps