None of these are marketing lists. They are places practices ask each other things we would not have thought to answer.
Practices swapping rota patterns, insurer quirks, and the workarounds they wish we had shipped.
2,140
members
One letter on the first Tuesday about what shipped, what broke, and one longer piece of writing.
3,860
subscribers
An open call every second Thursday. No agenda, no demo, and no obligation to turn your camera on.
40
seats each session
A smaller room for managers running four or more sites, where the questions get considerably more specific.
118
practices
We read everything and answer in public wherever we can, because the next practice with that question should not have to ask it again.
A community section listing four linked places to join as full-width hairline rows, each with an icon tile, a description, a light membership figure, and an arrow that shifts on hover.
A community section listing four linked places to join as full-width hairline rows, each with an icon tile, a description, a light membership figure and an arrow that shifts on hover.
Free block
This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.
Radix flavor
npx shadcn add "https://ui.beste.co/r/social48"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/social48"This installs the block to components/beste/block/social48.tsx plus the badge23 component it uses for the eyebrow.
The installed file exports social48Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Social48, social48Demo } from "@/components/beste/block/social48";
export default function CommunityPage() {
return <Social48 {...social48Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { BookOpen, MessagesSquare } from "lucide-react";
import { Social48 } from "@/components/beste/block/social48";
export default function CommunityPage() {
return (
<Social48
badge={{ label: "Where people talk" }}
heading="The rooms our users are already in"
description="None of these are marketing lists."
channels={[
{
icon: MessagesSquare,
name: "The forum",
description: "Practices swapping rota patterns and insurer quirks.",
count: "2,140",
countLabel: "members",
href: "/community/forum",
},
{
icon: BookOpen,
name: "The monthly note",
description: "One letter on the first Tuesday about what shipped and what broke.",
count: "3,860",
countLabel: "subscribers",
href: "/newsletter",
},
]}
footnote="We read everything and answer in public wherever we can."
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string } | – | Eyebrow above the hairline rule, rendered through Badge23 |
heading | string | – | Section heading in the left column of the header |
description | string | – | Supporting paragraph, right-aligned from md up |
channels | Channel[] | [] | Linked places to join, as hairline rows |
footnote | string | – | Closing note under the list |
className | string | – | Extra classes for the outer section |
import type { LucideIcon } from "lucide-react";
type Channel = {
icon: LucideIcon;
name: string;
description: string;
count: string;
countLabel: string;
href: string;
};count and countLabel are separate so the figure can take the display treatment while its unit stays small. The figure uses tabular-nums, so the column aligns down the list.Link elements in a three-track grid from md: name and description, the figure, then the arrow. Below md the arrow is hidden entirely, since the row is already obviously tappable.pl-14 md:pl-0 on mobile, which indents it to line up under the description rather than under the icon tile.group/social48, rather than the bare group class, and its shift is wrapped in motion-safe:.lucide-react icon and hand it over; the block renders it at size-5 in a size-10 tinted tile marked aria-hidden.md:px-4 alongside the hover fill, so the highlight extends slightly past the text on wider screens.border-t with no closing rule, so the list flows into the footnote rather than boxing itself off.social52
An upcoming sessions list with a date block, format, and remaining seats on each linked hairline row, beside a column that sticks and floats a live card for whoever is hosting next.
social53
A community credit section opening on three hairline figures, then naming each contributor in a hairline matrix of cards with their practice, what they changed, and how many reports they filed.
social50
A social section that gives one post an image tile of its own, floating a live post card with its engagement counts, beside the replies it drew as linked hairline rows.
social55
A community section on a soft surface with four bordered figure cards, each explaining what the number counts, over an image tile that floats a live cluster of member portraits.
social7
Group cards with cover images, member count, privacy indicators, category badges, and join buttons. Perfect for community discovery and group listings.
social59
A wall of short community posts in three masonry columns, each a muted card with an avatar, name, handle, a linked timestamp and the note itself, settling in with a small stagger. The header carries a serif headline that settles in word by word and a sliding-marker pill at its right end.