A Magazine-Style Blog Listing Block
Blog Page is a listing block that arranges posts the way editorial sites do: a large hero for the newest article, a Featured Posts rail beside it, and a Recent Posts grid underneath with an All Posts button. It is one of two blocks in the blog pages category, covering the index side while its sibling covers the article view.
Drop it into company blogs, SaaS content hubs, documentation changelog feeds, or personal sites. Because it is a self-contained section with its own max-width container, it can live on a dedicated /blog route or be embedded further down a landing page.
The Featured Hero and Sidebar Combo
The hero takes the most recent post, renders its cover through next/image, and overlays a gradient scrim with a category Badge and the title in white. Beside it, a Card component lists other featured posts as compact rows with a thumbnail, a two-line clamped title, and a read-time label with a clock icon.
Selection logic is plain TypeScript: type guards split FeaturedBlogPost from RegularBlogPost, a shared sortByDateDesc helper orders both groups, and the newest post overall wins the hero slot. No CMS is assumed, so the logic ports cleanly to whatever data source you have.
Typed Post Data You Can Swap Out
All content lives in blog-posts.ts as a typed array with image URLs, author names, avatars, read times, and ISO publish dates. The components never hardcode a post, which means wiring a headless CMS or an MDX loader is a matter of mapping your records onto the BlogPost type and deleting the sample file.
Each grid entry is a BlogPostCard component: an aspect-video cover image, clamped title and description, and an author row using the Avatar component with initials as fallback. Cards are wrapped in links with a hover opacity transition, keeping the whole surface clickable.
Styling the Grid With Tailwind Utilities and Tokens
Layout is pure Tailwind: a three-column CSS grid at the top that gives the hero two columns, and a responsive one-to-three column grid for recent posts. Muted text uses text-muted-foreground and cards inherit bg-card, so the block obeys dark and light themes through the standard Shadcn UI CSS variables.
To retheme it, adjust tokens in globals.css rather than the markup. Radius, muted contrast, and card background changes propagate to every post card at once, and the hero scrim remains legible because it composes a black gradient over the image rather than a themed color.
Getting the Blog Listing Into Your Project
Since the block is free, nothing stands between you and the source: open the code tab, copy page.tsx with its two child components and the data file, and you are done. The header of the page also prints a shadcn CLI command with npm, pnpm, yarn, and bun switches that registers the block and its dependencies automatically.
React, Vuejs, and Svelte are all covered. The listing has been recreated with shadcn-vue for Vuejs apps and shadcn-svelte for Svelte apps, so the hero, sidebar, and card grid look identical regardless of the framework badge in your package.json.

