Zenex CMSDocs

Get started with Next.js

Integrate your headless CMS into your Next.js application.

Setup

Create a blog in your dashboard and copy your Blog ID. Add your CMS URL and Blog ID to your environment variables. You can use cms.zenex.dev (hosted) or your own deployment.

.env.local
# .env.local
NEXT_PUBLIC_CMS_URL=https://cms.zenex.dev
NEXT_PUBLIC_BLOG_ID=your-blog-id
app/blog/page.tsx
// app/blog/page.tsx
export default async function BlogPage() {
const CMS_URL = process.env.NEXT_PUBLIC_CMS_URL;
const BLOG_ID = process.env.NEXT_PUBLIC_BLOG_ID;
const res = await fetch(`${CMS_URL}/api/blogs/${BLOG_ID}/posts?status=published&page=1&limit=10`);
const { data: posts } = await res.json();
return (
<div>
{posts.map((post) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
<a href={`/blog/${post.slug}`}>Read more</a>
</article>
))}
</div>
);
}

Fetch Single Post

Create a dynamic route to fetch individual posts by slug.

app/blog/[slug]/page.tsx
// app/blog/[slug]/page.tsx
export default async function PostPage({ params }: { params: { slug: string } }) {
const CMS_URL = process.env.NEXT_PUBLIC_CMS_URL;
const BLOG_ID = process.env.NEXT_PUBLIC_BLOG_ID;
const res = await fetch(`${CMS_URL}/api/blogs/${BLOG_ID}/posts/${params.slug}`);
const { data: post } = await res.json();
return (
<article>
<h1>{post.title}</h1>
{post.coverImage && <img src={post.coverImage} alt={post.title} />}
<p>{post.excerpt}</p>
{/* Render post.content (Editor.js format) */}
</article>
);
}

Filtering by Category

Filter posts by category using query parameters.

app/blog/page.tsx
const CMS_URL = process.env.NEXT_PUBLIC_CMS_URL;
const BLOG_ID = process.env.NEXT_PUBLIC_BLOG_ID;
const res = await fetch(
`${CMS_URL}/api/blogs/${BLOG_ID}/posts?category=${categoryId}`
);