🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

instaskeleton

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

instaskeleton

Ultra-light React skeleton loader with zero DOM scanning. Automatic JSX inference, manual schema support, shimmer & pulse animations. Only ~1.65KB gzipped.

latest
Source
npmnpm
Version
0.1.4
Version published
Weekly downloads
27
237.5%
Maintainers
1
Weekly downloads
 
Created
Source

instaskeleton

Ultra-light React skeleton loader with zero DOM scanning — the fastest way to add loading states to your React app

npm version bundle size npm downloads license TypeScript

Live Demo 🚀

instaskeleton is the lightest React skeleton loading library that doesn't scan your DOM. Perfect for building fast, responsive loading states in React applications with shimmer animations, pulse effects, and automatic JSX inference.

~1.2 KB JS + ~0.45 KB CSS = ~1.65 KB gzipped (total)

Table of Contents

Why instaskeleton?

The problem with other React skeleton loaders:

  • They require separate skeleton components for every UI element (tedious)
  • They scan the DOM at runtime to generate placeholders (slow, causes layout shifts)
  • They bloat your bundle with unnecessary dependencies

instaskeleton solves this differently:

FeatureBenefit
Zero DOM scanningNo runtime layout measurement, no CLS issues
🚀 Zero work when not loadingEarly exit skips all computation
🎯 Automatic JSX inferenceSkeleton shapes generated from your React component tree
📐 Manual schema modePixel-perfect control when you need exact layouts
💾 Smart LRU cachingRepeated renders are instant (100-entry limit)
🎨 Multiple animationsShimmer, pulse, or none — GPU accelerated
Accessibility firstRespects prefers-reduced-motion automatically
📦 Tiny bundleOnly ~1.65KB gzipped total

Install

npm install instaskeleton

Import the bundled styles once:

import 'instaskeleton/styles.css';

Quick Start

Use inference when you want the fastest setup:

import { InstaSkeleton } from 'instaskeleton';
import 'instaskeleton/styles.css';

type Product = {
  title: string;
  price: string;
};

function ProductCard({
  loading,
  product
}: {
  loading: boolean;
  product: Product;
}) {
  return (
    <InstaSkeleton loading={loading} infer cacheKey="product-card-v1">
      <article>
        <img src="/cover.png" alt="" />
        <h3>{product.title}</h3>
        <p>{product.price}</p>
        <button>Add to cart</button>
      </article>
    </InstaSkeleton>
  );
}

Manual Schema

Use manual schema when you want the skeleton to resemble the inner component structure more closely.

import { InstaSkeleton, type SkeletonNode } from 'instaskeleton';

const articleCardSchema: SkeletonNode[] = [
  { type: 'rect', height: '12rem', radius: '1rem' },
  { type: 'line', width: '68%' },
  { type: 'line', width: '92%' },
  { type: 'line', width: '40%' }
];

function ArticleCard({ loading }: { loading: boolean }) {
  return (
    <InstaSkeleton loading={loading} schema={articleCardSchema} infer={false}>
      <article>
        <img src="/hero.png" alt="" />
        <h3>How we removed DOM scanning from loading states</h3>
        <p>Manual schema mirrors the actual card anatomy.</p>
        <small>5 min read</small>
      </article>
    </InstaSkeleton>
  );
}

HOC Pattern

Use withInstaSkeleton when you want to preconfigure loading behavior for a reusable component.

import { withInstaSkeleton } from 'instaskeleton';

function StatCard({ label, value }: { label: string; value: string }) {
  return (
    <div>
      <span>{label}</span>
      <strong>{value}</strong>
    </div>
  );
}

const StatCardWithSkeleton = withInstaSkeleton(StatCard, {
  skeleton: [
    { type: 'line', width: '35%', height: '0.75rem' },
    { type: 'rect', height: '3rem', radius: '0.75rem' }
  ],
  infer: false,
  cacheKey: 'stat-card'
});

<StatCardWithSkeleton loading={isLoading} label="Downloads" value="12.4k" />;

API Reference

<InstaSkeleton>

The main component for wrapping content with skeleton loading states.

PropTypeDefaultDescription
loadingbooleanrequiredShow skeleton when true, children when false
childrenReactNoderequiredContent to display when not loading
schemaSkeletonNode | SkeletonNode[]undefinedManual skeleton definition
inferbooleantrueAuto-generate skeleton from children
cacheKeystringundefinedCache inferred schema for reuse
classNamestringundefinedAdditional CSS class for the skeleton root
animation'shimmer' | 'pulse' | 'none''shimmer'Animation style
inferOptionsInferOptions{}Control inference behavior

InferOptions

Fine-tune the inference algorithm:

OptionTypeDefaultDescription
maxDepthnumber6Maximum JSX tree depth to traverse
maxNodesnumber120Maximum nodes to process
textLineHeightstring | number'0.95rem'Height for text line skeletons

withInstaSkeleton(Component, options)

HOC to create a skeleton-wrapped version of any component.

const WrappedComponent = withInstaSkeleton(MyComponent, {
  skeleton: [...],      // Manual schema
  infer: false,         // Disable inference
  cacheKey: 'my-comp',  // Cache key
  className: 'custom',  // Root class
  animation: 'pulse',   // Animation style
});

// Adds `loading` prop to the component
<WrappedComponent loading={isLoading} {...props} />

clearInstaSkeletonCache(key?)

Clear cached schemas:

import { clearInstaSkeletonCache } from 'instaskeleton';

// Clear specific cache entry
clearInstaSkeletonCache('product-card');

// Clear all cached schemas
clearInstaSkeletonCache();

SkeletonNode

Supported node types:

line — Text placeholder

{ type: 'line', width: '80%', height: '1rem' }

rect — Block placeholder (images, buttons, cards)

{ type: 'rect', width: '100%', height: '8rem', radius: '1rem' }

circle — Avatar or icon placeholder

{ type: 'circle', width: '3rem', height: '3rem' }

group — Container for nested nodes

{
  type: 'group',
  gap: '0.75rem',
  children: [
    { type: 'circle', width: '3rem', height: '3rem' },
    { type: 'line', width: '60%' },
    { type: 'line', width: '40%' },
  ]
}

Performance

Zero Work When Not Loading

// When loading=false, InstaSkeleton returns children immediately
// No inference, no schema processing, no DOM overhead
if (!loading) return <>{children}</>;

LRU Cache with Size Limit

Schemas are cached with a 100-entry limit to prevent memory leaks in long-running SPAs.

GPU-Accelerated Animations

Shimmer animation uses will-change: transform for 60fps performance.

Reduced Motion Support

Animations are disabled automatically when prefers-reduced-motion: reduce is set.

Choosing The Right Mode

Use CaseModeWhy
Quick prototypinginferZero config, good approximation
Production cards with specific layoutschemaPixel-perfect control
Reusable componentswithInstaSkeletonConsistent API, one config
Lists with repeated itemsinfer + cacheKeyCached after first render
Complex nested structuresinfer + inferOptionsTune depth/node limits

Development

npm run build        # Build the library
npm run typecheck    # Run TypeScript checks
npm run dev          # Watch mode

Browser Support

  • Chrome/Edge 88+
  • Firefox 78+
  • Safari 14+

Keywords

react skeleton, skeleton loader, react loading, loading placeholder, shimmer animation, react placeholder, skeleton screen, loading state, react ui components, typescript skeleton, lightweight skeleton loader, zero dom scanning, jsx inference

License

MIT © LittleBoy9

Found this useful? Give it a ⭐ on GitHub!

Notes

  • Inference walks the React element tree, not the rendered DOM.
  • Function components may be unwrapped, but hook-heavy components can fall back to child inference.
  • If you need strict visual matching, use manual schema.

Keywords

skeleton

FAQs

Package last updated on 14 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts