Blueprint

A finished layout that builds itself. It starts as a wireframe measured from your real markup, then fills in block by block: text streams in, photos come into focus, buttons pop up. Scrub back and it comes apart again.

  • Layout
  • Scroll
  • Motion

Uses motion, clsx, tailwind-merge

Open in ChatGPTOpen in Claude
barro.studio
Barro

Ceramics studio · Lisbon

Pottery for slow mornings

Hand-thrown in Alfama, fired twice, and made to be used every day, not saved for guests.

Wheel classes every Saturday

Stoneware bowls and cups on a wooden table
Describe a site…↵

Installation

Add the component on its own with the CLI, or copy the file in by hand.

The CLI writes components/ui/blueprint.tsx and installs motion, clsx and tailwind-merge. It needs the @keyframeui registry in components.json; add it once per project.

npx shadcn@latest add @keyframeui/blueprint

Examples

Finished sections built with Blueprint. Each one installs whole, with the component included.

Studio Process

A case study that goes from an annotated blueprint to the finished design as you scroll, with `play="manual"` following `useScroll`. `data-blueprint-order` groups the build into type, imagery and surfaces, and `onBlockChange` lights up the matching stage in the rail. Scroll back up and it comes apart.

Case study 07

  1. Wireframe

  2. Type

  3. Imagery

  4. Final

Ondas CoffeeBrand · Web · 2026

A roaster's site that smells like the shop

We rebuilt Ondas around the Tuesday roast: one weekly drop, tasting notes from the roaster, and a checkout that takes under a minute.

+48%

online orders

3.1×

repeat buyers

Generated Dashboard

An analytics assistant answers with a dashboard card. KPIs count up through `data-blueprint-count`, chart bars grow from even placeholders into their real heights through `--blueprint-progress`, and table rows fill in cell by cell. Drag the scrubber to take it apart and put it back.

Revenue by region, last quarter

Built from 4 queries on orders and accounts

Revenue by region

Q3 2026 · Jul 1 – Sep 30

Revenue

$4.82M

vs. Q2

+12.4%

Orders

18,240

NAEUAPACLATAMMEA
RegionRevenueChange
North America$1.64M+14.2%
Europe$1.38M+9.8%
Asia Pacific$1.02M+21.5%
Latin America$0.49M+6.1%
Middle East & Africa$0.29M+3.4%
0%

Props

childrenRequired

TypeReact.ReactNode

Your markup. Every element marked with data-blueprint becomes a block; unmarked content shows as it is from the start.

play

Type"auto" | "scroll" | "manual"Default"auto"

auto rests on the wireframe, builds, holds the page, comes apart and starts over, pausing on hover and off screen. scroll builds as the section scrolls into view, finishing when it's centered. manual follows progress.

progress

Typenumber | MotionValue<number>

Build progress in manual mode, from 0 (wireframe) to 1 (finished page). Pass a MotionValue, such as one from useScroll, to drive it without re-rendering.

onProgressChange

Type(progress: number) => void

Called whenever Blueprint moves the progress itself: the auto loop, scrolling, or the scrubber. In manual mode only the scrubber calls it, so feed the value back into progress.

duration

Typenumber | { build?: number; hold?: number; unbuild?: number; rest?: number }Default5

Seconds the build takes in auto mode, or each part of the loop: the build (5), the hold on the finished page (2.5), coming apart (1) and the rest on the wireframe (0.8).

onLoop

Type(loop: number) => void

Called as each auto loop starts on the wireframe, with the loop count (0 first). Use it to swap content between builds; the wireframe re-measures to match.

onBlockChange

Type(element: HTMLElement, state: "wireframe" | "building" | "built") => void

Called when a marked element starts building, finishes, or goes back to its wireframe. The same state is on the element as data-blueprint-state for styling.

annotate

TypebooleanDefaultfalse

Put a small spec label beside each block until it's built, read from its computed styles: "H1 · 56/60", "Image 16:9", "Button".

scrubber

TypebooleanDefaultfalse

Show a scrubber under the stage, with a tick where each block starts. Drag or use the arrow keys to build and unbuild by hand; in auto mode the loop carries on from where you let go.

className

Typestring

Classes for the stage, the positioned box your markup and the skeletons share.

skeletonClassName

Typestring

Classes for the skeleton layer. Bars, boxes, outlines and labels are all drawn from its text color, so text-white turns the wireframe white on a dark or blue stage.

data-blueprint

Type"" | "text" | "image" | "button" | "box"

Attribute on your markup that makes an element a block. Left empty, the kind is guessed: images and video are image, buttons and filled links are button, elements with only inline text are text, anything else is a box. Only boxes can hold other blocks.

data-blueprint-order

TypenumberDefault0

Attribute that moves a block later in the build. Blocks build in order of this number, then in reading order, so 1 on every image builds all the text first.

data-blueprint-label

Typestring

Attribute that replaces a block's annotation. An empty value hides it.

data-blueprint-count

Typeboolean

Attribute for text blocks: numbers in it count up from zero as they stream in, keeping their format ("$4.82M", "18,240", "+12.4%").