UnfoldCMS + Tailwind CSS: Styling Guide
Style API-delivered HTML cleanly with the Tailwind typography plugin.
UnfoldCMS returns post bodies as ready-made HTML, not Markdown or a block JSON tree. That's good news for Tailwind users — but it raises one real question: how do you style HTML you didn't write class names into? This guide shows the clean answer (the Tailwind typography plugin), plus how to style the rest of your front end pulling from the UnfoldCMS API. About 15 minutes. See also: the Next.js integration guide and how the admin is built on shadcn/ui.
TL;DR: UnfoldCMS serves sanitized HTML from /api/v1/posts/{slug}. The post body has no Tailwind classes on it, so wrap it in prose from @tailwindcss/typography to style headings, lists, code, and tables in one line. Style your own layout components with normal utilities. No special integration, no SDK — it's just HTML and Tailwind.
How Does UnfoldCMS Content Arrive in Your Front End?
When you call GET /api/v1/posts/{slug}, the body field is a string of sanitized HTML — real <h2>, <p>, <ul>, <pre>, <table> tags. UnfoldCMS runs all content through a purifier, so it's safe to render. But those tags carry no class attributes, which is exactly the situation Tailwind's typography plugin was built for.
Your front end has two styling jobs:
- The CMS body — HTML you don't control the markup of, styled with
prose. - Your own layout — header, cards, nav, footer, styled with normal Tailwind utilities.
Step 1: Style the Post Body With the Typography Plugin
Install the official plugin and wrap the rendered body in a prose container. This styles every element inside without touching the HTML.
npm install -D @tailwindcss/typography
In Tailwind v4, add it in your CSS entry:
/* app.css */
@import "tailwindcss";
@plugin "@tailwindcss/typography";
Then wrap the CMS body. (React/Next.js shown; the class is the same anywhere.)
<article
className="prose prose-lg dark:prose-invert max-w-none"
dangerouslySetInnerHTML={{ __html: post.body }}
/>
That single prose class gives you readable headings, spaced paragraphs, styled lists, bordered tables, and formatted code blocks — all matching a sensible vertical rhythm. prose-invert handles dark mode; max-w-none removes the default reading-width cap if your layout already constrains it.
Step 2: Customize Prose to Match Your Brand
The plugin exposes CSS variables and modifier classes so you don't have to fight it. Tune the accent color, code style, and headings with utilities:
<article
className="prose prose-slate dark:prose-invert
prose-headings:font-semibold
prose-a:text-blue-600 prose-a:no-underline hover:prose-a:underline
prose-code:rounded prose-code:bg-slate-100 prose-code:px-1
max-w-none"
dangerouslySetInnerHTML={{ __html: post.body }}
/>
Each prose-{element}:{utility} modifier targets one tag type inside the body. This is how you make CMS content look like the rest of your design system without editing the content itself.
Step 3: Style Your Own Components Normally
Everything outside the post body is yours — use Tailwind the usual way. A blog index card pulling from /api/v1/posts is just a component:
{posts.map((post) => (
<a key={post.slug} href={`/blog/${post.slug}`}
className="block rounded-xl border border-slate-200 p-6
transition hover:border-blue-400 hover:shadow-md">
<h3 className="text-lg font-semibold text-slate-900">{post.title}</h3>
<p className="mt-2 text-sm text-slate-600">{post.short_description}</p>
</a>
))}
No special CMS knowledge needed here — it's a list of objects from the API rendered with utilities.
prose vs Manual Styling vs a UI Kit: Which Approach?
Three ways to style CMS-delivered HTML. Pick by how much control you need versus how fast you want to ship.
| Approach | Effort | Control | Best for |
|---|---|---|---|
| @tailwindcss/typography (prose) | One line | High via modifiers | Almost everyone — recommended |
| Manual element CSS | High | Total | Strict design systems |
| Third-party UI kit | Medium | Kit-dependent | Teams already on that kit |
For 90% of sites, the typography plugin is the right call: one class, full control through modifiers, zero content edits.
Frequently Asked Questions
Does UnfoldCMS return Markdown or HTML?
The API returns the post body as sanitized HTML, ready to render. You don't run a Markdown parser on the client. Wrap it in a prose container to style it with Tailwind.
Can I add my own Tailwind classes to the CMS content?
The body HTML has no classes, so style it with the prose modifier classes (prose-headings:, prose-a:, etc.) on the wrapper. That targets each element type without editing the content in the CMS.
Does this work with Tailwind v4?
Yes. Register the plugin with @plugin "@tailwindcss/typography" in your CSS entry. UnfoldCMS's own admin runs on Tailwind v4 with shadcn/ui, so the project is built on the same stack.
Is UnfoldCMS related to shadcn/ui?
The UnfoldCMS admin interface is built with shadcn/ui on Tailwind v4. Your public front end is separate and can use any styling you like — the API just returns content. See the shadcn/ui CMS write-up.
Is there a Tailwind plugin specific to UnfoldCMS?
No, and you don't need one. UnfoldCMS returns standard HTML, so the official @tailwindcss/typography plugin covers it. There's no UnfoldCMS-specific package to install.
Where to Go From Here
You can now style UnfoldCMS content with Tailwind in one line and build the rest of your front end with normal utilities. To wire the data layer, follow the Next.js integration guide or the Astro guide. The full endpoint list lives in the API docs.
UnfoldCMS is a one-time license, self-hosted, with the full public API in every tier — see pricing. It hands you clean HTML and gets out of your way on styling, which is exactly what you want from a headless source.
Related: Next.js integration · Astro integration · CMS built on shadcn/ui