@yoot/yoot
TypeScript icon, indicating that this package has built-in type declarations

0.5.1 • Public • Published

@yoot/yoot

One API. Any CDN. Full control.

A lightweight, flexible, CDN-agnostic image URL builder,
designed with SSR and hydration in mind.


TL;DR: Define image transformations once and apply them across any CDN with a single shared API.


 

Installation

Install this core package along with the CDN adapters you need:

npm install @yoot/yoot @yoot/shopify @yoot/cloudinary

 

Table of contents

 

Overview

Build predictable image URLs with a modular, chainable API — designed for reusable, CDN-agnostic image transformations.

Why yoot?

  • 🧠 Predictable API — chainable, composable, no surprises.
  • 🧵 Presets — define once, reuse everywhere.
  • 🔄 Portable — safely serialize and hydrate in any SSR framework.
  • ⚙️ Lightweight — zero runtime deps, framework-agnostic (Astro, SvelteKit, etc.).

Design philosophy

  • 💅 Layout and delivery only — leave visual effects to CSS.
  • 🧱 Small, modular adapters — no global config or hidden logic.
  • 🔌 Pluggable architecture — choose an adapter or write your own.

Adapters

Adapters translate yoot directives into CDN-specific URLs — handling each provider's syntax and features.

See all available adapters

 

Installation

Install this core library, plus CDN adapters needed for your project:

Replace <adapter-name> with the specific adapter you want to use, e.g. shopify, cloudinary.

Node / NPM

npm install @yoot/yoot @yoot/<adapter-name>

Deno / JSR

import {yoot} from 'jsr:@yoot/yoot';
import adapter from 'jsr:@yoot/<adapter-name>';

Browser (importmap)

<script type="importmap">
  {
    "imports": {
      "@yoot/yoot": "https://cdn.jsdelivr.net/npm/@yoot/yoot/+esm",
      "@yoot/<adapter-name>": "https://cdn.jsdelivr.net/npm/@yoot/<adapter-name>/+esm"
    }
  }
</script>
<script type="module">
  import {yoot} from '@yoot/yoot';
  import adapter from '@yoot/<adapter-name>';
</script>

 

Quick start

Step 1. Register adapters

Do this once per runtime (server/client). Use a bootstrap file:

Explicit registration

import {registerAdapters} from '@yoot/yoot';
import adapter1 from '@yoot/<adapter-name-1>';
import adapter2 from '@yoot/<adapter-name-2>';

registerAdapters(adapter1, adapter2);

Auto registration (via side-effect imports)

import '@yoot/<adapter-name>/register';

Step 2. Use the API

Initializing

The yoot function returns a chainable builder. You can optionally initialize it with an image URL or an object.

import {yoot} from '@yoot/yoot';

// Without arguments
const preset = yoot();

// With image URL
const preset = yoot('https://...');

// With an object
const preset = yoot({
  src: 'https://...',
  alt: 'Alt text',
  width: 1024, // Optional: intrinsic width
  height: 1024, // Optional: intrinsic height
});

Single use

const imgPreset = yoot('https://...').width(1024).aspectRatio(1).format('webp');
// Shortform: yoot('https://...').w(1024).ar(1).fm('webp');

const url = imgPreset.url; // Returns generated URL
const attrs = getImgAttrs(imgPreset); // Attributes for `<img>`

Using presets

Create presets
// yoot-presets.ts
import {yoot} from '@yoot/yoot';
import {defineSrcSetBuilder, withImgAttrs, withSourceAttrs} from '@yoot/yoot/jsx'; // Or @yoot/yoot/html

// Hero presets
export const heroPreset = yoot()
  .width(1024)
  .aspectRatio(16 / 9)
  .fit('cover');

export const getHeroImgAttrs = withImgAttrs({loading: 'eager'});

export const getHeroSourceAttrs = withSourceAttrs({
  srcSetBuilder: defineSrcSetBuilder({densities: [1, 2, 3]}),
});

// Thumbnail presets
export const thumbnailPreset = yoot().width(100).aspectRatio(1).fit('cover');

export const getThumbnailImgAttrs = withImgAttrs({loading: 'lazy'});

export const getThumbnailSourceAttrs = withSourceAttrs({
  srcSetBuilder: defineSrcSetBuilder({widths: [100, 200, 300]}),
});

See the API docs for all transformation options.

Use presets
import {thumbnailPreset, getThumbnailImgAttrs, getThumbnailSourceAttrs} from './yoot-presets.ts';

// With a URL string
const thumbnail = thumbnailPreset('https://cdn.example.com/image.jpg');
// Alternatively: thumbnailPreset.src('https://cdn.example.com/image.jpg');

// With an object
const thumbnail = thumbnailPreset({
  src: 'https://cdn.example.com/image.jpg',
  alt: 'Alt text',
  width: 2048, // Intrinsic width
  height: 2048, // Intrinsic height
});

const thumbnailAttrs = getThumbnailImgAttrs(thumbnail);

const webpSourceAttrs = getThumbnailSourceAttrs(thumbnail, {
  type: 'image/webp', // this helper modifies the format to webp
});

const jpegSourceAttrs = getThumbnailSourceAttrs(thumbnail, {
  type: 'image/jpeg', // this helper modifies the format to jpeg
});

Output markup (JSX/HTML)

Note: Use environment-specific imports:

  • Use @yoot/yoot/jsx for React, Preact, Solid
  • Use @yoot/yoot/html for Astro, Svelte, plain HTML
import {yoot} from '@yoot/yoot';
import {defineSrcSetBuilder, getImgAttrs, getSourceAttrs} from '@yoot/yoot/jsx'; // Or '@yoot/yoot/html'

const imgPreset = yoot('https://...').format('png').width(800);

const imgAttrs = getImgAttrs(imgPreset);

// Example demonstrating that format can be overridden via `type`
// and different `srcset` strategies can be used per <source>.

const webpSourceAttrs = getSourceAttrs(imgPreset, {
  type: 'image/webp', // `type` overrides format 'png'
  media: '(min-width: 800px)',
  sizes: '(min-width: 800px) 800px, 100vw',
  srcSetBuilder: defineSrcSetBuilder({widths: [600, 800, 1200]}),
});

const jpegSourceAttrs = getSourceAttrs(imgPreset, {
  type: 'image/jpeg', // `type` overrides format 'png'
  media: '(max-width: 799px)',
  sizes: '(max-width: 799px) 100vw',
  srcSetBuilder: defineSrcSetBuilder({densities: [1, 2, 3]}),
});

return (
  <picture>
    <source {...webpSourceAttrs} />
    <source {...jpegSourceAttrs} />
    <img {...imgAttrs} />
  </picture>
);

 

Resources

 

Demo

Try it live — zero setup:

Open in StackBlitz Open in CodeSandbox

 

Contributing

Found a bug or wish to contribute? Open an issue or send a PR.

 

License

Licensed under the ISC License.

Package Sidebar

Install

npm i @yoot/yoot

Weekly Downloads

265

Version

0.5.1

License

ISC

Unpacked Size

59.6 kB

Total Files

26

Last publish

Collaborators

  • theisel