shadimage
uiception
blockblog-section-v2source: ok · hit

Blog Section v2

Two-column editorial layout with a sticky author sidebar (square photo, label, name, title, GitHub) and two title/description/image/body content sections.

npx shadcn add "https://uiception.com/r/blog-section-v2.json"
free

Where it goes

sidebardashboard-shellblog-list

Use cases

dashboard

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light

Registry dependencies

https://uiception.com/r/block-media.jsonavatar

Files8 · source cached 10/8/2026, 10:40:24 PM

registry/new-york/blocks/blog-section-v2/page.tsx
import BlogSectionV2 from "./components/blog-section-v2"

export default function Page() {
  return <BlogSectionV2 />
}
registry/new-york/blocks/blog-section-v2/components/blog-section-v2.tsx
import Image from "next/image"
import Link from "next/link"

import { createBlockImage } from "@/lib/block-media"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { GithubDark } from "@/components/ui/svgs/githubDark"
import { GithubLight } from "@/components/ui/svgs/githubLight"

import { author, sections } from "../lib/config"

const blockImage = createBlockImage("blog-section-v2")

const authorData = {
  label: author.label,
  name: author.name,
  title: author.title,
  avatarSrc: blockImage(author.avatarFile),
  initials: author.initials,
  githubHref: author.githubHref,
  githubLabel: author.githubLabel,
}

const contentSections = sections.map((section) => ({
  title: section.title,
  description: section.description,
  body: section.body,
  alt: section.alt,
  src: blockImage(section.imageFile),
}))

export default function BlogSectionV2() {
  return (
    <section className="py-4 md:py-6 lg:py-8">
      <div className="mx-auto max-w-6xl px-4">
        <div className="grid grid-cols-1 gap-10 lg:grid-cols-[minmax(0,16rem)_1fr] lg:gap-0">
          <aside className="flex flex-col gap-4 border-b border-border pb-10 lg:sticky lg:top-8 lg:self-start lg:border-b-0 lg:pb-0 lg:pr-10">
            <Avatar className="size-24 rounded-none after:rounded-none">
              <AvatarImage
                src={authorData.avatarSrc}
                alt={authorData.name}
                className="rounded-none"
              />
              <AvatarFallback className="rounded-none">
                {authorData.initials}
              </AvatarFallback>
            </Avatar>

            <p className="text-sm tracking-tight text-muted-foreground">
              {authorData.label}
            </p>

            <div className="flex flex-col gap-1">
              <p className="text-lg font-semibold tracking-tight text-foreground">
                {authorData.name}
              </p>
              <p className="text-sm text-muted-foreground">{authorData.title}</p>
            </div>

            <Link
              href={authorData.githubHref}
              target="_blank"
              rel="noreferrer"
              className="inline-flex w-fit items-center gap-2 text-sm font-medium text-foreground outline-none transition-opacity hover:opacity-70 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
            >
              <GithubLight className="size-4 shrink-0 dark:hidden" aria-hidden />
              <GithubDark
                className="hidden size-4 shrink-0 dark:block"
                aria-hidden
              />
              {authorData.githubLabel}
            </Link>
          </aside>

          <div className="flex flex-col gap-14 lg:border-l lg:border-border lg:pl-10">
            {contentSections.map((section) => (
              <article key={section.title} className="flex flex-col gap-4">
                <h2 className="text-3xl font-medium leading-[1.1] tracking-[-0.03em] text-balance lg:text-4xl">
                  {section.title}
                </h2>
                <p className="max-w-2xl text-[0.9375rem] leading-relaxed text-muted-foreground">
                  {section.description}
                </p>
                <div className="relative aspect-video w-full overflow-hidden rounded-none bg-muted">
                  <Image
                    src={section.src}
                    alt={section.alt}
                    fill
                    unoptimized
                    className="object-cover"
                    sizes="(max-width: 1024px) 100vw, 48rem"
                  />
                </div>
                <p className="max-w-2xl text-[0.9375rem] leading-relaxed text-foreground">
                  {section.body}
                </p>
              </article>
            ))}
          </div>
        </div>
      </div>
    </section>
  )
}
registry/new-york/blocks/blog-section-v2/lib/config.ts
export const author = {
  label: "Author",
  name: "Jon Doe",
  title: "Fullstack Developer",
  avatarFile: "avatar.png",
  initials: "JD",
  githubHref: "https://github.com/",
  githubLabel: "GitHub",
} as const

export const sections = [
  {
    title: "Golden Hour Field Notes",
    description:
      "Last light on the mountains, and the work you leave unfinished on purpose.",
    imageFile: "image-1.jpg",
    alt: "Mountain landscape at golden hour",
    body: "There is a short window when the mountains keep time. Shadows climb the ridges in minutes, and I have to decide where to stand and what to leave out of the frame before the color drains. I treat that hour the way I treat a shipping deadline. The hard edge makes the rest of the day honest. I can walk the trail again in the morning, and I cannot get this light back.",
  },
  {
    title: "A Walk Along the Cliffs",
    description:
      "Notes from a coastal path where the weather changes faster than the plan.",
    imageFile: "image-2.jpg",
    alt: "Coastal cliffs and ocean waves",
    body: "Spray hits the path. The ocean keeps the same argument it has always kept with the shore. I walk slower than usual on days like this. The ground is difficult. The water is loud, and that makes room for quieter thoughts about what to build next and what to delete.",
  },
] as const
components/ui/svgs/githubLight.tsx
import type { SVGProps } from "react";

const GithubLight = (props: SVGProps<SVGSVGElement>) => (
  <svg {...props} viewBox="0 0 1024 1024" fill="none">
    <path
      fill="#1b1f23"
      fillRule="evenodd"
      d="M512 0C229.12 0 0 229.12 0 512c0 226.56 146.56 417.92 350.08 485.76 25.6 4.48 35.2-10.88 35.2-24.32 0-12.16-.64-52.48-.64-95.36-128.64 23.68-161.92-31.36-172.16-60.16-5.76-14.72-30.72-60.16-52.48-72.32-17.92-9.6-43.52-33.28-.64-33.92 40.32-.64 69.12 37.12 78.72 52.48 46.08 77.44 119.68 55.68 149.12 42.24 4.48-33.28 17.92-55.68 32.64-68.48-113.92-12.8-232.96-56.96-232.96-252.8 0-55.68 19.84-101.76 52.48-137.6-5.12-12.8-23.04-65.28 5.12-135.68 0 0 42.88-13.44 140.8 52.48 40.96-11.52 84.48-17.28 128-17.28s87.04 5.76 128 17.28c97.92-66.56 140.8-52.48 140.8-52.48 28.16 70.4 10.24 122.88 5.12 135.68 32.64 35.84 52.48 81.28 52.48 137.6 0 196.48-119.68 240-233.6 252.8 18.56 16 34.56 46.72 34.56 94.72 0 68.48-.64 123.52-.64 140.8 0 13.44 9.6 29.44 35.2 24.32C877.44 929.92 1024 737.92 1024 512 1024 229.12 794.88 0 512 0"
      clipRule="evenodd"
    />
  </svg>
);

export { GithubLight };
components/ui/svgs/githubDark.tsx
import type { SVGProps } from "react";

const GithubDark = (props: SVGProps<SVGSVGElement>) => (
  <svg {...props} viewBox="0 0 1024 1024" fill="none">
    <path
      fillRule="evenodd"
      clipRule="evenodd"
      d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z"
      transform="scale(64)"
      fill="#ffff"
    />
  </svg>
);

export { GithubDark };
public/images/blocks/blog-section-v2/avatar.png.gitkeep
Place your asset here. Same base name, any supported format: jpg, jpeg, png, webp, avif, gif, or svg. Remove the .gitkeep extension from the filename.
public/images/blocks/blog-section-v2/image-1.jpg.gitkeep
Place your asset here. Same base name, any supported format: jpg, jpeg, png, webp, avif, gif, or svg. Remove the .gitkeep extension from the filename.
public/images/blocks/blog-section-v2/image-2.jpg.gitkeep
Place your asset here. Same base name, any supported format: jpg, jpeg, png, webp, avif, gif, or svg. Remove the .gitkeep extension from the filename.

More from uiception

Browse all components in this library →