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 🙏

© 2025 – Pkg Stats / Ryan Hefner

htmx-ext-skeleton

v0.2.0

Published

An htmx extension for displaying skeleton screens during AJAX requests

Readme

htmx-ext-skeleton

An htmx extension for displaying skeleton screens during requests.

Installation

Via CDN

<script src="https://unpkg.com/htmx.org"></script>
<script src="https://unpkg.com/htmx-ext-skeleton"></script> 

Via npm

npm install htmx-ext-skeleton

Then import in your JavaScript:

import 'htmx.org';
import 'htmx-ext-skeleton';

Usage

Basic Usage (Default Skeleton)

  1. Define a skeleton template with id="skeleton":
<script type="text/template" id="skeleton">
  <div class="skeleton-placeholder">
    <div class="skeleton-line"></div>
    <div class="skeleton-line"></div>
    <div class="skeleton-line"></div>
  </div>
</script>
  1. Add hx-ext="skeleton" to your htmx element:
<div hx-ext="skeleton" hx-get="/api/data" hx-target="#content">
  Load Data
</div>

<div id="content">
  <!-- Initial content here -->
</div>

Custom Skeleton (Optional)

If you need multiple different skeletons, specify a custom template using any CSS selector:

<script type="text/template" id="custom-skeleton">
  <div class="custom-loading">...</div>
</script>

<div hx-ext="skeleton"
     hx-get="/api/data"
     hx-target="#content"
     hx-skeleton="#custom-skeleton">
  Load Data
</div>

Custom Skeleton Target (Optional)

Use hx-skeleton-target to display the skeleton in a different element than the swap target:

<button hx-ext="skeleton"
        hx-get="/api/data"
        hx-target="#results"
        hx-skeleton-target="#loading-area">
  Load Data
</button>

<div id="loading-area">
  <!-- Skeleton appears here -->
</div>

<div id="results">
  <!-- Data swaps here -->
</div>

If hx-skeleton-target is not specified, the extension falls back to hx-target, and if that's not present, it uses htmx's default target (the element itself).

Alpine.js Integration (Optional)

If Alpine.js is detected, you can override and extend data in your skeleton template using hx-skeleton-alpine:

<script type="text/template" id="skeleton">
  <div x-data="{ title: 'Loading...', count: 3 }">
    <h3 x-text="title"></h3>
    <template x-for="i in count" :key="i">
      <div class="skeleton-item"></div>
    </template>
  </div>
</script>

<div hx-ext="skeleton"
     hx-get="/api/data"
     hx-target="#content"
     hx-skeleton-alpine='{"title": "Loading Projects", "count": 5}'>
  Load Data
</div>

Features

  • Zero configuration: Just add hx-ext="skeleton" and create a template with id="skeleton"
  • Instant feedback: Shows skeleton immediately when request starts
  • Automatic cleanup: Removes skeleton when new content arrives
  • Error handling: Restores original content if request fails
  • History support: Properly handles browser back/forward navigation
  • Multiple skeletons: Use hx-skeleton with any CSS selector for custom templates
  • Custom targets: Use hx-skeleton-target to display skeleton in a different element than the swap target
  • Alpine.js support: Optional integration with Alpine.js for dynamic skeleton templates

How it works

  1. When an htmx request starts (htmx:beforeRequest), the extension:

    • Saves the original content
    • Replaces it with the skeleton template
    • Adds a skeleton-loading class
  2. When the response arrives (htmx:beforeSwap), the extension:

    • Removes the skeleton-loading class
    • Allows htmx to swap in the new content
  3. If an error occurs, the extension:

    • Restores the original content
    • Removes the skeleton-loading class

Styling

Add CSS to style your skeleton screens:

.skeleton-loading {
  pointer-events: none;
  opacity: 0.7;
}

.skeleton-line {
  height: 1rem;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s ease-in-out infinite;
  margin-bottom: 0.5rem;
  border-radius: 4px;
}

@keyframes skeleton-loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

Changelog

0.2.0 (2025-10-04)

  • Breaking/Enhancement: hx-skeleton now accepts any CSS selector instead of just an ID (defaults to #skeleton for backward compatibility)
  • New Feature: Added hx-skeleton-target attribute to specify a different target for skeleton display
  • Enhancement: Improved target resolution - falls back to hx-target, then htmx default if hx-skeleton-target not specified

0.1.1

  • Fixed issue that could cause skeleton to re-appear when navigating back in browser
  • Added tests
  • Updated Alpine.js integration to require x-data initialization within skeleton template
  • Added optional Alpine.js support to skeleton templates

License

MIT