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

@benpley/wappler-smart-image

v1.0.2

Published

On-the-fly image processing for Wappler with Sharp - resize, convert formats, and intelligent caching

Readme

Smart Image for Wappler

A full-stack image optimization extension for Wappler that automatically resizes, converts, and caches images on the fly — served through a clean <smart-img> component that is a direct drop-in replacement for the standard HTML <img> element.

Authors: Shalabh Gupta & Ben Pleysier

⚠️ Node.js only — This extension requires a Wappler Node.js project. It is not compatible with PHP or ASP.NET Wappler projects. The server-side processing depends on Node.js-specific libraries (Sharp, Express route hooks, and EJS templates).


Why Smart Image?

Replacing <img> with <smart-img> requires no configuration and gives you:

  • Automatic responsive images — the right size for mobile, tablet, and desktop
  • Retina / HiDPI support — 2× variants served automatically to high-density screens
  • Modern formats — WebP or AVIF generated on the fly from your original JPG/PNG
  • Blur-up placeholder — a blurred preview is shown instantly while the full image loads
  • Lazy loading — built in by default
  • Server-side caching — processed images are cached and served in subsequent requests at zero cost
  • Zero layout shift — set width and height to reserve space before load

Installation

Install via Wappler's built-in extension manager:

  1. Open your project in Wappler
  2. Go to Project Options → Extensions
  3. Search for and install Smart Image

On install, the extension automatically sets up:

  • app/config/smart-image.json — project configuration file
  • The server-side route hook so the image() EJS helper is available
  • The <smart-img> runtime under /public/js/smart-image.js
  • The App Connect component tile for use in the visual editor

Quick Start

Drop-in replacement for <img>

Simply swap <img> for <smart-img>:

<!-- Before -->
<img src="/assets/images/hero.jpg" alt="Hero">

<!-- After — responsive, retina-aware, lazy-loaded, with blur placeholder -->
<smart-img src="/assets/images/hero.jpg" alt="Hero"></smart-img>

That single change delivers desktop, tablet, and mobile variants in AVIF or WebP format, with a retina 2× version for each — all generated and cached automatically.

In the Wappler Visual Editor

Click on the Smart Image tile (found under Media) onto your page. Set the src to your source image and adjust widths and format as needed.

With explicit sizing

<smart-img
  id="hero_image"
  src="/assets/images/hero.jpg"
  alt="Hero banner"
  desktop-width="1600"
  tablet-width="1024"
  mobile-width="640"
  format="avif"
  width="1600"
  height="900">
</smart-img>

How It Works

Server Side (modules/smart-image.js)

When an image is requested, the server-side module:

  1. Validates the source path (must be in a configured source folder, no special characters)
  2. Checks the cache — if a fresh cached variant exists, returns its versioned URL immediately
  3. Auto-downscales oversized images if they exceed maxWidth / maxHeight
  4. Processes the image using Sharp — resize, convert, apply quality settings
  5. Writes the result to /public/<cacheRoot>/... and serves it with ETag and Last-Modified headers for automatic browser cache invalidation
  6. Optionally prepends a CDN base URL to the returned path

A concurrency lock ensures the same file is never generated twice simultaneously.

Cache Invalidation

No ?v= version strings are needed. Cache invalidation is handled automatically through the following chain:

  1. Every request to a cache URL (e.g. /img-cache/assets/images/hero-1600.webp) passes through the route handler
  2. The handler compares the source image mtime against the cached file mtime
  3. If the source is newer (e.g. you replaced hero.jpg with a different image of the same name), the cache file is regenerated automatically
  4. The regenerated file has a new mtime, which means a new ETag
  5. The browser's previously cached ETag no longer matches → Express returns 200 with the fresh content
  6. On subsequent requests where nothing has changed → Express returns 304 Not Modified — instant, zero bandwidth

This means replacing a source image on disk — even with a completely different image of the same filename and dimensions — is detected and handled correctly without any manual cache clearing or version management.

Client Side (includes/smart-image.js)

The <smart-img> custom element:

  1. Detects the current breakpoint (mobile/tablet/desktop) and pixel density using media queries and devicePixelRatio
  2. Constructs the correct cache URL matching the server-side naming convention
  3. Displays a blur-up placeholder (auto-generated from a tiny canvas render, or a manual image)
  4. Loads the optimised image and fades it in once ready
  5. Falls back to the original source image if the optimised variant fails to load
  6. Reacts to viewport changes — swaps to the appropriate variant when the viewport is resized

<smart-img> Attributes

Images

| Attribute | Default | Description | |---|---|---| | src | — | Source image path (must be under a configured source folder) | | desktop-width | 1600 | Target width for desktop | | tablet-width | 1024 | Target width for tablet | | mobile-width | 640 | Target width for mobile | | retina | 2 | Retina multiplier applied to each breakpoint width | | format | webp | Output format: avif, webp, jpeg, png | | fallback-format | jpeg | Fallback format if the primary image fails to load | | cache-root | img-cache | Cache folder prefix — change only if configured differently on the server |

Breakpoints

| Attribute | Default | Description | |---|---|---| | mobile-breakpoint | 767 | Max viewport width (px) at which the mobile image is used | | tablet-breakpoint | 1199 | Max viewport width (px) at which the tablet image is used |

Options

| Attribute | Default | Description | |---|---|---| | alt | — | Alt text for screen readers (supports App Connect data binding) | | title | — | Tooltip title attribute | | class | — | CSS classes applied to the inner <img> (e.g. img-fluid rounded) | | loading | lazy | lazy or eager | | fetchpriority | auto | auto, high, or low — use high for above-the-fold images | | placeholder-mode | auto | auto (blur), manual (use placeholder attribute), or none | | placeholder | — | Manual placeholder image URL shown while the main image loads | | width | — | Intrinsic width in pixels — prevents layout shift (CLS) | | height | — | Intrinsic height in pixels — prevents layout shift (CLS) |

Events

| Event | Description | |---|---| | load | Fired when the image has successfully loaded | | error | Fired when the image fails to load |


Project Configuration

Configuration lives at app/config/smart-image.json:

{
  "cacheRoot": "img-cache",
  "cdnBase": "",
  "sourceFolders": [
    "assets/logo",
    "assets/images",
    "assets/blog"
  ],
  "warmOnStart": false,
  "warmVariants": [
    { "width": 1200, "format": "webp" },
    { "width": 1600, "format": "webp" },
    { "width": 1600, "format": "jpeg" }
  ],
  "maxWidth": 2400,
  "maxHeight": 2400,
  "defaultQuality": 75,
  "allowedSourceFormats": [".jpg", ".jpeg", ".png", ".webp", ".svg"]
}

Troubleshooting

Images not processing / image is not defined in EJS

  • The startup route hook was not registered, or the server has not been restarted since install.
  • Verify that extensions/server_connect/routes/smart-image.js exists.

Image not found warnings in the console

  • The source image path must be inside one of the configured sourceFolders.
  • File names must use only letters, numbers, dashes, underscores, and dots — no spaces or special characters.

Version

Current version: 1.0.2 — Fix Node route hook package require path

What's included in 1.0.2

  • Fixed the generated Node route hook so extensions/server_connect/routes/smart-image.js now requires @benpley/wappler-smart-image/routes/smart-image-routes
  • Kept the legacy alias file extensions/server_connect/smart-image.js pointing to ./routes/smart-image

Previously included in 1.0.1

Server-side (Node.js / Sharp)

  • On-the-fly image resizing and format conversion (AVIF, WebP, JPEG, PNG) via Sharp
  • Automatic cache invalidation by comparing source and cache file mtime — no manual version strings needed
  • Concurrency lock prevents duplicate generation when multiple requests arrive for the same variant simultaneously
  • Auto-downscale of oversized source images that exceed the configured maxWidth / maxHeight
  • Optional cache warm-up on server start (warmOnStart) to pre-generate variants for all configured source folders
  • Orphan cache cleanup utility — removes cached variants whose source images no longer exist

Client-side (<smart-img> custom element)

  • Breakpoint-aware image selection (desktop / tablet / mobile) with configurable breakpoint thresholds
  • Retina / HiDPI support — 2× (or custom multiplier) variants served automatically
  • Blur-up placeholder with three modes: auto (generated), manual (custom image), none
  • Optional fallback image when the optimised variant fails to load
  • display-size attribute: responsive (fills available width) or original (natural size)
  • Reacts to viewport resize — swaps to the correct variant dynamically

Wappler integration

  • Visual editor tile under Media with full property panel and App Connect data-binding support for alt
  • app/config/smart-image.json scaffolded automatically on install
  • Express route hook registered at startup — no manual wiring required

License

MIT — developed for the Wappler community.