@motioness/proxy-client

The official client SDK. Three exports for three layers of integration. Most apps should reach for the React component first — it ships with the full effect set (hover, lazy, callbacks, SSR). Drop down to the web component or buildProxyUrl() only when you need to.

  • <MotionessImg> — React binding. Hover effects, lazy loading, signed-URL props, SSR-safe. Recommended.
  • <motioness-img> — web component (custom element). Same effects as the React binding without React. Drops into any HTML page.
  • buildProxyUrl() — pure-function URL builder. No DOM, no React. For OG cards, RSS, server-side rendering of <video> directly.

Install

bash
npm install @motioness/proxy-client

Peer deps: react >= 18 and react-dom >= 18 (only for the React entry).

buildProxyUrl(opts)

The lowest-level entry. Returns { mp4, jpg }:

ts
import { buildProxyUrl } from '@motioness/proxy-client';const urls = buildProxyUrl({ origin: 'https://motioness.com', projectKey: 'pk_abc', src: 'https://cdn.acme.com/hero.png', motion: 'medium', durSeconds: 4,});urls.mp4; // → https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4?motion=medium&dur=4urls.jpg; // → https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.jpg

Options

OptionTypeDefaultDescription
originstringrequiredUsually https://motioness.com
projectKeystringrequiredYour pk_…
srcstringrequiredFull source URL with scheme
motion'subtle' | 'medium' | 'kinetic'project defaultMotion intensity
durSecondsnumberproject defaultOutput length, clamped 2-8
mode'loop' | 'animate-in' | 'animate-on-hover'project defaultPlayback shape
promptstringOverride the brand-aware vision prompt (≤500 chars)
seednumberDeterministic seed
aspect'1:1' | '16:9' | '9:16' | 'preserve'preserveOutput framing
idempotencyKeystringForce a distinct asset from the same source
waitMsnumber0Long-poll up to N ms before falling back to 202
signaturestringHMAC sig for signed mode
expnumberUnix seconds expiry for signed mode

When signature is set, src is base64url-encoded into the path. Otherwise the scheme is stripped and the source URL is in the path verbatim. See signed URLs.

<motioness-img> web component

Self-contained custom element. Drop it in any HTML page:

html
<script type="module" src="https://motioness.com/proxy-client/element.js"></script><motioness-img project-key="pk_abc" src="https://cdn.acme.com/hero.png" motion="medium" dur-seconds="4" mode="loop" style="width: 100%; max-width: 800px;"/>

Renders <video> with poster, autoplay muted loop playsinline defaults. All the buildProxyUrl options are exposed as kebab-case attributes (project-key, dur-seconds, wait-ms, idempotency-key).

Mode behavior

ModeElement behavior
loopAutoplays, loops.
animate-inPlays once on entry. Sets loop=false.
animate-on-hoverLoads metadata only. Plays on mouseenter, pauses + resets on mouseleave.

Lazy loading

html
<motioness-img loading="lazy" ... />

Defers loading the mp4 until the element scrolls into view (uses IntersectionObserver). Poster jpg loads eagerly.

<MotionessImg> React binding

tsx
import { MotionessImg } from '@motioness/proxy-client/react';export function Hero() { return ( <MotionessImg projectKey="pk_abc" src="https://cdn.acme.com/hero.png" motion="kinetic" mode="loop" durSeconds={5} style={{ width: '100%', borderRadius: 12 }} onReady={(el) => console.log('mp4 loaded', el.duration)} onError={(err) => console.error(err)} /> );}

Same props as the web component (camelCase). Adds onReady and onError callbacks.

The React binding lazily registers the custom element on mount, so you don't need a separate <script> tag.

TypeScript

All entries ship .d.ts. Import types directly:

ts
import type { Motion, Mode, Aspect, ProxyUrls } from '@motioness/proxy-client';import type { BuildUrlOptions } from '@motioness/proxy-client';

Bundle size

EntryMin+gz
@motioness/proxy-client (buildProxyUrl only)~600B
@motioness/proxy-client/element~2KB
@motioness/proxy-client/react~500B + element

No external dependencies (besides peer-deps for the React entry).

Ask a question... ⌘I