Skip to content
Brok UI

Loading…

No results

Biolink

Open source

Link-in-bio layouts — a centered mobile-first column with avatar, bio and a stack of full-width link buttons.

Preview

resources/views/blocks/biolink-card.blade.php Blade
@props([
    'name'     => 'Mara Ellison',
    'handle'   => '@maraellison',
    'bio'      => 'Product designer & creative coder. I share systems, side projects, and tools that help you build faster.',
    'avatar'   => null,
    'fallback' => 'ME',
    'verified' => true,
    'links'    => null,
    'socials'  => null,
])

@php
    $links ??= [
        ['label' => 'Design System Handbook', 'subtitle' => 'Free, 12-chapter guide', 'href' => '#', 'icon' => 'article'],
        ['label' => 'Book a mentoring call', 'subtitle' => '45 min, Calendly', 'href' => '#', 'icon' => 'calendar'],
        ['label' => 'Browse the icon pack', 'subtitle' => '600+ icons, $19', 'href' => '#', 'icon' => 'store'],
        ['label' => 'Watch the latest teardown', 'subtitle' => 'YouTube, 22 min', 'href' => '#', 'icon' => 'play'],
        ['label' => 'Join the newsletter', 'subtitle' => 'Weekly, Free', 'href' => '#', 'icon' => 'mail'],
        ['label' => 'Download Figma starter', 'subtitle' => 'Community, Free', 'href' => '#', 'icon' => 'figma'],
    ];
    $socials ??= [['label' => 'X', 'href' => '#', 'icon' => 'x'], ['label' => 'GitHub', 'href' => '#', 'icon' => 'github'], ['label' => 'YouTube', 'href' => '#', 'icon' => 'youtube']];
    $tileIcons = [
        'article' => 'M4 5a2 2 0 0 1 2-2h9l5 5v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5Zm10-1v5h5M8 13h8M8 17h5',
        'calendar' => 'M7 3v3m10-3v3M4 9h16M5 6h14a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1Z',
        'store' => 'M4 9h16l-1 11H5L4 9Zm2-4h12l1 4H5l1-4Zm3 8v3m6-3v3',
        'play' => 'M5 5.5v13a1 1 0 0 0 1.52.85l10.5-6.5a1 1 0 0 0 0-1.7L6.52 4.65A1 1 0 0 0 5 5.5Z',
        'mail' => 'M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7Zm0 .5 8 5 8-5',
        'figma' => 'M8.5 2H12v7H8.5A3.5 3.5 0 1 1 8.5 2Zm3.5 0h3.5a3.5 3.5 0 1 1 0 7H12V2Zm0 9.5h3.5a3.5 3.5 0 1 1 0 7H12v-7Zm-3.5 0H12V22H8.5a3.5 3.5 0 1 1 0-7Z',
        'link' => 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
    ];
    $socialIcons = [
        'x' => 'M4 4l16 16M20 4 4 20',
        'github' => 'M9 19c-4 1.5-4-2.5-6-3m12 6v-3.5a3 3 0 0 0-.8-2.3c2.7-.3 5.5-1.3 5.5-6a4.6 4.6 0 0 0-1.3-3.2 4.3 4.3 0 0 0-.1-3.2s-1-.3-3.4 1.3a11.6 11.6 0 0 0-6 0C6.5 2.5 5.5 2.8 5.5 2.8a4.3 4.3 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.2c0 4.6 2.8 5.7 5.5 6a3 3 0 0 0-.8 2.3V21',
        'youtube' => 'M22 8.2a3 3 0 0 0-2.1-2.1C18 5.5 12 5.5 12 5.5s-6 0-7.9.6A3 3 0 0 0 2 8.2 31 31 0 0 0 1.5 12 31 31 0 0 0 2 15.8a3 3 0 0 0 2.1 2.1c1.9.6 7.9.6 7.9.6s6 0 7.9-.6a3 3 0 0 0 2.1-2.1A31 31 0 0 0 22.5 12 31 31 0 0 0 22 8.2ZM10 15V9l5 3-5 3Z',
    ];
@endphp

<section {{ $attributes->merge(['class' => 'flex min-h-[60vh] items-center justify-center bg-muted/30 py-12 text-foreground']) }}>
    <div class="mx-auto w-full max-w-md px-4">
        <x-ui.card class="overflow-hidden shadow-md">
            <div class="flex flex-col items-center px-6 pb-4 pt-8 text-center">
                <x-ui.avatar size="xl" :src="$avatar" :alt="$name" :fallback="$fallback" class="ring-4 ring-background" />
                <h1 class="mt-4 flex items-center justify-center gap-2 text-lg font-semibold tracking-tight">
                    {{ $name }}
                    @if ($verified)
                        <span class="inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground" role="img" aria-label="{{ __('Verified') }}">
                            <svg class="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5 12 4 4L19 7" /></svg>
                        </span>
                    @endif
                </h1>
                <p class="mt-0.5 text-sm font-medium text-muted-foreground">{{ $handle }}</p>
                @if ($bio)<p class="mt-4 text-pretty text-sm leading-relaxed text-muted-foreground">{{ __($bio) }}</p>@endif
            </div>

            <hr class="border-border" />

            <nav class="grid grid-cols-2 gap-4 p-4" aria-label="{{ __('Links') }}">
                @foreach ($links as $link)
                    <a href="{{ $link['href'] }}" class="group flex flex-col items-start gap-2 rounded-lg border border-border bg-card p-6 transition-colors hover:border-primary/40 hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
                        <span class="flex size-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground transition-colors group-hover:bg-primary/10 group-hover:text-primary" aria-hidden="true">
                            <svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="{{ $tileIcons[$link['icon']] ?? $tileIcons['link'] }}" /></svg>
                        </span>
                        <span class="flex flex-col gap-0.5">
                            <span class="line-clamp-2 text-xs font-semibold leading-snug text-foreground">{{ __($link['label']) }}</span>
                            @if (! empty($link['subtitle']))<span class="text-xs leading-snug text-muted-foreground">{{ __($link['subtitle']) }}</span>@endif
                        </span>
                    </a>
                @endforeach
            </nav>

            <hr class="border-border" />

            <div class="flex items-center justify-center gap-2 px-4 py-4">
                @foreach ($socials as $social)
                    <x-ui.button :href="$social['href']" variant="ghost" size="icon" class="rounded-full text-muted-foreground hover:text-foreground" aria-label="{{ __($social['label']) }}">
                        <svg class="size-[1.125rem]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="{{ $socialIcons[$social['icon']] ?? $socialIcons['x'] }}" /></svg>
                    </x-ui.button>
                @endforeach
            </div>
        </x-ui.card>
    </div>
</section>

Installation

terminal
php artisan ui:add blocks/biolink-card

Installs these dependencies automatically:

Registry contract

Install confidence

php artisan ui:add blocks/biolink-card writes only the generated targets below. The CLI validates each file hash before writing and prompts before replacing local changes unless --force is used.

Version
1.0.4
License
open
Stability
stable
Contract
v1
Foundation
≥ 1.0.0
Type Generated target
blade resources/views/blocks/biolink-card.blade.php

Registry dependencies

card avatar button

Package dependencies

composer: jml/brok:^0.2

Use with AI

A brief for your coding agent: what the block is, the install command, how to render it, its props and the rules. Copy it, or open a prompt about this block in an assistant.

biolink-card.md
# Brok UI block: Biolink Card (`biolink-card`)

A link-in-bio card with an avatar, verified name, bio, a two-column grid of link tiles and a social-icon row.

Brok UI is a Laravel Blade registry. `ui:add` copies this block into the app as plain Blade the app owns; it composes installed `<brok:*>` primitives and semantic design tokens.

## Install

```bash
php artisan ui:add blocks/biolink-card
```

## Render it

```blade
<x-blocks.biolink-card />
```

## Props

- `name` (string, default `Mara Ellison`)
- `handle` (string, default `@maraellison`)
- `bio` (string, default `Product designer & creative coder. I share systems, side projects, and tools that help you build faster.`)
- `avatar` (mixed|null, default `null`)
- `fallback` (string, default `ME`)
- `verified` (bool, default `true`)
- `links` (mixed|null, default `null`)
- `socials` (mixed|null, default `null`)

## Use when

- Building a link-in-bio card with an avatar, bio and a two-column grid of link tiles rather than a single stacked list.
- Closing the card with a social-icon row beneath the link grid.

## Avoid when

- Use biolink-links for a single-column stacked link list, or biolink-cover for a cover-banner layout.

## Rules

- Render the installed block with `<x-blocks.biolink-card />` and pass data through its props; edit the copied file only for structural changes.
- Keep the semantic design tokens (`bg-background`, `text-muted-foreground`); never swap in raw colour utilities.
- Keep the `data-slot` attributes and the logical (start/end) spacing so the markup still mirrors under `dir="rtl"`.

## Links

- Docs: https://brokui.dev/blocks/biolink-card
- Registry JSON (files, props, contract): https://brokui.dev/r/open/blocks/biolink-card.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

Guidance

Use when

  • Building a link-in-bio card with an avatar, bio and a two-column grid of link tiles rather than a single stacked list.
  • Closing the card with a social-icon row beneath the link grid.

Avoid when

  • Use biolink-links for a single-column stacked link list, or biolink-cover for a cover-banner layout.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.

Usage

Render the block as a component, passing data where useful:

resources/views/welcome.blade.php Blade
<x-blocks.biolink-card />

Built from primitives

Composes <brok:*> Semantic tokens Re-themeable RTL-ready

This block composes installed <brok:*> primitives and semantic design tokens only — it does not reimplement any primitive. Re-theme it (light, dark, admin, customer) by editing CSS variables; flip the preview to RTL to confirm it mirrors.

Source

The exact, editable file ui:add writes into your app. The preview above renders this same source — there are no preview-only blocks.

resources/views/blocks/biolink-card.blade.php Blade
@props([
    'name'     => 'Mara Ellison',
    'handle'   => '@maraellison',
    'bio'      => 'Product designer & creative coder. I share systems, side projects, and tools that help you build faster.',
    'avatar'   => null,
    'fallback' => 'ME',
    'verified' => true,
    'links'    => null,
    'socials'  => null,
])

@php
    $links ??= [
        ['label' => 'Design System Handbook', 'subtitle' => 'Free, 12-chapter guide', 'href' => '#', 'icon' => 'article'],
        ['label' => 'Book a mentoring call', 'subtitle' => '45 min, Calendly', 'href' => '#', 'icon' => 'calendar'],
        ['label' => 'Browse the icon pack', 'subtitle' => '600+ icons, $19', 'href' => '#', 'icon' => 'store'],
        ['label' => 'Watch the latest teardown', 'subtitle' => 'YouTube, 22 min', 'href' => '#', 'icon' => 'play'],
        ['label' => 'Join the newsletter', 'subtitle' => 'Weekly, Free', 'href' => '#', 'icon' => 'mail'],
        ['label' => 'Download Figma starter', 'subtitle' => 'Community, Free', 'href' => '#', 'icon' => 'figma'],
    ];
    $socials ??= [['label' => 'X', 'href' => '#', 'icon' => 'x'], ['label' => 'GitHub', 'href' => '#', 'icon' => 'github'], ['label' => 'YouTube', 'href' => '#', 'icon' => 'youtube']];
    $tileIcons = [
        'article' => 'M4 5a2 2 0 0 1 2-2h9l5 5v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5Zm10-1v5h5M8 13h8M8 17h5',
        'calendar' => 'M7 3v3m10-3v3M4 9h16M5 6h14a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1Z',
        'store' => 'M4 9h16l-1 11H5L4 9Zm2-4h12l1 4H5l1-4Zm3 8v3m6-3v3',
        'play' => 'M5 5.5v13a1 1 0 0 0 1.52.85l10.5-6.5a1 1 0 0 0 0-1.7L6.52 4.65A1 1 0 0 0 5 5.5Z',
        'mail' => 'M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7Zm0 .5 8 5 8-5',
        'figma' => 'M8.5 2H12v7H8.5A3.5 3.5 0 1 1 8.5 2Zm3.5 0h3.5a3.5 3.5 0 1 1 0 7H12V2Zm0 9.5h3.5a3.5 3.5 0 1 1 0 7H12v-7Zm-3.5 0H12V22H8.5a3.5 3.5 0 1 1 0-7Z',
        'link' => 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
    ];
    $socialIcons = [
        'x' => 'M4 4l16 16M20 4 4 20',
        'github' => 'M9 19c-4 1.5-4-2.5-6-3m12 6v-3.5a3 3 0 0 0-.8-2.3c2.7-.3 5.5-1.3 5.5-6a4.6 4.6 0 0 0-1.3-3.2 4.3 4.3 0 0 0-.1-3.2s-1-.3-3.4 1.3a11.6 11.6 0 0 0-6 0C6.5 2.5 5.5 2.8 5.5 2.8a4.3 4.3 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.2c0 4.6 2.8 5.7 5.5 6a3 3 0 0 0-.8 2.3V21',
        'youtube' => 'M22 8.2a3 3 0 0 0-2.1-2.1C18 5.5 12 5.5 12 5.5s-6 0-7.9.6A3 3 0 0 0 2 8.2 31 31 0 0 0 1.5 12 31 31 0 0 0 2 15.8a3 3 0 0 0 2.1 2.1c1.9.6 7.9.6 7.9.6s6 0 7.9-.6a3 3 0 0 0 2.1-2.1A31 31 0 0 0 22.5 12 31 31 0 0 0 22 8.2ZM10 15V9l5 3-5 3Z',
    ];
@endphp

<section {{ $attributes->merge(['class' => 'flex min-h-[60vh] items-center justify-center bg-muted/30 py-12 text-foreground']) }}>
    <div class="mx-auto w-full max-w-md px-4">
        <x-ui.card class="overflow-hidden shadow-md">
            <div class="flex flex-col items-center px-6 pb-4 pt-8 text-center">
                <x-ui.avatar size="xl" :src="$avatar" :alt="$name" :fallback="$fallback" class="ring-4 ring-background" />
                <h1 class="mt-4 flex items-center justify-center gap-2 text-lg font-semibold tracking-tight">
                    {{ $name }}
                    @if ($verified)
                        <span class="inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground" role="img" aria-label="{{ __('Verified') }}">
                            <svg class="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5 12 4 4L19 7" /></svg>
                        </span>
                    @endif
                </h1>
                <p class="mt-0.5 text-sm font-medium text-muted-foreground">{{ $handle }}</p>
                @if ($bio)<p class="mt-4 text-pretty text-sm leading-relaxed text-muted-foreground">{{ __($bio) }}</p>@endif
            </div>

            <hr class="border-border" />

            <nav class="grid grid-cols-2 gap-4 p-4" aria-label="{{ __('Links') }}">
                @foreach ($links as $link)
                    <a href="{{ $link['href'] }}" class="group flex flex-col items-start gap-2 rounded-lg border border-border bg-card p-6 transition-colors hover:border-primary/40 hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
                        <span class="flex size-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground transition-colors group-hover:bg-primary/10 group-hover:text-primary" aria-hidden="true">
                            <svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="{{ $tileIcons[$link['icon']] ?? $tileIcons['link'] }}" /></svg>
                        </span>
                        <span class="flex flex-col gap-0.5">
                            <span class="line-clamp-2 text-xs font-semibold leading-snug text-foreground">{{ __($link['label']) }}</span>
                            @if (! empty($link['subtitle']))<span class="text-xs leading-snug text-muted-foreground">{{ __($link['subtitle']) }}</span>@endif
                        </span>
                    </a>
                @endforeach
            </nav>

            <hr class="border-border" />

            <div class="flex items-center justify-center gap-2 px-4 py-4">
                @foreach ($socials as $social)
                    <x-ui.button :href="$social['href']" variant="ghost" size="icon" class="rounded-full text-muted-foreground hover:text-foreground" aria-label="{{ __($social['label']) }}">
                        <svg class="size-[1.125rem]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="{{ $socialIcons[$social['icon']] ?? $socialIcons['x'] }}" /></svg>
                    </x-ui.button>
                @endforeach
            </div>
        </x-ui.card>
    </div>
</section>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.0.4
Status
Stable
License
open
Deprecation
Not deprecated
Contract
v1
Foundation
≥ 1.0.0