Patterns
Post row block
View in FigmaA row of one to four content cards from flat article records, with a column-count enum. CMS-serializable.
Install
npx shadcn@latest add @alix/postRowBlockPreview
Revenue actions that protect the next quarter
A field note on pricing, mix, and execution discipline for executive teams.
Preparing diligence for a volatile market
How finance teams can tighten the story before investors ask for it.
Standing up a cash office in ten days
The operating cadence, reports, and decisions that create momentum.
Usage
import PostRowBlock, { type PostRowProps } from "@/components/postRowBlock";
const fromCMS: PostRowProps = await getPostRow("latest-insights");
<PostRowBlock {...fromCMS} />
<PostRowBlock
columns={3}
contentCards={[
{
media: { type: "image", src: "/article-placeholder.svg", alt: "" },
alignment: "vertical",
title: "Revenue actions that protect the next quarter",
excerpt: "A field note on pricing, mix, and execution discipline.",
href: "/insights/revenue-actions",
},
]}
/>Examples
Two editorial columns
Set columns to 2 and give each card the editorial variant when the titles and excerpts should carry the weight.
Port disruption is now a working-capital issue
Leaders are connecting freight reliability, inventory exposure, and near-term cash decisions.

Capital projects need clearer control points
Where owners can reduce schedule risk before cost pressure compounds.

<PostRowBlock
columns={2}
contentCards={[
{
variant: "editorial",
media: { src: "/brand/editorial-1.jpg", alt: "" },
alignment: "vertical",
title: "Port disruption is now a working-capital issue",
excerpt: "Leaders are connecting freight reliability, inventory exposure, and near-term cash decisions.",
href: "/insights/port-disruption",
titleAs: "h2",
},
{
variant: "editorial",
media: { src: "/brand/construction.webp", alt: "" },
alignment: "vertical",
title: "Capital projects need clearer control points",
excerpt: "Where owners can reduce schedule risk before cost pressure compounds.",
href: "/insights/capital-controls",
titleAs: "h2",
},
]}
/>Four across, with a video card
A four-column row scans as a compact index; one card uses a video media type (type: "video") to show the discriminant per card.

Liquidity planning when cash windows compress
A concise insight for leaders deciding under pressure.
Turnaround delivery in motion
A short loop from a live cash-office engagement.

Diligence findings that translate to value
A sharper handoff into the first hundred days.

Board reporting under pressure
Keeping decisions moving as the picture shifts weekly.
<PostRowBlock
columns={4}
contentCards={[
{ media: { type: "image", src: "/brand/editorial-1.jpg", alt: "" }, alignment: "vertical", title: "Liquidity planning when cash windows compress", excerpt: "…", href: "/insights/liquidity-planning" },
{ media: { type: "video", src: "/media/turnaround-loop.mp4", poster: "/brand/ship.webp", muted: true, loop: true }, alignment: "vertical", title: "Turnaround delivery in motion", excerpt: "…", href: "/insights/turnaround-delivery" },
{ media: { type: "image", src: "/brand/editorial-2.jpg", alt: "" }, alignment: "vertical", title: "Diligence findings that translate to value", excerpt: "…", href: "/insights/diligence-to-value" },
{ media: { type: "image", src: "/brand/people.webp", alt: "" }, alignment: "vertical", title: "Board reporting under pressure", excerpt: "…", href: "/insights/board-reporting" },
]}
/>When to use it
Use it for
- A single CMS-fed row of related articles, e.g. "latest insights", with the column count set by content.
- Editorial rows where each title and excerpt should read as the lead, not a category-led item.
- Reusing the same row renderer a PostGrid uses, so a standalone row and an index page can't drift apart.
Reach for something else
- A full paginated index of posts — use PostGrid instead.
- One teaser card on its own — use ContentCard instead.
- Custom spacing or row semantics — call renderPostRow inside your own section frame instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| contentCards | ContentCardProps[] | — | Flat CMS article/card records passed to ContentCard in the shared row renderer. |
| columns | 1 | 2 | 3 | 4 | — | Required row column count supplied by the CMS. |
| ContentCardProps.variant | "news" | "editorial" | "news" | Card visual variant. |
| ContentCardProps.media.type | "image" | "video" | "image" | Media discriminant for each card. |
| ContentCardProps.alignment | "vertical" | "horizontal" | — | Required card media/text orientation. |
| ContentCardProps.titleAs | "h2" | "h3" | "h4" | "h3" | Semantic heading level for each card title. |
| escape hatch | compose lower layer | — | For custom spacing or row semantics, call `renderPostRow` inside your own section frame. |