GET Single Post
Fetch a single post by slug, including full content.
Endpoint
Endpoint
GET /api/blogs/{blogId}/posts/{slug}Response
Response
{ "data": { "id": "clx1234567890", "title": "My First Post", "slug": "my-first-post", "content": { "time": 1672531200000, "blocks": [ { "type": "paragraph", "data": { "text": "This is the post content in Editor.js format." } } ], "version": "2.28.0" }, "excerpt": "A short description", "coverImage": "https://example.com/image.jpg", "language": "en", "html": "<p class=\"zenex-cms__paragraph\">This is the post content in Editor.js format.</p>", "publishedAt": "2024-01-01T00:00:00.000Z", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "categories": [...], "tags": [...], "metaTitle": "SEO Title", "metaDescription": "SEO Description", "ogImage": "https://example.com/og-image.jpg", "ogTitle": "Social Title", "ogDescription": "Social Description", "canonicalUrl": "https://example.com/blog/my-first-post", "keywords": "javascript, web", "availableLanguages": ["en", "es"], "translations": [ { "language": "en", "slug": "my-first-post", "canonicalUrl": "https://example.com/blog/my-first-post" }, { "language": "es", "slug": "mi-primer-articulo", "canonicalUrl": null } ] }}Translations
The response includes the published translations from the same blog and translation group. Each item has its own slug and optional canonicalUrl, so clients can build language selectors and hreflang links. Posts without a translation group include only themselves. Draft and scheduled translations are excluded from both translations and availableLanguages.
Example
example.ts
const blogId = "your-blog-id";const slug = "my-first-post";
const res = await fetch( `https://yourdomain.com/api/blogs/${blogId}/posts/${slug}`);const { data: post } = await res.json();
console.log(post.title);console.log(post.content); // Editor.js formatContent Format
The content is available in two formats:
content- Raw Editor.js JSON blocks structure.html- Server-side rendered HTML withzenex-cms__*classes.
Rendering & Styling
The easiest way to render post content is to use the html field and include our default stylesheet.
1. Render HTML
In React / Next.js:
Post.tsx
<div className="zenex-cms-content" dangerouslySetInnerHTML={{ __html: post.html }} />In Astro:
Post.astro
<div class="zenex-cms-content" set:html={post.html} />2. Add Styles
Copy the following CSS to your project (e.g., zenex-cms.css) and import it.
zenex-cms.css
/* Zenex CMS Default Styles */
.zenex-cms__header { font-weight: 700; line-height: 1.2; margin: 1.5rem 0 1rem; color: inherit;}
.zenex-cms__h1 { font-size: 2.25rem; font-weight: 800; }.zenex-cms__h2 { font-size: 1.875rem; font-weight: 700; }.zenex-cms__h3 { font-size: 1.5rem; font-weight: 600; }.zenex-cms__h4 { font-size: 1.25rem; font-weight: 600; }
.zenex-cms__paragraph { font-size: 1rem; line-height: 1.75; margin: 0.75rem 0; color: inherit;}
.zenex-cms__list { margin: 0.75rem 0; padding-left: 1.5rem;}
.zenex-cms__list-item { margin: 0.25rem 0; line-height: 1.75;}
.zenex-cms__list--unordered { list-style-type: disc; }.zenex-cms__list--ordered { list-style-type: decimal; }
.zenex-cms__quote { border-left: 4px solid currentColor; padding-left: 1rem; margin: 1rem 0; font-style: italic; opacity: 0.9;}
.zenex-cms__code-block { background-color: #111827; color: #e5e7eb; border-radius: 0.5rem; padding: 1.25rem; margin: 1.5rem 0; overflow-x: auto; border: 1px solid #374151;}
.zenex-cms__code { font-family: monospace; font-size: 0.9rem; line-height: 1.6; color: inherit;}
.zenex-cms__image-figure { margin: 1.5rem 0; }.zenex-cms__image { max-width: 100%; height: auto; border-radius: 0.5rem;}.zenex-cms__image-caption { font-size: 0.875rem; text-align: center; margin-top: 0.5rem; opacity: 0.8;}
.zenex-cms__link-tool { border: 1px solid currentColor; opacity: 0.8; border-radius: 0.5rem; margin: 1rem 0; padding: 1rem; display: block; text-decoration: none;}