Good things
take shape.
A few ideas. A little motion. A lot of intention.
A few ideas. A little motion. A lot of intention.
An evolving collection: Explore working demos, inspect the code, and try the interactive controls. These experiments are still being refined.
A 3D event badge hanging from a strap. Drag it to swing, double-click to flip, and bind your own name, role, event, colour and photo.
Drag to swing · Double-click to flip
The share link includes your text and colour; photos are never uploaded.
Three steps to add the badge to your own React or Next.js project.
Run this in your project. It installs three.js, React Three Fiber and Lucide icons, and adds the badge files to components/lanyard/.
npx shadcn@latest add https://haneesh.dev/r/lanyard-badge.json
This uses the shadcn CLI. If your project doesn’t have a components.json yet, the CLI asks a few setup questions the first time; the defaults are fine.
Install the dependencies:
pnpm add three @react-three/fiber lucide-react pnpm add -D @types/three
Then create a components/lanyard/ folder and add these three files. They import each other, so keep the names as they are.
Import it and pass your details. Pick an example that matches what you’re building:
Pass your details as props. The badge fills its parent, so give the wrapper a height.
import { LanyardBadge } from '@/components/lanyard/LanyardBadge';
export default function Page() {
return (
<LanyardBadge
name="Haneesh Bandaru"
role="Builder"
event="Hack Week 2026"
date="10–17 Oct 2026"
handle="@yourhandle"
accent="#e2643a"
photo="/me.jpg"
className="h-[520px] w-full"
/>
);
}Every prop is optional; anything you leave out uses the default.
| Prop | Type | Default | What it does |
|---|---|---|---|
| name | string | 'Haneesh Bandaru' | Name printed on the front |
| role | string | 'Builder' | Role or title under the name |
| event | string | 'Your Event' | Event name on the card, back and strap |
| date | string | — | Date shown in the footer |
| handle | string | — | Handle or website shown in the footer |
| accent | string | '#e2643a' | Hex colour for the strap and highlights |
| photo | string | null | — | Portrait image URL; falls back to initials |
| apiRef | Ref<LanyardBadgeApi> | — | Exposes flip(), reset() and downloadPng() |
| className | string | — | Classes for the wrapper — set a height here |
The badge fills its parent and has no height of its own. Give it one, for example className="h-[520px]" or a parent with a fixed height.
Images from another domain must allow cross-origin use (CORS), otherwise the browser blocks the export. Host the photo on your own domain or use an uploaded file.
Yes. LanyardBadge is a client component and loads the 3D scene only in the browser, so you can render it from a Next.js server page.
Text shrinks to fit and is shortened with “…” if it is still too long.
It needs only three.js and React Three Fiber — no physics engine or 3D model files. The scene pauses when it scrolls off-screen, and users with “reduce motion” enabled get a still badge.
Only for the built-in reset/flip/full-screen buttons. Without Tailwind the card still works; restyle or remove those buttons in LanyardBadge.tsx.