npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

instaskeleton

v0.1.4

Published

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

Readme

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:

| Feature | Benefit | |---------|----------| | ⚡ Zero DOM scanning | No runtime layout measurement, no CLS issues | | 🚀 Zero work when not loading | Early exit skips all computation | | 🎯 Automatic JSX inference | Skeleton shapes generated from your React component tree | | 📐 Manual schema mode | Pixel-perfect control when you need exact layouts | | 💾 Smart LRU caching | Repeated renders are instant (100-entry limit) | | 🎨 Multiple animations | Shimmer, pulse, or none — GPU accelerated | | ♿ Accessibility first | Respects prefers-reduced-motion automatically | | 📦 Tiny bundle | Only ~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.

| Prop | Type | Default | Description | |------|------|---------|-------------| | loading | boolean | required | Show skeleton when true, children when false | | children | ReactNode | required | Content to display when not loading | | schema | SkeletonNode \| SkeletonNode[] | undefined | Manual skeleton definition | | infer | boolean | true | Auto-generate skeleton from children | | cacheKey | string | undefined | Cache inferred schema for reuse | | className | string | undefined | Additional CSS class for the skeleton root | | animation | 'shimmer' \| 'pulse' \| 'none' | 'shimmer' | Animation style | | inferOptions | InferOptions | {} | Control inference behavior |

InferOptions

Fine-tune the inference algorithm:

| Option | Type | Default | Description | |--------|------|---------|-------------| | maxDepth | number | 6 | Maximum JSX tree depth to traverse | | maxNodes | number | 120 | Maximum nodes to process | | textLineHeight | string \| 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 Case | Mode | Why | |----------|------|-----| | Quick prototyping | infer | Zero config, good approximation | | Production cards with specific layout | schema | Pixel-perfect control | | Reusable components | withInstaSkeleton | Consistent API, one config | | Lists with repeated items | infer + cacheKey | Cached after first render | | Complex nested structures | infer + inferOptions | Tune 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.