- 12. Mai 2026
#lessonlearned – Custom Nuxt Image Provider: AdmiralCloud als zweite Bildquelle
Nicht alle Bilder in einer Website stammen aus derselben Quelle. In vielen Projekten kommen redaktionelle Bilder aus dem CMS, während andere Medien über ein Digital-Asset-Management-System bereitgestellt werden. Genau diese Situation hatten wir auch in unserem Projekt: Storyblok lieferte die redaktionellen Bilder, AdmiralCloud stellte hochauflösende Medien aus dem DAM bereit. In diesem Lesson Learned zeigen wir, wie wir dafür einen eigenen Nuxt Image Provider entwickelt haben, um beide Quellen einheitlich in der Anwendung zu nutzen.

Warum eine zweite Bildquelle zur Herausforderung wird
Wenn Bilder aus unterschiedlichen Systemen kommen, unterscheiden sich meist nicht nur die URLs, sondern auch die Art, wie Bildgrößen, Zuschnitte und Formate gesteuert werden.
Während Storyblok bereits gut in das Nuxt-Image-Ökosystem integriert werden kann, brachte AdmiralCloud eine eigene URL-Struktur mit Transformationsparametern mit. Darin wurden zum Beispiel folgende Informationen übergeben:
Modus des Bildzuschnitts
Breite und Höhe
Skalierung
Koordinaten für einen definierten Bildausschnitt
Ohne eine zentrale Lösung hätte diese Logik an vielen Stellen in Templates und Komponenten manuell umgesetzt werden müssen. Das wäre nicht nur fehleranfällig, sondern auch schwer wartbar geworden.
Unser Ansatz: ein eigener Image Provider für Nuxt
Damit sich Bilder aus AdmiralCloud genauso einfach einbinden lassen wie Bilder aus Storyblok, haben wir einen eigenen Provider mit defineProvider erstellt.
Ein vereinfachter Ausschnitt sieht so aus:
// app/providers/admiralCloud.ts
import { joinURL } from 'ufo'
import { defineProvider } from '@nuxt/image/runtime'
export default defineProvider({
getImage: (src, { modifiers = {}, baseURL } = {}) => {
const aspectRatioWidth = modifiers.aspectRatioWidth ?? 3
const aspectRatioHeight = modifiers.aspectRatioHeight ?? 2
const width = modifiers.width ?? 100
const height =
modifiers.height ??
Math.ceil(width / (aspectRatioWidth / aspectRatioHeight))
const mode = modifiers.mode ?? 'autocrop'
const scale = modifiers.scale ?? '1'
const coordinates =
mode === 'autocrop_aoi'
? `${modifiers.coordinates.left},${modifiers.coordinates.top},${modifiers.coordinates.width},${modifiers.coordinates.height}`
: ''
return {
url: joinURL(baseURL, src, 'image', mode, `${width}`, `${height}`, `${scale}`, coordinates)
}
}
})ts
Der Provider übernimmt dabei die Aufgabe, aus einer einfachen Eingabe die korrekte AdmiralCloud-URL zu erzeugen. So bleibt die eigentliche Bildlogik zentral gekapselt.
Bildquellen im Template einheitlich verwenden
Der große Vorteil dieses Ansatzes war für uns, dass im Template kaum noch unterschieden werden muss, aus welchem System ein Bild stammt. Statt verschiedene <img>-Logiken zu pflegen, kann weiterhin mit <NuxtImg> gearbeitet werden.
Zum Beispiel so:
<!-- Storyblok-Bild -->
<NuxtImg
provider="storyblok"
:src="storyblokAsset.filename"
:width="800"
loading="lazy"
/>
<!-- AdmiralCloud-Bild -->
<NuxtImg
provider="admiralCloud"
:src="asset.admiralCloudImageUuid"
:width="800"
:modifiers="{
aspectRatioWidth: 16,
aspectRatioHeight: 9,
mode: 'autocrop_aoi',
coordinates: asset.admiralCloudImageSettings?.coordinates
}"
loading="lazy"
/>Vue
m Template wird also nur noch über den provider festgelegt, welche Bildquelle verwendet werden soll. Die Grundlogik bleibt gleich. Das hat die Integration für uns deutlich vereinfacht.
Dynamische Bildzuschnitte zentral steuern
Ein wichtiger Bestandteil bei AdmiralCloud war die Möglichkeit, Bilder nicht nur automatisch zuzuschneiden, sondern auch mit einem definierten Fokusbereich zu arbeiten. Dafür wurden Koordinaten übergeben, die nur in bestimmten Modi relevant sind.
Gerade bei großen Bildbühnen, Teasern oder redaktionellen Inhalten war das hilfreich, weil wichtige Bildbereiche so auch in unterschiedlichen Formaten sichtbar bleiben konnten.
Die dafür notwendige URL-Logik liegt nun vollständig im Provider und nicht mehr verstreut in einzelnen Komponenten.
Responsive Hintergrundbilder ebenfalls berücksichtigen
Neben klassischen Inhaltselementen mussten bei uns auch Hintergrundbilder unterstützt werden, zum Beispiel für Hero-Bereiche oder größere Teaserflächen.
Dafür haben wir eine zusätzliche Hüllkomponente aufgebaut, die je nach Bildschirmgröße unterschiedliche Bild-URLs über CSS-Variablen einbindet.
Ein vereinfachter Ausschnitt:
onMounted(() => {
const styleElement = document.createElement('style')
styleElement.textContent = `
:root { --sb-ac-bg-image-${uid}: url('${images[0]}'); }
@media (min-width: 640px) {
:root { --sb-ac-bg-image-${uid}: url('${images[1]}'); }
}
@media (min-width: 1024px) {
:root { --sb-ac-bg-image-${uid}: url('${images[2]}'); }
}
@media (min-width: 1440px) {
:root { --sb-ac-bg-image-${uid}: url('${images[3]}'); }
}
`
document.head.appendChild(styleElement)
})ts
So kann pro Breakpoint eine eigene Bildgröße ausgeliefert werden. Das verbessert nicht nur die Darstellung, sondern hilft auch dabei, unnötig große Dateien auf kleineren Geräten zu vermeiden.
Die redaktionelle Pflege gleich mitdenken
Ein technischer Bildprovider ist nur dann wirklich hilfreich, wenn die dazugehörigen Einstellungen auch redaktionell gut gepflegt werden können. Deshalb wurden die Bildeinstellungen bei uns direkt in Storyblok über ein eigenes Feld-Plugin abgebildet.
Dort können Redakteurinnen und Redakteure zum Beispiel Zuschnitt, Fokusbereich und Seitenverhältnis festlegen und die Wirkung direkt in einer Vorschau prüfen. Das war für uns ein wichtiger Schritt, damit die technische Lösung nicht nur im Code funktioniert, sondern auch im redaktionellen Alltag gut nutzbar bleibt.
Was sich für uns bewährt hat
Im Projekt hat sich vor allem gezeigt, dass eine zusätzliche Bildquelle nicht automatisch zu mehr Komplexität im Template führen muss.
Einheitliche Nutzung über <NuxtImg>
Der eigene Provider sorgt dafür, dass Bilder aus unterschiedlichen Systemen mit derselben Komponente eingebunden werden können. Das macht Templates übersichtlicher und wiederverwendbarer.
Komplexe URL-Logik zentral kapseln
Transformationen, Zuschnitte und Koordinaten müssen nicht mehr an vielen Stellen manuell zusammengesetzt werden. Die Logik liegt an genau einer Stelle.
Redaktionelle Anforderungen früh mitdenken
Gerade bei Bildzuschnitten ist es wichtig, dass nicht nur Entwicklerinnen und Entwickler die Logik verstehen, sondern auch die Redaktion die Einstellungen sinnvoll pflegen kann.
Unser Fazit
Unser wichtigstes Learning war, dass sich zusätzliche Bildquellen sehr gut in eine bestehende Nuxt-Anwendung integrieren lassen, wenn die technische Komplexität in einen eigenen Provider ausgelagert wird.
Mit einem Custom Nuxt Image Provider für AdmiralCloud konnten wir dieselbe Bildkomponente für unterschiedliche Quellen verwenden, ohne im Template Sonderlogik aufzubauen. Das hat die Wartbarkeit verbessert, die Integration sauber gehalten und gleichzeitig genug Flexibilität für redaktionelle Bildbearbeitung geschaffen.