Frameworks
Each loader is a thin adapter over @truocloud/img — the
same URL builder, so every framework emits byte-identical URLs and shares CDN
cache entries.
Next.js
Section titled “Next.js”npm install @truocloud/img-nextmodule.exports = { images: { loader: "custom", loaderFile: "./node_modules/@truocloud/img-next/loader.js", deviceSizes: [640, 828, 1200, 1600, 2048], },};NEXT_PUBLIC_TRUO_IMG_PID=acmeThat is the whole setup — <Image> works unchanged.
deviceSizes is trimmed from the default eight for the reason described in
the ladder.
Next only walks deviceSizes when the image has a sizes prop. Without one it
emits a 1x/2x density pair around the declared width — which is fine, but it is
not the responsive ladder, and it surprises people.
npm install @truocloud/img-nuxtexport default defineNuxtConfig({ modules: ["@nuxt/image"], image: { providers: { truocloud: { provider: "@truocloud/img-nuxt", options: { pid: "acme" } }, }, provider: "truocloud", screens: { xs: 640, sm: 828, md: 1200, lg: 1600, xl: 2048 }, },});<NuxtImg src="/uploads/photo.jpg" width="800" format="auto" />Angular
Section titled “Angular”npm install @truocloud/img-angularimport { provideTruoImageLoader } from "@truocloud/img-angular";
bootstrapApplication(AppComponent, { providers: [provideTruoImageLoader("https://img.truo.cloud/i/acme")],});<img ngSrc="uploads/photo.jpg" width="800" height="600" priority />The signature mirrors Angular’s own provideImageKitLoader, so swapping
providers is a one-line change. Anything the directive does not model goes
through loaderParams:
<img ngSrc="hero.jpg" width="1200" height="600" [loaderParams]="{ transform: { fit: 'cover', gravity: 'attention' } }" />React, Vue, Svelte, Solid, Qwik, Astro
Section titled “React, Vue, Svelte, Solid, Qwik, Astro”Through unpic, which detects img.truo.cloud and
transforms the URL for you:
import { Image } from "@unpic/react";
<Image src="https://img.truo.cloud/i/acme/uploads/photo.jpg" layout="constrained" width={800} height={600} />A custom domain does not autodetect — /i/ is too generic a path to claim
globally — so pass cdn="truocloud" explicitly if you use one.
Pinning the format
Section titled “Pinning the format”Every loader defaults to format: "auto". If your images sit behind a
third-party CDN that ignores Vary on images, pin it instead:
createTruoLoader({ pid: "acme", format: "webp" }) // Next{ options: { pid: "acme", format: "webp" } } // NuxtprovideTruoImageLoader(endpoint, { format: "webp" }) // AngularThe reasoning is in format negotiation.