Innovations

Brutalist Grid

Off-white paper bg with thick 2px black borders, JetBrains Mono labels, asymmetric tile grid (avatar + name + bio), 2-column link grid with rotated number labels, and oversized featured-product tiles.

Preview

Source

tsx
"use client";

import {
  Instagram,
  Twitter,
  Youtube,
  Mail,
  Globe,
  ShoppingBag,
  PlayCircle,
  Linkedin,
  Music2,
  ArrowUpRight,
  type LucideIcon,
} from "lucide-react";
import type { LinkIcon, LinksInBioData, RichBlock } from "../types";
import { defaultData } from "../defaultData";

const ICONS: Record<LinkIcon, LucideIcon> = {
  instagram: Instagram,
  twitter: Twitter,
  tiktok: Music2,
  youtube: Youtube,
  spotify: Music2,
  apple: Music2,
  linkedin: Linkedin,
  email: Mail,
  globe: Globe,
  shop: ShoppingBag,
  play: PlayCircle,
};

const PAPER = "#f3f0e8";
const INK = "#0c0c0c";
const ACCENT = "#ff5b1f";

function pad(n: number) {
  return String(n).padStart(2, "0");
}

export interface LinksInBioBrutalistGridProps {
  data?: LinksInBioData;
}

export default function LinksInBioBrutalistGrid({
  data = defaultData,
}: LinksInBioBrutalistGridProps) {
  const products =
    data.richBlocks?.filter(
      (b): b is Extract<RichBlock, { kind: "featured-product" }> =>
        b.kind === "featured-product"
    ) ?? [];

  return (
    <>
      <link rel="preconnect" href="https://fonts.googleapis.com" />
      <link
        rel="stylesheet"
        href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Space+Grotesk:wght@400;500;700&display=swap"
      />
      <section
        className="min-h-screen w-full px-4 py-12 sm:px-6 sm:py-16"
        style={{
          background: PAPER,
          color: INK,
          fontFamily: "'JetBrains Mono', monospace",
        }}
      >
        <div className="mx-auto w-full max-w-[680px]">
          <div className="mb-4 flex items-center justify-between text-[10px] uppercase tracking-[0.25em]">
            <span>// links.bio</span>
            <span>v1 · {new Date().getFullYear()}</span>
          </div>

          <div
            className="grid gap-2 border-2"
            style={{ gridTemplateColumns: "repeat(6, 1fr)", borderColor: INK }}
          >
            {/* AVATAR TILE — spans 2 cols */}
            <div
              className="col-span-2 row-span-2 border-r-2 border-b-2 p-3"
              style={{ borderColor: INK }}
            >
              <div className="aspect-square overflow-hidden border-2" style={{ borderColor: INK }}>
                <img
                  src={data.avatar}
                  alt={data.name}
                  width={400}
                  height={400}
                  loading="eager"
                  className="h-full w-full object-cover"
                  style={{ filter: "grayscale(0.15) contrast(1.05)" }}
                />
              </div>
              <p className="mt-2 text-[10px] uppercase tracking-[0.2em]">[ portrait ]</p>
            </div>

            {/* NAME TILE — spans 4 cols */}
            <div
              className="col-span-4 border-b-2 p-5"
              style={{ borderColor: INK, background: ACCENT, color: INK }}
            >
              <p className="text-[10px] uppercase tracking-[0.25em]">// identity</p>
              <h1
                className="mt-2 leading-[0.95] tracking-tight"
                style={{
                  fontFamily: "'Space Grotesk', sans-serif",
                  fontWeight: 700,
                  fontSize: "clamp(1.6rem, 4.6vw, 2.5rem)",
                }}
              >
                {data.name}
                {data.verified && <span className="ml-2 align-top text-base">[✓]</span>}
              </h1>
              {data.handle && (
                <p className="mt-1 text-sm font-medium">{data.handle}</p>
              )}
            </div>

            {/* BIO TILE — spans 4 cols */}
            <div className="col-span-4 border-b-2 p-5" style={{ borderColor: INK }}>
              <p className="text-[10px] uppercase tracking-[0.25em] opacity-60">// bio</p>
              <p className="mt-2 text-[15px] leading-snug">{data.bio}</p>
            </div>

            {/* LINKS — 2-column grid with selective spanning */}
            {data.links.map((link, i) => {
              const span = i % 5 === 0 ? "col-span-6" : "col-span-3";
              const Icon = link.icon ? ICONS[link.icon] : ArrowUpRight;
              const isAccent = i % 5 === 0;
              return (
                <a
                  key={link.label}
                  href={link.href}
                  className={`group relative ${span} overflow-hidden border-b-2 p-5 transition-colors`}
                  style={{
                    borderColor: INK,
                    borderRightWidth: i % 2 === 0 && span === "col-span-3" ? "2px" : "0",
                    background: isAccent ? INK : "transparent",
                    color: isAccent ? PAPER : INK,
                  }}
                >
                  <span
                    aria-hidden
                    className="absolute right-2 top-2 select-none text-[44px] leading-none opacity-15"
                    style={{
                      fontFamily: "'Space Grotesk', sans-serif",
                      fontWeight: 700,
                      transform: "rotate(-8deg)",
                    }}
                  >
                    {pad(i + 1)}
                  </span>
                  <div className="relative z-10 flex items-start gap-3">
                    <Icon className="mt-0.5 h-4 w-4 shrink-0" strokeWidth={2} />
                    <div className="min-w-0 flex-1">
                      <p
                        className="text-[10px] uppercase tracking-[0.22em] opacity-60"
                      >
                        link · {pad(i + 1)}
                      </p>
                      <p
                        className="mt-1.5 truncate text-base"
                        style={{
                          fontFamily: "'Space Grotesk', sans-serif",
                          fontWeight: 600,
                        }}
                      >
                        {link.label}
                      </p>
                      {link.badge && (
                        <span
                          className="mt-2 inline-block border px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wider"
                          style={{
                            borderColor: isAccent ? PAPER : INK,
                            color: isAccent ? PAPER : INK,
                          }}
                        >
                          {link.badge}
                        </span>
                      )}
                    </div>
                  </div>
                </a>
              );
            })}

            {/* PRODUCT TILES — render any featured-product rich blocks as oversized tiles */}
            {products.map((p, idx) => (
              <a
                key={`product-${idx}`}
                href={p.href}
                className="group col-span-6 grid grid-cols-[140px_1fr] border-b-2 transition-colors hover:bg-black hover:text-[color:var(--paper)] sm:grid-cols-[180px_1fr]"
                style={{ borderColor: INK, ["--paper" as never]: PAPER }}
              >
                <div className="overflow-hidden border-r-2" style={{ borderColor: INK }}>
                  <img
                    src={p.image}
                    alt={p.title}
                    width={400}
                    height={400}
                    loading="lazy"
                    className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.04]"
                  />
                </div>
                <div className="flex flex-col justify-between p-5">
                  <div>
                    <p className="text-[10px] uppercase tracking-[0.25em] opacity-60">
                      // featured · drop {pad(idx + 1)}
                    </p>
                    <p
                      className="mt-2 text-base leading-snug"
                      style={{
                        fontFamily: "'Space Grotesk', sans-serif",
                        fontWeight: 700,
                      }}
                    >
                      {p.title}
                    </p>
                  </div>
                  <div className="mt-4 flex items-center justify-between">
                    <span className="text-lg font-bold">{p.price}</span>
                    <span className="flex items-center gap-1 text-xs font-medium uppercase tracking-widest">
                      Buy <ArrowUpRight className="h-3.5 w-3.5" />
                    </span>
                  </div>
                </div>
              </a>
            ))}

            {/* SOCIALS strip */}
            {data.socials && data.socials.length > 0 && (
              <div
                className="col-span-6 flex flex-wrap items-center gap-2 p-4"
                style={{ background: INK, color: PAPER }}
              >
                <span className="mr-2 text-[10px] uppercase tracking-[0.25em] opacity-70">
                  // socials
                </span>
                {data.socials.map((s, i) => {
                  const Icon = ICONS[s.type] ?? Globe;
                  return (
                    <a
                      key={i}
                      href={s.href}
                      aria-label={s.type}
                      className="border p-2 transition-colors hover:bg-[color:var(--paper)] hover:text-[color:var(--ink)]"
                      style={{
                        borderColor: PAPER,
                        ["--paper" as never]: PAPER,
                        ["--ink" as never]: INK,
                      }}
                    >
                      <Icon className="h-4 w-4" strokeWidth={2} />
                    </a>
                  );
                })}
              </div>
            )}
          </div>

          <div className="mt-3 flex items-center justify-between text-[10px] uppercase tracking-[0.25em] opacity-70">
            <span>{data.links.length + products.length} entries</span>
            <span>// end</span>
          </div>
        </div>
      </section>
    </>
  );
}
Claude Code Instructions

CLI Install

npx innovations add brutalist-grid

Where to use it

A brutalist editorial-zine link-in-bio page. Hardcoded paper/ink palette with an orange accent, JetBrains Mono labels and Space Grotesk display. Pass a typed 'data' prop (LinksInBioData from src/registry/links-in-bio/types.ts) to swap content. With no prop it renders sample data. Add richBlocks entries with kind 'featured-product' to render oversized product tiles inline with the link grid (great for drops, courses, prints). Each takes image + title + price + href. In Astro: import LinksInBioBrutalistGrid from '../components/innovations/links-in-bio/brutalist-grid'; <LinksInBioBrutalistGrid client:load data={myProfile} /> In Next.js: import LinksInBioBrutalistGrid from '@/components/innovations/links-in-bio/brutalist-grid'; Best for: editorial brands, indie shops, designers, zine-makers — any audience that responds to opinionated, deliberately rough typography.