@revenexx/storage-nuxt-image

Nuxt Image provider for the revenexx Storage CDN. Build optimized, on-the-fly image URLs against your own domain's /cdn/ endpoint.
663
Install
npm install @revenexx/storage-nuxt-image
Latest Version:0.1.0
Vue:3
License:MIT
Last Updated:Oct 20, 2026
Links: GitHub  ·  npm

@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 0–100
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 } }"
/>

position ∈ ce 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 publishing — no 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

Related Packages

@scayle/nuxt-image-provider

An image provider to handle SCAYLE-specific modifiers

99,945
@teamnovu/nuxt-image-module

Responsive image module for Nuxt 4 with provider-agnostic focal-point handling a...

1,124
@rhapsodic/nuxt-vuewer

Nuxt module for viewing images

4,632 0
@rezo-zero/intervention-request-provider

InterventionRequest provider for @nuxt/image

4,420 3
@macrulez/vue-image-kit

Vue 3 image optimization — lazy loading, WebP/AVIF, srcset, Blurhash/LQIP placeh...

4,157 0

Version History

Version Released License
0.1.0 MIT