Sidhanshu MongaContribution
GitHub↗
/ Engineering contribution — C.04Independent
← All contributions

Runtime-adaptive loading interfaces

Loading states generated from the real structure of an interface, instead of hand-maintained placeholder layouts.

Organization
Independent
Dates
2024 — present · v0.4.2
Status
Open source · maintained · zero runtime dependencies

The problem

Skeleton screens are maintained by hand. Every list, card and profile gets a second, parallel component made of grey rectangles, and that component is wrong the moment the real one changes. The cost is not writing it once — it is that two things now have to be kept in agreement forever, and nothing fails when they drift.

The visible symptom is layout shift. A hand-drawn placeholder approximates the real layout, so the swap to content moves the page. The usual fixes make it worse: freeze the skeleton and it stops matching responsive behaviour; generate it from a design file and it stops matching what shipped.

My role

Sole author. The measurement core, the layout compiler, the learning and storage layer, the React, Vue, Svelte and Next adapters, the CLI, and the documentation site are all mine. React appears as a peer dependency; the package itself ships with none.

The approach

Stop describing the layout and measure it. The real component has already told the browser exactly what shape it is; a skeleton is a question the DOM can answer.

So Skelly reads the geometry of a subtree that has rendered once, compiles it to a small coordinate spec, and replays that spec the next time the same region is waiting on data. The placeholder is derived from the thing it stands in for, which means it cannot drift from it — and the layout shift on release approaches zero because the boxes were measured from the boxes.

The honest limit, documented rather than hidden: a layout has to be seen before it can be replayed, so a first visit falls back to a generic shape unless it is seeded with a preset, an explicit spec, or layouts committed to the repo.

Architecture

Four stages, each one independently usable:

  1. MeasureWalk the element subtree, recording position, bounds, border radius and an element kind — text, image, structural block, or surface. Decoration opts out with data-skelly-ignore rather than being painted and hidden.
  2. CompileFlatten the measurements into a compact JSON spec — one entry per box, percentage widths where the element was fluid, so the spec survives a change of viewport instead of pinning pixels.
  3. RenderPaint the spec as an animated overlay. Nothing here reads the DOM, which is what lets the same spec render on a server with no layout engine at all.
  4. LearnOn release, measure the real content again and store it under the region’s name, bucketed by viewport width. The next load starts with the answer already in hand.

Splitting measure from render is what makes the server path possible. A spec is data, so it can be committed, shipped in the HTML, and painted before any JavaScript arrives — the case a client-only skeleton library cannot cover.

Implementation

The spec is the whole interface between the halves. One entry per box, and percentage widths where the measured element was fluid:

[
  { "x": 0,  "y": 10, "w": 380,   "h": 22, "type": "block" },
  { "x": 0,  "y": 74, "w": 44,    "h": 44, "r": "50%", "type": "image" },
  { "x": 56, "y": 80, "w": "95%", "h": 10, "type": "text" }
]

Because that is the only contract, the framework adapters are thin: each one owns a lifecycle hook and a ref, and hands the subtree to the same core. The package publishes separate entry points for the core, React, Vue, Svelte and Next, plus a CLI and a build helper for committing learned layouts. The repo measures each entry point itself — npm run size — which is the number worth trusting over anything written in a README.

Sources

Public references, so none of the above has to be taken on my word.