AI Virtual Try-On
The cv-tryon addon lets customers see their customized product on AI-generated model photos. It uses FASHN.ai under the hood to dress a model with the current canvas design, and optionally generate short videos from the results.
How It Works
- The user opens the try-on drawer (via action button or programmatically).
- They select a product view and optionally pick a model photo.
- The component captures the canvas as a PNG and sends it to your server-side proxy endpoint.
- Your server forwards the request to FASHN.ai, polls for completion, and returns the result images.
- The user can enlarge results in a lightbox, download them, or generate a short video.
Quick Start
Place the <cv-tryon> element anywhere on the page. Configure models and endpoints via ChamevoOptions.tryOn:
<cv-customizer id="customizer"></cv-customizer>
<cv-tryon id="tryon"></cv-tryon>
<script type="module">
import { createCustomizer } from '@chamevo/customizer';
const customizer = createCustomizer('#customizer', {
tryOn: {
endpoint: '/api/fashn/product-to-model',
videoEndpoint: '/api/fashn/image-to-video',
models: [
{
id: 'female-1',
label: 'Sofia',
subtitle: 'Slim, casual',
thumb: '/images/models/sofia-thumb.jpg',
full: '/images/models/sofia-full.jpg',
},
{
id: 'male-1',
label: 'Marcus',
subtitle: 'Athletic, smart',
thumb: '/images/models/marcus-thumb.jpg',
full: '/images/models/marcus-full.jpg',
},
],
allowUpload: true,
},
});
customizer.addEventListener('cvReady', (e) => {
document.getElementById('tryon').chamevo = e.detail.chamevo;
});
</script>
If no models are configured, only the upload card and the "Skip" option are available.
Adding the Action Button
Use the built-in ai-try-on action ID to add a trigger button to the action bar. It renders as an animated gradient widget button:
customizer.options = {
actions: [
{ items: ['undo', 'redo'], align: 'start' },
{ items: ['ai-try-on'], align: 'end' },
],
};
The ai-try-on action is a widget action — it renders the <cv-tryon-button> component inline and never collapses into a dropdown.
You can also use <cv-tryon-button> as a standalone element anywhere on your page:
<cv-tryon-button label="Try It On"></cv-tryon-button>
cv-tryon-button Properties
| Property | Type | Default | Description |
|---|---|---|---|
label | string | 'AI Try On' | Button label text. |
size | 'sm' | 'md' | 'md' | Size variant. 'sm' is used automatically in the actions bar. |
Server-Side Proxy
The component does not call FASHN.ai directly from the browser. You must provide two server endpoints that proxy requests to the FASHN.ai API:
- Receive the request from the component.
- Forward it to FASHN with your API key (submit job → poll status).
- Download the output files to your server.
- Return local URLs to the client.
This keeps your FASHN API key secure and avoids CORS issues.
POST /api/fashn/product-to-model
Try-on image generation. The component sends this request when the user clicks Generate Try-On.
Request Body
{
"product_image": "data:image/png;base64,iVBORw0KGgo…",
"model_image": "https://example.com/model-photo.jpg",
"prompt": "studio lighting, white background"
}
| Field | Type | Required | Description |
|---|---|---|---|
product_image | string | Yes | Base64 data URI of the canvas view (PNG). |
model_image | string | No | URL or base64 of the model photo. If omitted, FASHN generates a model automatically. |
prompt | string | No | Style prompt for the generation (e.g. "outdoor photoshoot"). |
Your server may also forward these optional FASHN parameters if provided:
| Field | Type | Description |
|---|---|---|
image_prompt | string | Image-based style prompt. |
face_reference | string | URL or base64 of a face reference image. |
face_reference_mode | 'match_reference' | 'match_base' | How to use the face reference. |
aspect_ratio | string | Output aspect ratio (e.g. "3:4"). |
resolution | '1k' | '4k' | Output resolution. |
background_reference | string | URL or base64 of a background reference. |
seed | number | Random seed for reproducibility. |
num_images | number | Number of images to generate (default 1). |
output_format | 'png' | 'jpeg' | Output image format. |
200 Response
{
"images": [
"/uploads/2026/02/fashn_1740700000_0.png",
"/uploads/2026/02/fashn_1740700000_1.png"
]
}
| Field | Type | Description |
|---|---|---|
images | string[] | Array of public URL paths to the generated images on your server. Must be accessible by the browser. |
The component renders each URL as a result card with enlarge, download, and video-generation actions.
Error Response
On failure, return a non-200 status code. The component reads the response body as text and displays it as an error message:
HTTP 500
{"error": "FASHN job failed: Invalid product image"}
POST /api/fashn/image-to-video
Video generation from a try-on result image. The component sends this request when the user clicks the play icon on a result card.
Request Body
{
"image": "/uploads/2026/02/fashn_1740700000_0.png",
"resolution": "720p",
"duration": 5
}
| Field | Type | Required | Description |
|---|---|---|---|
image | string | Yes | URL path of the source image (from the try-on images response). Can be a local path — your server must resolve it to a file or convert to base64 before forwarding to FASHN. |
resolution | string | Yes | Video resolution. The component sends "720p". |
duration | number | Yes | Video duration in seconds. The component sends 5. |
prompt | string | No | Motion/style prompt for the video. |
Your server should detect local paths (e.g. /uploads/…), read the file from disk, and convert it to a base64 data URI before sending to FASHN — the FASHN API does not accept local paths.
200 Response
{
"videos": [
"/uploads/2026/02/fashn_video_1740700100_0.mp4"
]
}
| Field | Type | Description |
|---|---|---|
videos | string[] | Array of public URL paths to the generated .mp4 video files on your server. |
The component renders each video with inline playback controls, a download link, and an enlarge button (opens in the lightbox).
Error Response
Same pattern as the try-on endpoint — return a non-200 status with an error message in the body.
Configuration (ChamevoOptions.tryOn)
The try-on feature is configured via the tryOn property in ChamevoOptions. This is the recommended way to set models, endpoints, and behavior:
interface TryOnConfig {
/** API endpoint for try-on image generation. @default '/api/fashn/product-to-model' */
endpoint?: string;
/** API endpoint for image-to-video generation. @default '/api/fashn/image-to-video' */
videoEndpoint?: string;
/** Model images available for selection. @default [] */
models?: TryOnModel[];
/** Allow users to upload their own photo as model. @default true */
allowUpload?: boolean;
}
Model Data Format (TryOnModel)
interface TryOnModel {
id: string; // Unique identifier
label: string; // Display name shown below the thumbnail
subtitle?: string; // Secondary text (e.g. "Slim, casual")
thumb: string; // Thumbnail URL (~300×400 recommended)
full: string; // Full-resolution URL sent to the API (~800×1067)
}
When no models are configured, only the upload card and the "Skip" option are shown. The user can skip model selection entirely — the FASHN API will generate its own model automatically (costs 1 credit instead of 2).
Example
createCustomizer('#customizer', {
tryOn: {
models: [
{ id: 'f1', label: 'Sofia', subtitle: 'Slim, casual', thumb: '/models/sofia-sm.jpg', full: '/models/sofia.jpg' },
{ id: 'm1', label: 'Marcus', subtitle: 'Athletic', thumb: '/models/marcus-sm.jpg', full: '/models/marcus.jpg' },
],
allowUpload: false, // disable user photo uploads
},
});
Runtime Updates
You can update the try-on config at runtime via setOptions:
chamevo.setOptions({
tryOn: {
models: [...newModels],
},
});
Component Reference (cv-tryon)
Properties
| Property | Type | Default | Description |
|---|---|---|---|
chamevo | ChamevoJS | Auto from store | ChamevoJS instance. Falls back to the internal store if not set. |
open | boolean | false | Controls drawer visibility. |
endpoint | string | From options.tryOn | Server endpoint for try-on generation. Overrides the options value. |
videoEndpoint | string | From options.tryOn | Server endpoint for video generation. Overrides the options value. |
models | string | TryOnModel[] | From options.tryOn | Predefined model images. Overrides the options value. Pass a JSON string or array. |
Direct props on the <cv-tryon> element override options.tryOn values. The resolution order is: prop > options.tryOn > default.
Events
| Event | e.detail | Description |
|---|---|---|
cvTryOnOpen | — | Fires when the drawer opens. |
cvTryOnClose | — | Fires when the drawer closes. |
cvTryOnGenerate | { images: string[] } | Fires when generation completes with result image URLs. |
Opening Programmatically
Toggle the drawer from JavaScript:
// Via the component's open prop
document.querySelector('cv-tryon').open = true;
// Or via the action system
document.querySelector('cv-customizer')
.dispatchEvent(new CustomEvent('cv-action-request', {
detail: { action: 'ai-try-on' },
}));
Features
Stepped Wizard
The try-on flow is a 4-step wizard: Design → Model → Style → Result. Users can navigate back to previous steps by clicking the stepper dots.
Skip Model Selection
Users can skip the model step by clicking "Skip — let AI choose the model". When skipped, no model_image is sent to the FASHN API, which generates its own model based on the garment image. This is useful for back/side views where the model orientation matters.
Image Lightbox
Click the enlarge icon on any result image to open it in a fullscreen lightbox overlay. Press Escape or click the background to close.
Image-to-Video
Click the video icon on a result image to generate a short video (720p, 5 seconds) using FASHN's image-to-video API. The video appears below the image results with playback controls and download/enlarge options.
Result History
Generated images and videos are stored in the browser's localStorage (up to 10 most recent entries). A horizontal "Recent" strip appears between the stepper and the wizard body, showing thumbnails of past results. Click a thumbnail to open it in the lightbox. Hover to reveal the delete button.
History persists across drawer open/close and page refreshes.
Session Persistence
Closing and reopening the drawer preserves the current generation state — results, loading spinners, and video output remain visible without needing to refresh the page.
i18n
The action button label is translatable via the actions.ai_try_on key:
customizer.options = {
langJSON: {
actions: {
ai_try_on: 'Virtuelles Anprobieren',
},
},
};
See i18n for full translation setup.
Next Steps
- Actions — Configure action bars and the
ai-try-onwidget - Background Removal & Upscale — AI image processing features
- 3D Preview — Another visual addon for product previewing
- Events — Listen for
cvTryOnGenerateand other events