Blog — Post Grid
Responsive grid of blog post cards with image, title, excerpt, and metadata.
Content cardbadge
Installation
npx shadcn@latest add @saastro/blog-grid-01Preview
Latest from the blog
Read our latest articles and tutorials.
Blog
Tutorial
Getting Started with Astro Blocks
Learn how to install and use blocks in your Astro project with the shadcn CLI.
Mar 10, 2026
Blog
Guide
Building a SaaS Landing Page
A step-by-step guide to creating a complete landing page using pre-built blocks.
Mar 8, 2026
Blog
Design
Customizing Block Themes
How to match blocks to your brand using CSS variables and Tailwind configuration.
Mar 5, 2026
Source Code
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { cn } from '@/lib/utils';
type Post = {
title: string;
excerpt: string;
date: string;
category?: string;
imageUrl?: string;
href: string;
};
type BlogGrid01Props = {
title?: string;
description?: string;
posts: Post[];
className?: string;
};
export function BlogGrid01({ title, description, posts, className }: BlogGrid01Props) {
return (
<section className={cn('w-full px-6 py-24 md:py-32', className)}>
<div className="mx-auto max-w-6xl">
{(title || description) && (
<div className="mx-auto mb-16 max-w-2xl text-center">
{title && <h2 className="text-3xl font-bold tracking-tight sm:text-4xl">{title}</h2>}
{description && <p className="mt-4 text-lg text-muted-foreground">{description}</p>}
</div>
)}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{posts.map((post) => (
<a key={post.href} href={post.href} className="group">
<Card className="h-full overflow-hidden transition-shadow group-hover:shadow-lg">
<div className="aspect-video overflow-hidden bg-muted">
{post.imageUrl ? (
<img
src={post.imageUrl}
alt={post.title}
className="h-full w-full object-cover transition-transform group-hover:scale-105"
/>
) : (
<div className="flex h-full w-full items-center justify-center bg-gradient-to-br from-muted to-muted-foreground/5">
<span className="text-xl text-muted-foreground/30">Blog</span>
</div>
)}
</div>
<CardHeader>
{post.category && (
<Badge variant="secondary" className="w-fit">
{post.category}
</Badge>
)}
<CardTitle className="line-clamp-2 text-lg group-hover:text-primary">
{post.title}
</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="line-clamp-2">{post.excerpt}</CardDescription>
<p className="mt-4 text-xs text-muted-foreground">{post.date}</p>
</CardContent>
</Card>
</a>
))}
</div>
</div>
</section>
);
}
Registry Setup
Add the Saastro registry to your components.json:
{
"registries": {
"@saastro": "https://ui.saastro.io/r/{name}.json"
}
}