This is the full developer documentation for nitida # nitida > Hand it raw media. Get back every size, every format, every screen — crisp. Upload that survives a phone Multipart with resume across a reload, IndexedDB-backed, progress per file. A dropped 4G connection resumes where it stopped instead of starting over. Compression in the browser A worker and `OffscreenCanvas` — the main thread never blocks. HEIC decodes natively where the engine can (**136 ms**), and only falls back to WASM where it cannot, so the 341 KB decoder stays unfetched for most users. Video, not just images Poster, transcode, an adaptive HLS ladder, and a cheap proxy built for machine analysis rather than for eyes. Multi-tenant from the first line Keys per tenant, isolation by prefix, and usage you can actually read. Running in production across five tenants. ## Two packages, one idea [Section titled “Two packages, one idea”](#two-packages-one-idea) **`@aquienpz/asset-client`** builds URLs. No network, no key, nothing to configure beyond a tenant id. If all your app does is *render* media, this is the only thing you need. **`@aquienpz/sdk`** adds the write half — upload, compress, register, poll — and re-exports every URL builder, so you never import both for the same job. ## The reference is generated from the types [Section titled “The reference is generated from the types”](#the-reference-is-generated-from-the-types) Every page under **API reference** is produced from the source on each build. Nothing there is transcribed by hand, which is the only way a reference stays true after a rename. The same content is published at [`/llms.txt`](/llms.txt) and [`/llms-full.txt`](/llms-full.txt) so an agent can read the whole surface in one fetch. # Exclude ```ts type Exclude = T extends U ? never : T; ``` Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1618 Exclude from T those types that are assignable to U ## Type Parameters [Section titled “Type Parameters”](#type-parameters) | Type Parameter | | -------------- | | `T` | | `U` | # Omit ```ts type Omit = Pick>; ``` Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1628 Construct a type with the properties of T except for those in type K. ## Type Parameters [Section titled “Type Parameters”](#type-parameters) | Type Parameter | | ------------------------- | | `T` | | `K` *extends* keyof `any` | # computeVariantDimensions ```ts function computeVariantDimensions(asset, preset): | { height: number; width: number; } | null; ``` Defined in: packages/asset-client/src/index.ts:353 Compute the dimensions a variant would have given the source asset’s width/height and the variant’s bounding box. For thumbnails (square smart-crop) the result is always 256×256; for the other presets, scales the max side to the box dimension and the other side proportionally. ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | --------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `asset` | [`Pick`](/api/sdk/src/react/-internal-/type-aliases/pick/)<[`AssetDTO`](/api/asset-client/src/type-aliases/assetdto/), `"w"` \| `"h"`> | | `preset` | [`VariantPreset`](/api/asset-client/src/type-aliases/variantpreset/) | ## Returns [Section titled “Returns”](#returns) \| { `height`: `number`; `width`: `number`; } | `null` # configureSlotResolver ```ts function configureSlotResolver(opts): void; ``` Defined in: packages/asset-client/src/slots.ts:70 Configure the resolver process-wide. Call once at boot from your storefront layout / server entry / worker init. configureSlotResolver({ endpoint: process.env.AQUIENPZ\_URL, apiKey: process.env.ASSET\_MANAGER\_RUNTIME\_KEY, tenantCode: “realtyone-cr”, }); ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | ------------------ | ------------------------------------------------------------------------ | | `opts` | { `apiKey?`: `string`; `endpoint?`: `string`; `tenantCode?`: `string`; } | | `opts.apiKey?` | `string` | | `opts.endpoint?` | `string` | | `opts.tenantCode?` | `string` | ## Returns [Section titled “Returns”](#returns) `void` # extractAssetSha ```ts function extractAssetSha(url): string | null; ``` Defined in: packages/asset-client/src/transform.ts:160 Extract the 16-hex short sha from an aquienpz CDN URL, regardless of shape: * tenant-prefixed variant: `https://8ok.uk/4/v/-.` * legacy variant: `https://8ok.uk/-.` * on-the-fly transform: `https://8ok.uk/t//.` * streaming HLS: `https://8ok.uk/t/format=hls/.m3u8` Returns `null` for non-aquienpz URLs (pexels, googleusercontent, raw uploaded URLs to other CDNs) so call sites can fall back to the URL with a plain `` instead of generating a broken transform URL. Useful when a value reaches the component as a pre-built URL string (legacy data, site-config JSON, third-party feeds) but you want to drop in `getTransformSrcSet` for the responsive ladder if it happens to be an aquienpz asset. ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | --------- | --------------------------------- | | `url` | `string` \| `null` \| `undefined` | ## Returns [Section titled “Returns”](#returns) `string` | `null` # getAmbientGradient ```ts function getAmbientGradient(palette, opts?): string | undefined; ``` Defined in: packages/asset-client/src/palette.ts:63 Build a CSS linear-gradient from the palette. Useful for hero / detail backgrounds. ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | ------------- | ---------------------------------------------------------------------------------------------- | | `palette` | \| [`AssetPalette`](/api/asset-client/src/type-aliases/assetpalette/) \| `null` \| `undefined` | | `opts` | { `angle?`: `string`; `from?`: keyof AssetPalette; `to?`: keyof AssetPalette; } | | `opts.angle?` | `string` | | `opts.from?` | keyof AssetPalette | | `opts.to?` | keyof AssetPalette | ## Returns [Section titled “Returns”](#returns) `string` | `undefined` # getAssetDimensions ```ts function getAssetDimensions(asset): | { height: number; width: number; } | null; ``` Defined in: packages/asset-client/src/index.ts:369 Source dimensions, for aspect-ratio sizing. ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | --------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `asset` | [`Pick`](/api/sdk/src/react/-internal-/type-aliases/pick/)<[`AssetDTO`](/api/asset-client/src/type-aliases/assetdto/), `"w"` \| `"h"`> | ## Returns [Section titled “Returns”](#returns) \| { `height`: `number`; `width`: `number`; } | `null` # getAssetSrcSet ```ts function getAssetSrcSet(asset): string; ``` Defined in: packages/asset-client/src/index.ts:337 ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `asset` | [`Pick`](/api/sdk/src/react/-internal-/type-aliases/pick/)<[`AssetDTO`](/api/asset-client/src/type-aliases/assetdto/), `"sha"` \| `"presets"`> | ## Returns [Section titled “Returns”](#returns) `string` # getAssetUrl ```ts function getAssetUrl(asset, preset): string; ``` Defined in: packages/asset-client/src/index.ts:290 Build the public CDN URL for a specific variant of an asset. The variant may not actually exist (regenerate may not have run, or video has no `aiproxy`); call `hasPreset()` first or expect a 404. Pass the asset’s `mime` (present on the full `AssetDTO`) so the `original` preset resolves to the correct extension; without it the original falls back to the `"bin"` sentinel. ## Parameters [Section titled “Parameters”](#parameters) | Parameter | Type | | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `asset` | [`Pick`](/api/sdk/src/react/-internal-/type-aliases/pick/)<[`AssetDTO`](/api/asset-client/src/type-aliases/assetdto/), `"sha"`> & { `mime?`: `string`; } | | `preset` | [`VariantPreset`](/api/asset-client/src/type-aliases/variantpreset/) | ## Returns [Section titled “Returns”](#returns) `string` ## Examples [Section titled “Examples”](#examples) **Video — the tenant segment is base36, so let this build the path** ```ts import { getAssetUrl, setTenantId } from "@aquienpz/asset-client"; setTenantId(12); // 12 → "c"; a decimal "/12/v/" 404s getAssetUrl({ sha }, "video"); // → https://8ok.uk/c/v/-v.mp4 getAssetUrl({ sha }, "poster"); // → https://8ok.uk/c/v/-p.webp ``` **The \`original\`, which needs the mime — and still deserves a HEAD** ```ts getAssetUrl({ sha }, "original"); // → …-o.bin ❌ 404, always getAssetUrl({ sha, mime }, "original"); // → …-o.webp ✓ // ⚠️ The stored extension comes from the UPLOADED FILENAME, not the mime: // "image/jpeg" builds "-o.jpeg" while a camera's ".jpg" was stored as "-o.jpg". // When the URL must be right, verify it: const res = await fetch(url, { method: "HEAD" }); ``` **Check before you link** ```ts import { getAssetUrl, hasPreset } from "@aquienpz/asset-client"; const url = hasPreset(asset, "thumb") ? getAssetUrl(asset, "thumb") : null; ``` # getCdnBase ```ts function getCdnBase(): string; ``` Defined in: packages/asset-client/src/index.ts:192 ## Returns [Section titled “Returns”](#returns) `string` # getHlsStreamingUrl ```ts function getHlsStreamingUrl(asset, opts?): string; ``` Defined in: packages/asset-client/src/transform.ts:284 Build an HLS streaming URL for a VIDEO asset (Phase 5). Returns the master.m3u8 entry point — HLS-aware players (Video.js’s @videojs/http-streaming, hls.js, native iOS Safari) follow it to fetch the variant playlist + segments at the appropriate bitrate for the connection. ⚠️ A master.m3u8 is NOT a video file. Assigning it to `