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

@revenexx/storage-nuxt-image

v0.1.0

Published

Nuxt Image provider for the revenexx Storage CDN. Build optimized, on-the-fly image URLs against your own domain's /cdn/ endpoint.

Downloads

111

Readme

@revenexx/storage-nuxt-image

The Nuxt Image provider for the revenexx Storage CDN. Optimized, on-the-fly images straight from your own domain's /cdn/ endpoint — resize, crop, smart gravity, format negotiation, colour grading, watermarks and presets, all as clean query params.

npm version npm downloads License: MIT


Why

  • 🌐 Bring your own domain. Images are served from your site (https://my-shop.com/cdn/…), not a third-party host. Leave the base URL empty and URLs stay relative — the same build works on every customer domain automatically.
  • 🪄 /cdn/ is appended for you. Point images at a path; the provider routes them through the edge.
  • 🧰 The full transform surface. Resize, crop, smart & focus-point gravity, colour adjustments, blur/sharpen, watermarks, format/quality, presets — and a raw escape hatch for everything else.
  • 📐 Native Nuxt modifiers. width, height, fit, format, quality, background map automatically. Works with <NuxtImg>, <NuxtPicture> and $img.
  • 🎨 Batteries included. Ready-made presets (thumbnail, avatar, card, hero, ogImage, placeholder) and a typed watermark API.
  • 🔒 Safe by design. Transforms are plain query params; the CDN validates, clamps and signs them server-side — your app never handles signing keys.
  • 🪶 Tiny & isomorphic. One dependency (ufo), runs on server and client, ships ESM + types. Also usable without Nuxt via the URL builder.

Contents

Installation

npm i @revenexx/storage-nuxt-image        # or pnpm add / yarn add
npx nuxi module add image                 # @nuxt/image (peer)

Quick start

// nuxt.config.ts
import { presets } from '@revenexx/storage-nuxt-image'

export default defineNuxtConfig({
  modules: ['@nuxt/image'],
  image: {
    provider: 'storage',          // make it the default (optional)
    presets,                      // ship-ready presets (optional)
    providers: {
      storage: {
        provider: '@revenexx/storage-nuxt-image',
        options: {
          // Empty → relative URLs (recommended, see below). Or pin a domain:
          // baseURL: 'https://my-shop.com',
        },
      },
    },
  },
})
<template>
  <NuxtImg src="/sftp-imports/header.jpg" width="800" height="450" fit="cover" format="webp" />
</template>

/cdn/sftp-imports/header.jpg?w=800&h=450&fit=cover&fm=webp

The browser resolves that relative URL against the current site, so on my-shop.com it becomes https://my-shop.com/cdn/…, where the revenexx edge serves (and caches) the optimized image.

Bring your own domain

Sites run on their own domain pointed at the revenexx edge, which exposes image processing under /cdn/. Two ways to target it:

  1. Relative URLs (recommended, multi-domain / white-label). Leave baseURL empty → the provider emits /cdn/…, resolved against whatever origin serves the page. One build, every domain — zero per-tenant config.

  2. Absolute URLs. Set baseURL to pin an origin (SSR, emails, sitemaps, or images on a different host):

    options: { baseURL: 'https://my-shop.com' }

/cdn/ is always appended — change it with cdnPath (or cdnPath: '' to disable).

Usage

<NuxtImg>

<!-- standard modifiers as props -->
<NuxtImg src="/uploads/p.jpg" width="600" height="400" fit="cover" format="webp" quality="80" />

<!-- richer transforms via :modifiers -->
<NuxtImg src="/uploads/p.jpg" :width="600" :modifiers="{ gravity: 'sm', blur: 3 }" />

<!-- a named preset -->
<NuxtImg preset="card" src="/uploads/p.jpg" />

<NuxtPicture> (responsive & multi-format)

<NuxtPicture> emits a <picture> with multiple <source>s — perfect for serving AVIF with a WebP fallback and the right size per viewport:

<NuxtPicture
  src="/uploads/hero.jpg"
  format="avif,webp"
  sizes="sm:100vw md:50vw lg:1200px"
  :modifiers="{ gravity: 'sm' }"
/>

$img composable

Need the URL itself (CSS background, <meta> tags, canvas)?

<script setup lang="ts">
const img = useImage()
const bg = img('/uploads/p.jpg', { width: 1600, format: 'webp' }, { provider: 'storage' })
</script>

<template>
  <section :style="{ backgroundImage: `url(${bg})` }" />
</template>

Modifiers

Standard Nuxt modifiers map automatically:

| Modifier | Query param | Notes | | ------------ | ------------ | ---------------------------------------------------- | | width | w | | | height | h | | | fit | fit | cover · contain · fill · inside · outside | | format | fm | webp, avif, jpg, png, gif | | quality | q | 0100 | | background | background | 'ffffff' or [r, g, b] |

The richer set (gravity, crop, adjust, blur/sharpen, trim, padding, rotate, watermark, …) goes through :modifiers; structured options take ergonomic objects:

<NuxtImg
  src="/uploads/p.jpg"
  :modifiers="{
    gravity: { type: 'fp', x: 0.5, y: 0.35 },   // focus point
    crop: { width: 1000, height: 1000, gravity: 'sm' },
    adjust: { brightness: 10, contrast: 0.9, saturation: 1.1 },
    quality: 80,
    stripMetadata: true,
  }"
/>

👉 Full list with every option, value shape and example: docs/transformations.md.

Anything not modelled? Use the escape hatch:

{ rawOptions: ['gr:0.5:1:0'] } // → ?opts=gr:0.5:1:0

Presets

Define transform bundles once, reference them by name. Ship-ready presets are included — spread them into image.presets:

import { presets } from '@revenexx/storage-nuxt-image'
export default defineNuxtConfig({ image: { provider: 'storage', presets } })
<NuxtImg preset="card" src="/uploads/photo.jpg" />

| Preset | Output | | ------------- | ---------------------------- | | thumbnail | 150×150, smart crop, webp | | avatar | 96×96, smart crop, webp | | card | 400×300, smart crop, webp | | hero | 1920×1080, smart crop, webp | | ogImage | 1200×630 social card, jpg | | placeholder | 32px blurred LQIP, webp |

Extend or override:

image: {
  presets: {
    ...presets,
    banner: { width: 1600, height: 400, fit: 'cover', format: 'webp', quality: 80 },
  },
}

These are Nuxt presets — they expand to modifiers before the request, so they work on any CDN tier.

Watermarks

Overlay the watermark configured on your CDN. Shorthand sets opacity; the object form adds position, offset and scale:

<NuxtImg src="/uploads/photo.jpg" :modifiers="{ watermark: 0.4 }" />

<NuxtImg
  src="/uploads/photo.jpg"
  :modifiers="{ watermark: { opacity: 0.4, position: 'soea', x: 16, y: 16, scale: 0.15 } }"
/>

positionce no so ea we noea nowe soea sowe re (re tiles it). The watermark image itself is configured on the CDN; this modifier controls how it is applied.

Recipes

Common real-world patterns — responsive hero, LQIP blur-up placeholder, avatars, Open Graph images, CSS backgrounds, art direction — are collected in the cookbook → docs/recipes.md.

Programmatic / standalone usage

No Nuxt required — import the builder:

import { buildImageUrl } from '@revenexx/storage-nuxt-image/builder'

buildImageUrl('/uploads/a.jpg', { width: 400, format: 'webp' }, { baseURL: 'https://my-shop.com' })
// → 'https://my-shop.com/cdn/uploads/a.jpg?w=400&fm=webp'

Great for plain <img> tags, Open Graph URLs, emails, RSS, or back-end services.

Security & signing

You don't sign anything. Transforms are ordinary query params; the revenexx edge validates and clamps them, then signs the upstream transform request server-side. That keeps signing keys off the client and prevents abusive/arbitrary transforms — by design. (Private assets use short-lived signed delivery URLs minted by the storage API.)

TypeScript

Fully typed. Import the public types when you need them:

import type {
  TransformModifiers, ProviderOptions, ImagePreset, WatermarkPosition,
} from '@revenexx/storage-nuxt-image'

API

| Export | Kind | Description | | ------------------- | -------- | ---------------------------------------------------- | | default | provider | The Nuxt Image provider (point provider here). | | getImage | function | The provider's getImage(src, ctx). | | buildImageUrl | function | Framework-agnostic URL builder (also at /builder). | | serializeModifiers| function | Modifiers → query string. | | presets | object | Ready-made Nuxt Image presets. | | types | — | TransformModifiers, ProviderOptions, ImagePreset, WatermarkPosition, Gravity, Crop, Adjust, Trim, Watermark, … |

Provider options

| Option | Type | Default | Description | | --------- | -------- | --------- | ----------------------------------------------- | | baseURL | string | '' | Origin to prefix. Empty → relative URLs. | | cdnPath | string | '/cdn/' | Path that routes to the edge. '' disables it. |

How it works

<NuxtImg src="/uploads/a.jpg" width="800" format="webp" />
        │  getImage(src, { modifiers, ...options })
        ▼
@revenexx/storage-nuxt-image   →   /cdn/uploads/a.jpg?w=800&fm=webp
        │  browser requests it from your domain
        ▼
my-shop.com → revenexx edge → (signed, server-side) → optimized image (cached)

Troubleshooting

  • Image isn't transformed (original served). The path must resolve to an asset on the CDN, and at least one modifier must be present. Check the generated <img src> in devtools.
  • A modifier seems ignored / errors. Some transforms require a CDN tier or source type (e.g. page needs a multi-page source). Verify against docs/transformations.md. Unknown params are ignored by the CDN.
  • URLs point at the wrong host. Set baseURL (or leave it empty for relative URLs) — see Bring your own domain.
  • Provider not found. Ensure @nuxt/image is installed and the provider is registered under image.providers with provider: '@revenexx/storage-nuxt-image'.

Requirements

  • Nuxt 3/4 with @nuxt/image v1 or v2 (peer; optional for standalone builder use).
  • Node ≥ 18.

Releasing

Fully automated with Changesets + npm OIDC trusted publishingno tokens. To ship a change:

  1. pnpm changeset — pick a bump (patch/minor/major) and describe it; commit the generated file.
  2. On push to main, the Release workflow opens a "Version Packages" PR.
  3. Merge it → the workflow bumps the version, updates the changelog, and publishes to npm with provenance.

License

MIT © revenexx