Release Timeline
A dated changelog on a vertical rail with added/changed/fixed tags and machine-readable <time> values.
An about-page team section on initials avatars rather than photos, so shipping it never waits on headshots and there is no broken-image state to design.
components/team-grid.tsxnpx hoverlab add team-grid
Or over MCP, from your editor's agent — no account needed.
Free to read, copy and install, for personal and non-commercial projects. Shipping it in client work or a paid product needs Pro ($79 once). The source lands in your repo and stops being ours — no attribution, nothing to upgrade.
Start a page with this section — add more, order them, and leave with the page source.
A small team spread across four time zones, shipping every week since 2023.
Co-founder & CEO
Previously led platform at a payments unicorn; still reviews PRs.
Co-founder & CTO
Wrote the first commit in March 2023 and the incident runbook the week after.
Head of Design
Believes every empty state deserves as much care as the dashboard.
Staff Engineer
Owns the sync engine; measures success in p99s, not features.
Product Manager
Turns forty support tickets a week into a roadmap the team believes in.
Developer Advocate
If you found us through a conference talk in 2026, it was probably his.
Rendered live in your current theme — this is the same component whose source is below, not a screenshot of it.
/**
* <TeamGrid> — the about-page team section, without the photo shoot.
*
* Initials avatars instead of photos is the load-bearing decision. Photos
* mean an asset pipeline, a cropping convention, a retina variant, and a
* broken-image state for the person who joined last week — the grid looks
* unfinished until everyone has sat for the same photographer. Initials
* drawn from the design tokens are correct on day one, theme with the
* page, and never 404. The palette varies by person but stays inside the
* token system, so both themes hold without a single hex value.
*
* Social links are real anchors with accessible names — an icon-only link
* with no label is a mystery button to a screen reader.
*/
import * as React from 'react'
import { Github, Linkedin, Twitter } from 'lucide-react'
export interface TeamMember {
name: string
role: string
bio: string
/** Overrides the initials derived from the name. */
initials?: string
twitter?: string
linkedin?: string
github?: string
}
export interface TeamGridProps {
heading?: string
intro?: string
members?: TeamMember[]
className?: string
}
/** Token/opacity combos only — no hex, so both themes stay coherent. */
const AVATAR_STYLES = [
'bg-primary/15 text-primary',
'bg-secondary text-secondary-foreground',
'bg-muted text-foreground',
'bg-primary/10 text-primary',
'bg-accent text-accent-foreground',
'bg-muted/60 text-muted-foreground',
]
const DEFAULT_MEMBERS: TeamMember[] = [
{
name: 'Priya Raghavan',
role: 'Co-founder & CEO',
bio: 'Previously led platform at a payments unicorn; still reviews PRs.',
twitter: '#', linkedin: '#', github: '#',
},
{
name: 'Marcus Okafor',
role: 'Co-founder & CTO',
bio: 'Wrote the first commit in March 2023 and the incident runbook the week after.',
twitter: '#', github: '#',
},
{
name: 'Elena Sokolova',
role: 'Head of Design',
bio: 'Believes every empty state deserves as much care as the dashboard.',
twitter: '#', linkedin: '#',
},
{
name: 'Tom Whitfield',
role: 'Staff Engineer',
bio: 'Owns the sync engine; measures success in p99s, not features.',
github: '#', linkedin: '#',
},
{
name: 'Aisha Diallo',
role: 'Product Manager',
bio: 'Turns forty support tickets a week into a roadmap the team believes in.',
twitter: '#', linkedin: '#',
},
{
name: 'Daniel Kim',
role: 'Developer Advocate',
bio: 'If you found us through a conference talk in 2026, it was probably his.',
twitter: '#', github: '#', linkedin: '#',
},
]
function initialsOf(name: string): string {
const parts = name.trim().split(/\s+/)
const first = parts[0]?.[0] ?? ''
const last = parts.length > 1 ? parts[parts.length - 1][0] : ''
return (first + last).toUpperCase()
}
export function TeamGrid({
heading = 'The people building it',
intro = 'A small team spread across four time zones, shipping every week since 2023.',
members = DEFAULT_MEMBERS,
className = '',
}: TeamGridProps) {
return (
<section className={`mx-auto w-full max-w-5xl px-6 py-16 ${className}`}>
<h2 className="text-2xl font-bold tracking-tight sm:text-3xl">{heading}</h2>
<p className="mt-2 max-w-2xl text-sm text-muted-foreground sm:text-base">{intro}</p>
<ul className="mt-10 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{members.map((member, index) => (
<li
key={member.name}
className="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground"
>
<div className="flex items-center gap-3">
<span
aria-hidden
className={`flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold ${
AVATAR_STYLES[index % AVATAR_STYLES.length]
}`}
>
{member.initials ?? initialsOf(member.name)}
</span>
<div className="min-w-0 flex-1">
{member.name ? (
<h3 data-stress-ignore className="break-words text-sm font-semibold">{member.name}</h3>
) : null}
<p className="break-words text-xs text-muted-foreground">{member.role}</p>
</div>
</div>
<p className="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">
{member.bio}
</p>
<div className="mt-4 flex gap-1">
{member.twitter ? (
<a
href={member.twitter}
aria-label={`${member.name} on X`}
className="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
<Twitter aria-hidden className="h-4 w-4" />
</a>
) : null}
{member.linkedin ? (
<a
href={member.linkedin}
aria-label={`${member.name} on LinkedIn`}
className="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
<Linkedin aria-hidden className="h-4 w-4" />
</a>
) : null}
{member.github ? (
<a
href={member.github}
aria-label={`${member.name} on GitHub`}
className="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
<Github aria-hidden className="h-4 w-4" />
</a>
) : null}
</div>
</li>
))}
</ul>
</section>
)
}
bg-card, text-muted-foreground) — it inherits your theme instead of overriding it.Drop it at components/team-grid.tsx and import it where you need the section:
import { TeamGrid } from '@/components/team-grid'2 of this block’s props are simple enough to drive from here. Change them and the block below re-renders — it is the same component whose source is above, not a mock of it. Everything else it accepts is in the table underneath.
Read out of the component’s own type and signature, so this cannot drift from the source below. Every prop has a default — the component renders standalone before you pass it anything.
| Prop | Type | Default |
|---|---|---|
heading | string | 'The people building it' |
intro | string | 'A small team spread across four time zones, … |
members | TeamMember[] | DEFAULT_MEMBERS |
className | string | '' |
The same block rendered once to markup, wrapped as a file your framework compiles. Tailwind classes are framework-agnostic, so the design transfers intact — the behaviour does not.
<!--
Team Grid — markup from the Hoverlab catalog.
This is the block rendered once to HTML and wrapped as a component
file. It is not a port of the React source: the Tailwind classes carry
the design, which is the part that took the work, and they are the same
in every framework.
This block has no interactive behaviour, so nothing is missing.
-->
<section class="mx-auto w-full max-w-5xl px-6 py-16 ">
<h2 class="text-2xl font-bold tracking-tight sm:text-3xl">The people building it</h2>
<p class="mt-2 max-w-2xl text-sm text-muted-foreground sm:text-base">A small team spread across four time zones, shipping every week since 2023.</p>
<ul class="mt-10 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<li class="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground">
<div class="flex items-center gap-3">
<span aria-hidden="true" class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold bg-primary/15 text-primary">PR</span>
<div class="min-w-0 flex-1">
<h3 data-stress-ignore="true" class="break-words text-sm font-semibold">Priya Raghavan</h3>
<p class="break-words text-xs text-muted-foreground">Co-founder & CEO</p>
</div>
</div>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">Previously led platform at a payments unicorn; still reviews PRs.</p>
<div class="mt-4 flex gap-1">
<a href="#" aria-label="Priya Raghavan on X" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-twitter h-4 w-4" aria-hidden="true">
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path>
</svg>
</a>
<a href="#" aria-label="Priya Raghavan on LinkedIn" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-linkedin h-4 w-4" aria-hidden="true">
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
<rect width="4" height="12" x="2" y="9"></rect>
<circle cx="4" cy="4" r="2"></circle>
</svg>
</a>
<a href="#" aria-label="Priya Raghavan on GitHub" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-github h-4 w-4" aria-hidden="true">
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path>
<path d="M9 18c-4.51 2-5-2-7-2"></path>
</svg>
</a>
</div>
</li>
<li class="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground">
<div class="flex items-center gap-3">
<span aria-hidden="true" class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold bg-secondary text-secondary-foreground">MO</span>
<div class="min-w-0 flex-1">
<h3 data-stress-ignore="true" class="break-words text-sm font-semibold">Marcus Okafor</h3>
<p class="break-words text-xs text-muted-foreground">Co-founder & CTO</p>
</div>
</div>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">Wrote the first commit in March 2023 and the incident runbook the week after.</p>
<div class="mt-4 flex gap-1">
<a href="#" aria-label="Marcus Okafor on X" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-twitter h-4 w-4" aria-hidden="true">
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path>
</svg>
</a>
<a href="#" aria-label="Marcus Okafor on GitHub" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-github h-4 w-4" aria-hidden="true">
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path>
<path d="M9 18c-4.51 2-5-2-7-2"></path>
</svg>
</a>
</div>
</li>
<li class="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground">
<div class="flex items-center gap-3">
<span aria-hidden="true" class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold bg-muted text-foreground">ES</span>
<div class="min-w-0 flex-1">
<h3 data-stress-ignore="true" class="break-words text-sm font-semibold">Elena Sokolova</h3>
<p class="break-words text-xs text-muted-foreground">Head of Design</p>
</div>
</div>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">Believes every empty state deserves as much care as the dashboard.</p>
<div class="mt-4 flex gap-1">
<a href="#" aria-label="Elena Sokolova on X" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-twitter h-4 w-4" aria-hidden="true">
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path>
</svg>
</a>
<a href="#" aria-label="Elena Sokolova on LinkedIn" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-linkedin h-4 w-4" aria-hidden="true">
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
<rect width="4" height="12" x="2" y="9"></rect>
<circle cx="4" cy="4" r="2"></circle>
</svg>
</a>
</div>
</li>
<li class="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground">
<div class="flex items-center gap-3">
<span aria-hidden="true" class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold bg-primary/10 text-primary">TW</span>
<div class="min-w-0 flex-1">
<h3 data-stress-ignore="true" class="break-words text-sm font-semibold">Tom Whitfield</h3>
<p class="break-words text-xs text-muted-foreground">Staff Engineer</p>
</div>
</div>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">Owns the sync engine; measures success in p99s, not features.</p>
<div class="mt-4 flex gap-1">
<a href="#" aria-label="Tom Whitfield on LinkedIn" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-linkedin h-4 w-4" aria-hidden="true">
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
<rect width="4" height="12" x="2" y="9"></rect>
<circle cx="4" cy="4" r="2"></circle>
</svg>
</a>
<a href="#" aria-label="Tom Whitfield on GitHub" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-github h-4 w-4" aria-hidden="true">
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path>
<path d="M9 18c-4.51 2-5-2-7-2"></path>
</svg>
</a>
</div>
</li>
<li class="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground">
<div class="flex items-center gap-3">
<span aria-hidden="true" class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold bg-accent text-accent-foreground">AD</span>
<div class="min-w-0 flex-1">
<h3 data-stress-ignore="true" class="break-words text-sm font-semibold">Aisha Diallo</h3>
<p class="break-words text-xs text-muted-foreground">Product Manager</p>
</div>
</div>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">Turns forty support tickets a week into a roadmap the team believes in.</p>
<div class="mt-4 flex gap-1">
<a href="#" aria-label="Aisha Diallo on X" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-twitter h-4 w-4" aria-hidden="true">
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path>
</svg>
</a>
<a href="#" aria-label="Aisha Diallo on LinkedIn" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-linkedin h-4 w-4" aria-hidden="true">
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
<rect width="4" height="12" x="2" y="9"></rect>
<circle cx="4" cy="4" r="2"></circle>
</svg>
</a>
</div>
</li>
<li class="flex min-w-0 flex-col rounded-2xl border border-border/60 bg-card/60 p-5 text-card-foreground">
<div class="flex items-center gap-3">
<span aria-hidden="true" class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full text-sm font-bold bg-muted/60 text-muted-foreground">DK</span>
<div class="min-w-0 flex-1">
<h3 data-stress-ignore="true" class="break-words text-sm font-semibold">Daniel Kim</h3>
<p class="break-words text-xs text-muted-foreground">Developer Advocate</p>
</div>
</div>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted-foreground">If you found us through a conference talk in 2026, it was probably his.</p>
<div class="mt-4 flex gap-1">
<a href="#" aria-label="Daniel Kim on X" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-twitter h-4 w-4" aria-hidden="true">
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"></path>
</svg>
</a>
<a href="#" aria-label="Daniel Kim on LinkedIn" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-linkedin h-4 w-4" aria-hidden="true">
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
<rect width="4" height="12" x="2" y="9"></rect>
<circle cx="4" cy="4" r="2"></circle>
</svg>
</a>
<a href="#" aria-label="Daniel Kim on GitHub" class="rounded-lg p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-github h-4 w-4" aria-hidden="true">
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path>
<path d="M9 18c-4.51 2-5-2-7-2"></path>
</svg>
</a>
</div>
</li>
</ul>
</section>
What each framework gets across the whole catalog — effects convert properly; this rung is markup.
The component, its props, the design tokens it expects and the command that installs it — as one prompt. Paste it into Claude, Cursor, v0 or ChatGPT and what they build around it will match the rest of the catalog instead of inventing its own system.
Want the whole screen instead of this one section? Open a page and copy it entire.
All of them free to read, copy and install — no account, no locked tiles, no watermarked preview. The whole catalog is open, and so are the API and the CLI.
Browse Content & BlogCopying the code is free. Putting it in client work or a paid product is what Pro is for — the licence, not the access.
A dated changelog on a vertical rail with added/changed/fixed tags and machine-readable <time> values.
Shipped / in progress / planned in three columns, with status carried by icon as well as colour.
A featured post at full width above a card grid, with drawn covers built from tokens — a blog index with no image pipeline and no broken-thumbnail state.
A grid of case-study cards that lead with the metric rather than the company name, each one linking out to the full write-up — the block a customer-stories section or a home page needed and only had a full case-study page for.
Kicker, headline, standfirst, byline and share row, with the opening prose and a pull quote included — the type scale of a post, decided once instead of per-article.
Openings grouped by department with location, type and salary on every row — candidates self-select by craft first, and a flat list makes them scan for it.
Sidebar, article and on-this-page rail — each column answers a different question, and they collapse on mobile in the order that keeps the article alive.
Method badge, path, parameter table and a request/response pair kept side by side — an example request whose response is a scroll away gets pasted blind.
One install command behind npm/pnpm/yarn/bun tabs with a working copy button — every reader uses exactly one package manager, so showing all four wastes three lines.
A CV as a document rather than a timeline of cards — one column, dates on the end edge, and a print layer that puts it on paper without a separate PDF to keep in step.
The watch screen with no playback in it: a ratio-locked stage, a control bar drawn down to the buffered layer, and an up-next rail. Drop a video element in and wire your own player.