@souldi/try-on
v0.1.89
Published
Embeddable virtual try-on widget for e-commerce
Downloads
4,466
Maintainers
Readme
@souldi/try-on
Drop a virtual try-on button into any e-commerce site in under 5 minutes.
Let your customers see how clothes look on them — powered by AI, embedded with a single script tag. No iframes, no redirects, no heavy dependencies.
Quick Start
1. Install
npm install @souldi/try-onOr load directly via CDN:
<script src="https://unpkg.com/@souldi/try-on/dist/widget.umd.js"></script>2. Initialize
<script>
VirtualTryOn.init({
tenantApiKey: 'your_publishable_api_key',
});
</script>3. Add a Try-On Button
<div id="try-on-jacket"></div>
<script>
VirtualTryOn.createButton({
containerId: 'try-on-jacket',
garmentUrl: 'https://your-cdn.com/images/jacket.png',
targetImageId: 'product-image', // optional: auto-swaps this <img> with the result
});
</script>That's it. Your customers can now try on clothes with AI.
How It Works
- Customer clicks the Try On button
- First-time users verify their email (magic link OTP — no passwords)
- They upload a photo of themselves
- AI generates a realistic try-on image in seconds
- The result appears directly on your product page
Returning users skip straight to step 4 — their session and photo are remembered.
Configuration
init(options)
Call once per page load to configure the widget.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| tenantApiKey | string | Yes | Your publishable API key (from your Souldi dashboard) |
| theme | object | No | Customize the widget appearance (see Theming) |
| onGenerationStart | function(info) | No | Called when AI generation begins |
| onGenerationSuccess | function(resultUrl, info) | No | Called with the result image URL on success |
| onError | function(message, info) | No | Called when something goes wrong |
| onLogout | function | No | Called when the user's session ends — by logout, or by a token the backend no longer honours |
| onAuthPrompt | function | No | Called just before the widget takes the screen to ask the user to sign in |
The info argument
Callbacks about a specific try-on receive a trailing info object:
| Field | Type | Present on | Description |
|-------|------|-----------|-------------|
| buttonId | string | all three | The containerId of the button this callback is about |
| operation | 'generate' \| 'refine' | onError | Which operation failed |
buttonId matters as soon as a page has more than one try-on button: without it
you cannot tell which button's job just finished, and a result can only be
placed by guessing. Read it whenever you render results yourself.
info is passed after the existing arguments, so onGenerationSuccess(url)
and onError(message) keep working unchanged.
Note that onError with operation: 'refine' also covers a refine the widget
declined — only the most recently generated result can be refined, so a
request against an older one is reported here rather than silently dropped.
Present it wherever you collected the instruction; the previous result is
untouched either way.
onLogout deliberately carries no buttonId — a session ends for the whole
page, and every result surface on it must be torn down. If you render results
yourself, this is where you drop them: the result URL is signed, user-specific,
and must not outlive the session.
onAuthPrompt fires before the widget's own sign-in card opens. Use it to move
anything of yours that would cover it (a modal, a lightbox) out of the way. It
says nothing about whether the previous session ended — that is onLogout.
createButton(options)
Add a try-on button for a specific garment. Call once per product on the page.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| containerId | string | Yes | ID of the DOM element where the button will render |
| garmentUrl | string | Yes | Public URL of the garment image |
| internalId | string | No | Your internal/vendor id for this garment; correlated server-side |
| targetImageId | string | No | ID of an <img> element to auto-swap with the try-on result |
Theming
The widget ships with dark and light themes and supports deep customization to match your store's brand.
Theme Modes
VirtualTryOn.init({
tenantApiKey: 'your_key',
theme: {
mode: 'light', // 'dark' (default) or 'light'
},
});Custom Brand Colors
Override individual properties to match your brand:
VirtualTryOn.init({
tenantApiKey: 'your_key',
theme: {
mode: 'dark',
accentColor: '#7C3AED', // Primary button & accent color
accentTextColor: '#FFFFFF', // Text color on accent buttons
borderRadius: '8px', // Border radius for cards & modals
fontFamily: '"Inter", sans-serif',
headingFontFamily: '"Playfair Display", serif',
buttonOutlineColor: '#7C3AED', // Outline on the split button
},
});Available Theme Options
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| mode | 'dark' \| 'light' | 'dark' | Base color palette |
| accentColor | CSS color | #adcfab (dark) / #4d7c4b (light) | Primary action color |
| accentTextColor | CSS color | #193620 (dark) / #ffffff (light) | Text on accent buttons |
| borderRadius | CSS value | 12px | Corner rounding for cards and modals |
| fontFamily | CSS font stack | 'Manrope', system-ui, sans-serif | Body text font |
| headingFontFamily | CSS font stack | 'Newsreader', serif | Heading font |
| buttonOutlineColor | CSS color | transparent | Border color on the try-on button |
All UI is rendered inside a Shadow DOM, so your site's CSS will never leak into the widget and the widget will never break your styles.
Full Example
<!DOCTYPE html>
<html>
<head>
<title>My Store</title>
<script src="https://unpkg.com/@souldi/try-on/dist/widget.umd.js"></script>
</head>
<body>
<div class="product-card">
<img id="product-image" src="/images/jacket.jpg" alt="Jacket" />
<h2>Classic Denim Jacket</h2>
<p>$89.00</p>
<!-- The try-on button renders here -->
<div id="try-on-btn"></div>
</div>
<script>
VirtualTryOn.init({
tenantApiKey: 'pk_live_abc123',
theme: { mode: 'light', accentColor: '#2563EB' },
onGenerationSuccess: (url) => {
console.log('Try-on result:', url);
},
onError: (msg) => {
console.error('Try-on error:', msg);
},
});
VirtualTryOn.createButton({
containerId: 'try-on-btn',
garmentUrl: 'https://your-cdn.com/images/jacket-flat.png',
targetImageId: 'product-image',
});
</script>
</body>
</html>Keys & Authentication
| Key | Where to use | Purpose |
|-----|-------------|---------|
| Publishable API Key (tenantApiKey) | In your frontend code | Identifies your store — safe to expose in client-side code |
| Secret API Key | Backend only, never in frontend | Used for server-to-server API calls (manage your account, view usage, etc.) |
Your API keys are available in your Souldi Dashboard. The publishable key is scoped to the domains you whitelist — it cannot be used from unauthorized origins.
Security note: The widget communicates exclusively with your Souldi API endpoint. No third-party services are contacted from the browser. All authentication, file uploads, and AI generation are handled server-side.
Browser Support
Works in all modern browsers:
- Chrome 80+
- Firefox 78+
- Safari 14+
- Edge 80+
License
UNLICENSED - Proprietary software. See your Souldi service agreement for usage terms.
