Skeleton
Skeletons only where your component waits on data, drawn from its own markup. Everything else is already there.
Everything else is already there.
Only data
A skeleton goes on what comes from the data: a title, a price, a name, a photo. Labels, dividers, buttons and icons that are part of the design show as they are from the first frame. A skeleton says data goes here; on a button or a label it says something that isn't true, and hides what's already known.
The skill decides from your component's source and marks each element that shows data withdata-skeleton. In mixed text, only the data part is marked.
<Skeleton loading={isPlaceholderData}>
<p>Order <span data-skeleton>{order.id}</span></p>
<p>Total <span data-skeleton>{order.total}</span></p>
<Button>Track order</Button>
</Skeleton>Loading
Order #0000
Total$00.00
ArrivesDay, Mon 00
Loaded
Order #4821
Total$184.00
ArrivesThursday, Oct 23
A bar per line, no border.
Text
Text from the data (titles, names, prices, dates, counts) becomes one filled bar per line, as long as that line, with square corners and no border. Text is most of what loads: quiet bars read as lines of text at any size, and keep the real text's line count and rhythm.
Loading
A short title
A description of a usual length, a sentence or two, long enough to run over two lines.
Loaded
Notes on a 1542 herbal
Five hundred woodcuts, each colored by hand. The plates were cut first, the text set around them, so every page is laid out like a garden.
Striped, with a border.
Pictures
Images and video become plates: a 1px border and diagonal stripes, the way a layout sketch marks where a picture goes. A round picture, like an avatar, stays round. A picture must never be mistaken for text, and stripes say picture at a glance.
Loading
Loaded



A drawing of the chart that's coming.
Charts
A chart becomes a drawing of itself: its axes and gridlines, as many bars or points as it will have, a bar where each label goes. A plate would only say picture; a chart's shape is known before its numbers are, and the drawing says which chart is coming and where it will sit. It fills the chart's box, its lines kept 1px, so nothing is measured.
Common charts have presets in a package. Any other chart, a sankey, a Gantt timeline, a box plot, the skill draws in one go from its name, its code or a screenshot, with the kit the presets are drawn with. While loading, the drawing stands in the chart's place:
import { BarChartSkeleton } from '@frontendsupply/chart-skeletons';
<Skeleton loading={isPending} className="h-45 w-full">
{isPending ? (
<BarChartSkeleton width={320} height={180} bars={7} />
) : (
<OrdersChart data={data} />
)}
</Skeleton>Loading
Loaded
A circle, if the data picks it.
Icons
An icon the data chooses (a status, a file type, a flag) becomes a 1px circle: a mark goes here, without guessing which. An icon that's always the same, like the clock next to "Updated", is design, and shows as itself.
Loading
- Status
- Updated 0 h ago
Loaded
- Delivered
- Updated 2 h ago
An outline.
Everything else
A data element with nothing inside to read, like a color swatch or a status dot, becomes a 1px outline of its own box. Every line in a skeleton is 1px, and every skeleton has its element's own corners: one line weight keeps a screen full of skeletons calm, and each keeps the shape of what it stands for.
Loading
Loaded
Estimate low.
How much
While loading, the component renders with invented placeholder data. Give it the short end of usual: short names, one-line titles, the fewest rows a list usually has. Real data can make the layout grow when it arrives, which is expected; it should never make it shrink, which looks like a glitch.
Loading
Name
Name
Name
Loaded
Marco Bellini
Hanna Lind
Jamal Okafor
Sofia Rossi
Daniel Cho
A pulse, and nothing moves.
Motion
The skeletons pulse gently, and when the data arrives the bars fade out as it fades in. They're painted by CSS on the placeholder's own layout, rendered with the page: there from the first frame, before any JavaScript, and never jumping. With reduced motion, there's no pulse.
Title
Artist
00 songs
Wrap what loads, nothing more.
Where
Each part that loads on its own gets its own skeleton, and hands over when its data arrives. While a part loads, it can't be clicked or read aloud: its values aren't real yet. Everything outside it works from the start.
Marigold
000 listeners
00 songs
Only for data that isn't there yet.
When not to
No skeleton over content that's already in the page: a post from a static build, text rendered on the server, a list the app already has while it refreshes. A skeleton over what's ready only delays it. A button that's saving shows its own loading state, and an upload shows its progress.
The rules together.
In an app
Three apps built with the boilerplate's components. Each loads its data in parts, the way real screens do. Press refresh in an app's toolbar to load it again.
Overview
Song
Artist
Presets for common charts, any other on demand.
Chart drawings
The presets in @frontendsupply/chart-skeletons, loading. Each takes the chart's design size,width and height in pixels, and how many of its marks there will be: bars, points, slices, series. It fills the chart's box; the rest is the chart's own structure.
They're shortcuts, not the limit. For a chart that isn't here, ask for it by name, paste its code or a screenshot: the skill reads the chart, writes down its structure, and draws it with the same kit, checked like the presets.
pnpm add @frontendsupply/chart-skeletons<LineChartSkeleton series={2} legend="bottom" />
<AreaChartSkeleton />
<BarChartSkeleton bars={7} />
<StackedBarChartSkeleton />
<HorizontalBarChartSkeleton bars={5} />
<PieChartSkeleton />
<DonutChartSkeleton />
<ScatterChartSkeleton />
<RadarChartSkeleton />
<HeatmapSkeleton rows={7} columns={12} />
<CandlestickChartSkeleton />
<FunnelChartSkeleton stages={4} />
<GaugeSkeleton />
<SparklineSkeleton />
Install once per project, then ask.
Getting started
Install the skeleton skill in your project's folder. It works in Claude Code, Codex, Cursor and other agents:
npx skills add frontendsupply/skills --skill skeletonAdd -g to install it for every project on your machine. Then ask, in your own words:
Show a skeleton while the orders table loads.Or give it a chart, by name or as a screenshot:
Make a skeleton for the revenue chart in this screenshot.Or have it replace skeletons drawn by hand:
Replace our hand-drawn skeletons with ones made from the components.It needs React 19 and Tailwind CSS v4, and is built on Base UI and cn, which the skill installs if they're missing.
One variable.
Color
The skeletons take their color from your theme. The skill points it at your tokens:
:root {
--skeleton: #e5e5e5; /* bars, borders and stripes */
}Or just ask.
Commands
/skeleton- What loads in the project and how each screen shows it now. Changes nothing.
/skeleton add orders- Gives a component skeletons: marks its data, writes its placeholder data, wraps it.
/skeleton chart revenue- Draws a chart's skeleton at its size, from its name, its code or a screenshot.
/skeleton refactor- Replaces spinners and hand-drawn skeletons with skeletons drawn from the component.
/skeleton check- Checks the installed component (below).
Paint, never layout.
The check
A script reads your copy of the component and fails any class that turns on while loading and could move a box: the skeletons change only paint, so the placeholder's layout stays as it is under them. It also checks the color is set and Base UI and cn are in place. A second script checks every chart drawing: its viewBox and scaling, only the four parts, lines that stay 1px, no colors, everything inside the box and on the pixel grid. Then the skill opens the screen and looks at it, on desktop and on a phone.