__________
                      .~#########%%;~.
                     /############%%;`\
                    /######/~\/~\%%;,;,\
                   |#######\    /;;;;.,.|
                   |#########\/%;;;;;.,.|
          XX       |##/~~\####%;;;/~~\;,|       XX
        XX..X      |#|  o  \##%;/  o  |.|      X..XX
      XX.....X     |##\____/##%;\____/.,|     X.....XX
 XXXXX.....XX      \#########/\;;;;;;,, /      XX.....XXXXX
X |......XX%,.@      \######/%;\;;;;, /      @#%,XX......| X
X |.....X  @#%,.@     |######%%;;;;,.|     @#%,.@  X.....| X
X  \...X     @#%,.@   |# # # % ; ; ;,|   @#%,.@     X.../  X
 X# \.X        @#%,.@                  @#%,.@        X./  #
  ##  X          @#%,.@              @#%,.@          X   #
, "# #X            @#%,.@          @#%,.@            X ##
   `###X             @#%,.@      @#%,.@             ####'
  . ' ###              @#%.,@  @#%,.@              ###`"
    . ";"                @#%.@#%,.@                ;"` ' .
      '                    @#%,.@                   ,.
      ` ,                @#%,.@  @@                `
                          @@@  @@@                  .

[!WARNING] Experimental: This package is under active development. APIs and generated output may change between releases.

Skullmaster

Skullmaster is a CLI tool that lets you generate customizable skeleton loaders for your UI components directly from the browser. Instead of manually creating placeholder components, Skullmaster analyzes the rendered component and generates a matching skeleton that you can customize further with data attributes.

Getting started

Step 1: Install Skullmaster

npm install skullmaster@beta --save-dev
npm install @skullmaster/react@beta

Step 2: Start the Development Server

Start the Skullmaster development server:

npm skullmaster serve

On the first run, Skullmaster will guide you through a short setup.

You'll be asked to choose:

After setup, the following file will be created:

## <outDir>/skeletons/DefaultBone.tsx

DefaultBone.tsx is the fallback skeleton that is rendered whenever a generated skeleton does not exist.

The development server will then be available at:

http://localhost:8080

Step 3: Mark a Component

Register any element you want to generate a skeleton for using the markAsSkull helper from @skullmaster/react. Spread the returned props onto the element:

import { markAsSkull } from "@skullmaster/react";

<div {...markAsSkull("ProfileCard")}>...</div>;

The name argument becomes the skeleton name.

You can also fine-tune an element without registering it as a named component using tweakForSkull:

import { tweakForSkull } from "@skullmaster/react";

<fieldset {...tweakForSkull({ hideSubTree: true })}>...</fieldset>;

Both helpers accept a tweaks object: hideSubTree (sets data-skip-skull), isTransparent (sets data-depth="-1"). If you prefer, you can still set these data-* attributes manually instead.

Step 4: Render the Skeleton

Render the skeleton anywhere in your application using the generated registry.

<Skeleton name="ProfileCard" />

Import the Skeleton component from:

<outDir>/registry.tsx

Until the skeleton is generated, DefaultBone will be rendered.

Step 5: Install the React Runtime

npm install @skullmaster/react@next

This package sends component information from your React application to the running Skullmaster development server.

Step 6: Add the Provider

In your application's entry file (App.tsx, main.tsx, or layout.tsx), add the skullmaster component:

import { Skullmaster } from "@skullmaster/react";

<Skullmaster />;

Step 7: Generate Your First Skeleton

Start both:

Then:

  1. Enable Skullmaster using the skull icon.
  2. Hover over a component marked with data-skullmaster.
  3. Click the download button.

Skullmaster will analyze the rendered component and generate its skeleton automatically.

The generated file will be saved to:

<outDir>/skeletons/ProfileCard.tsx

Step 8: Use the Generated Skeleton

Once generated, rendering:

<Skeleton name="ProfileCard" />

will display the generated skeleton instead of DefaultBone.

How it works

Generating an accurate skeleton requires runtime information that only exists after your application has been rendered by the browser. This includes the final HTML structure, computed styles, image dimensions, text layout, and other rendering details.

Skullmaster solves this by running a small development helper inside your application. During development, this helper collects the runtime information required to recreate your UI as a skeleton and sends it to the Skullmaster CLI, which runs locally (by default on port 8080).

The CLI receives this payload and generates skeleton components for your chosen framework.

Generated output

Unlike approaches that reconstruct your skeletons from scratch, Skullmaster preserves the original DOM structure as much as possible. The generated skeleton closely resembles the original markup.

For example, unlike libraries such as 0xGF/boneyard, Skullmaster does not flatten your UI into a collection of generic <div> elements. Semantic elements such as <article>, <section>, <header>, <nav>, <button>, and <img> are preserved whenever possible.

Interactive elements are transformed so they remain visually accurate while behaving like non-interactive placeholders.

During generation, Skullmaster performs the following transformations:

Why preserve the DOM?

Keeping the generated markup close to the original component has several advantages:

Customization

The generated skeleton is intended to be a starting point. Depending on your component, the default output may not always match the level of detail you want. In some cases, generating placeholders for every DOM element can make the skeleton appear overly cluttered.

To reduce unnecessary visual noise, SkullMaster automatically assigns data-depth="-1" to elements that are used only for layout or are not visually significant. These elements are rendered as transparent while still preserving the layout.

You can also control these attributes yourself instead of writing them by hand. The <outDir>/registry.{tsx, jsx} package exports two helpers that apply the attributes as type-safe props:

Both accept a SkullTweaks object:

If you prefer to set the attributes manually, you can still do so:

If you want to exclude an entire subtree from skeleton generation, add the data-skip-skull attribute to its root element. SkullMaster will ignore that element and all of its descendants during generation.

<div data-skip-skull>
  <!-- This subtree will not be included in the generated skeleton -->
</div>

Accessibility

Generated skeletons are intended to be visual placeholders only.

To avoid confusing screen reader users, SkullMaster automatically removes interactive behavior, marks placeholder content as inaccessible, and applies the appropriate aria-busy attributes to indicate that content is still loading.

Generated skeletons should never be interpreted as meaningful page content.

Caveats