Server-Side Rendering
Boneyard is inherently SSR-friendly. The CLI pre-computes your skeleton layout at build time into .bones.json files — so the skeleton is ready to render on the very first frame. No runtime DOM measurement, no layout shift, no waiting for JavaScript to hydrate.
Pass a fixture prop with representative placeholder data to your <Skeleton>. At build time, Playwright renders this fixture, snapshots the real DOM layout, and writes the exact pixel positions to a .bones.json file. At runtime, import that file as initialBones — the skeleton renders instantly from the pre-generated data, no runtime DOM measurement needed.
Real components on the left, their extracted skeletons on the right.
Notification list
import { Skeleton } from "boneyard-js/react"
import bones from "./bones/notifications.bones.json"
// Fixture — representative data for build-time snapshot
const fixture = [
{ name: "Anna Kim", text: "Merged PR #142" },
{ name: "Tom Lee", text: "Commented on review" },
{ name: "Sara R.", text: "Assigned you to INFRA-301" },
]
export default function Page() {
const { data, isLoading } = useFetch("/api/notifications")
return (
<Skeleton
name="notifications"
loading={isLoading}
fixture={fixture}
initialBones={bones}
>
<NotificationList data={data ?? fixture} />
</Skeleton>
)
}Dashboard stats
Feed post
Just shipped the new dashboard. Feels good to see real metrics after weeks of placeholder data.
- React Server Components — skeleton loads with the page, not after hydration
- Static sites / SSG — bake skeletons into the build output
- Edge functions — render skeletons at the edge with zero runtime cost
- Non-React apps —
renderBonesreturns an HTML string for any template engine
Most skeleton libraries measure the DOM at runtime — which means the skeleton can't render until JavaScript loads and hydrates. Boneyard works differently:
- Bones are pre-computed at build time — the CLI snapshots your real layout and saves it as static JSON
- No runtime DOM measurement —
<Skeleton>reads from the JSON, not fromgetBoundingClientRect - Same API everywhere — use
initialBonesor the registry. Works the same in SSR, SSG, SPAs, and edge functions - Configurable defaults — set colors, animation, and breakpoints in
boneyard.config.json