{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "blog-1",
  "title": "Three Card Post Grid",
  "description": "Blog post grid of three cards with cover images, category badges, titles, excerpts, read time, and author avatars.",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "avatar",
    "badge",
    "button",
    "card",
    "separator"
  ],
  "files": [
    {
      "path": "registry/blocks/blog/1/blog-block.tsx",
      "content": "import { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst posts = [\n  {\n    category: \"Engineering\",\n    title: \"How we cut API latency by 60% with edge caching\",\n    excerpt:\n      \"Our monolith was fast enough, until it wasn't. We traced the bottleneck to cold database reads on every request and rearchitected our caching layer in three weeks.\",\n    author: {\n      name: \"Lena Park\",\n      initials: \"LP\",\n      avatar: \"https://i.pravatar.cc/150?img=45\",\n    },\n    date: \"Jun 9, 2026\",\n    readTime: \"7 Min Read\",\n    image:\n      \"https://images.unsplash.com/photo-1558494949-ef010cbdcc31?w=800&q=80\",\n    imageAlt: \"Server rack with blinking lights in a data center\",\n  },\n  {\n    category: \"Design\",\n    title: \"Building a token system that survives a rebrand\",\n    excerpt:\n      \"Semantic tokens feel abstract until the day your brand color changes. We share the naming conventions and tooling that let us ship a full rebrand in under two days.\",\n    author: {\n      name: \"Marcus Webb\",\n      initials: \"MW\",\n      avatar: \"https://i.pravatar.cc/150?img=12\",\n    },\n    date: \"May 28, 2026\",\n    readTime: \"5 Min Read\",\n    image:\n      \"https://images.unsplash.com/photo-1561070791-2526d30994b5?w=800&q=80\",\n    imageAlt: \"Colour swatches and design tokens spread on a desk\",\n  },\n  {\n    category: \"Product\",\n    title: \"What 1,200 user interviews taught us about onboarding\",\n    excerpt:\n      \"Drop-off at step two turned out to have nothing to do with the UI. Listening to customers revealed a mismatch between our mental model and theirs. Here's how we fixed it.\",\n    author: {\n      name: \"Sofia Andrade\",\n      initials: \"SA\",\n      avatar: \"https://i.pravatar.cc/150?img=32\",\n    },\n    date: \"May 14, 2026\",\n    readTime: \"9 Min Read\",\n    image:\n      \"https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=800&q=80\",\n    imageAlt: \"Two people in a user research interview session\",\n  },\n]\n\nexport default function BlogBlock() {\n  return (\n    <section className=\"flex w-full items-center justify-center bg-background px-6 py-16 text-foreground\">\n      <div className=\"mx-auto w-full max-w-5xl\">\n        <div className=\"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between\">\n          <div className=\"flex flex-col gap-1.5\">\n            <span className=\"text-xs font-semibold tracking-[0.18em] text-muted-foreground uppercase\">\n              Blog\n            </span>\n            <h2 className=\"font-heading text-3xl font-bold tracking-tight sm:text-4xl\">\n              From the Acme team\n            </h2>\n          </div>\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"group w-fit gap-1.5 transition-colors\"\n          >\n            All Articles\n            <IconPlaceholder\n              lucide=\"ArrowRight\"\n              tabler=\"IconArrowRight\"\n              hugeicons=\"ArrowRightIcon\"\n              phosphor=\"ArrowRight\"\n              remixicon=\"RiArrowRightLine\"\n              className=\"transition-transform duration-200 group-hover:translate-x-0.5\"\n              size={15}\n            />\n          </Button>\n        </div>\n\n        <Separator className=\"my-8\" />\n\n        <div className=\"grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3\">\n          {posts.map((post) => (\n            <Card\n              key={post.title}\n              className=\"group flex flex-col overflow-hidden border-border pt-0 transition-shadow duration-200 hover:shadow-md\"\n            >\n              <div className=\"aspect-[16/9] w-full overflow-hidden border-b border-border bg-muted\">\n                <img\n                  src={post.image}\n                  alt={post.imageAlt}\n                  className=\"size-full object-cover transition-transform duration-300 group-hover:scale-[1.03]\"\n                />\n              </div>\n\n              <CardHeader className=\"gap-2 pb-3\">\n                <div className=\"flex items-center justify-between gap-2\">\n                  <Badge\n                    variant=\"secondary\"\n                    className=\"text-[11px] font-semibold tracking-wide uppercase\"\n                  >\n                    {post.category}\n                  </Badge>\n                  <span className=\"flex shrink-0 items-center gap-1 text-xs leading-none text-muted-foreground\">\n                    <IconPlaceholder\n                      lucide=\"Clock\"\n                      tabler=\"IconClock\"\n                      hugeicons=\"TimeIcon\"\n                      phosphor=\"Clock\"\n                      remixicon=\"RiTimeLine\"\n                      size={11}\n                      className=\"shrink-0\"\n                    />\n                    {post.readTime}\n                  </span>\n                </div>\n                <CardTitle className=\"text-base leading-snug font-semibold\">\n                  {post.title}\n                </CardTitle>\n                <CardDescription className=\"line-clamp-3 text-sm leading-relaxed\">\n                  {post.excerpt}\n                </CardDescription>\n              </CardHeader>\n\n              <CardContent className=\"mt-auto pt-0 pb-0\" />\n\n              <CardFooter className=\"border-t border-border pt-4 pb-4\">\n                <div className=\"flex w-full items-center gap-3\">\n                  <Avatar size=\"sm\">\n                    <AvatarImage\n                      src={post.author.avatar}\n                      alt={post.author.name}\n                      className=\"grayscale\"\n                    />\n                    <AvatarFallback className=\"text-xs\">\n                      {post.author.initials}\n                    </AvatarFallback>\n                  </Avatar>\n                  <div className=\"flex flex-1 flex-col gap-0.5 overflow-hidden\">\n                    <span className=\"truncate text-xs font-semibold text-foreground\">\n                      {post.author.name}\n                    </span>\n                    <span className=\"text-xs text-muted-foreground\">\n                      <time dateTime={post.date}>{post.date}</time>\n                    </span>\n                  </div>\n                  <IconPlaceholder\n                    lucide=\"ArrowRight\"\n                    tabler=\"IconArrowRight\"\n                    hugeicons=\"ArrowRightIcon\"\n                    phosphor=\"ArrowRight\"\n                    remixicon=\"RiArrowRightLine\"\n                    size={14}\n                    className=\"shrink-0 text-muted-foreground opacity-0 transition-opacity duration-200 group-hover:opacity-100\"\n                    aria-hidden=\"true\"\n                  />\n                </div>\n              </CardFooter>\n            </Card>\n          ))}\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "meta": {
    "height": "721px",
    "tier": "free"
  },
  "categories": [
    "blog"
  ],
  "type": "registry:block"
}