---
name: Distralabslimited
description: Use when integrating image or video editing capabilities into web applications. Reach for this skill when building editors for React/Next.js apps, configuring theme customization, handling media export, setting up video processing with proper headers, or troubleshooting editor integration issues.
metadata:
    mintlify-proj: distralabslimited
    version: "1.0"
---

# Layermetry Media Editor Skill

## Product summary

`@layermetry/media-editor` is a single npm package that embeds a working image or video editor directly into a web page—not as an iframe or hosted service. The editor runs entirely in the user's browser; editing, preview, and file export all happen client-side. Install with `npm install @layermetry/media-editor` (version 2.0.0, ~1.1 MB gzipped, no ffmpeg, no React peer dependency). Import via `@layermetry/media-editor/react` for React components or `mount()` for framework-free usage. Both editors support full theme customization, templates, brand presets, and AI-powered features routed to custom endpoints. See [Installation](https://layermetry.com/docs/installation.md) for framework-specific setup and [API Reference](https://layermetry.com/docs/api-reference/introduction.md) for complete prop documentation.

## When to use

Reach for this skill when:
- **Building image editors**: Adding filters, text, shapes, layers, crop/resize, gradients, templates, or brand kit to web apps
- **Building video editors**: Multi-track timeline, trim/split, text/sticker overlays, audio tracks, subtitles, speed control, or 4K export
- **Integrating into React/Next.js**: Setting up dynamic imports, configuring webpack, handling SSR constraints, or managing state around editor lifecycle
- **Customizing appearance**: Applying theme overrides for white-labeling, setting brand presets, or controlling UI visibility
- **Handling exports**: Implementing callbacks for image/video output, downloading files, or uploading to servers
- **Setting up video processing**: Configuring CORS headers, copying WASM files, adding URL rewrites, or troubleshooting SharedArrayBuffer errors
- **Debugging integration issues**: Resolving license validation, WASM loading, React version conflicts, or build errors

## Quick reference

### Installation & mounting

| Task | Code |
|------|------|
| Install package | `npm install @layermetry/media-editor` |
| React import | `import { ImageEditor, VideoEditor } from '@layermetry/media-editor/react'` |
| Framework-free mount | `import { mount } from '@layermetry/media-editor'; mount(element, { licenseKey })` |
| Next.js dynamic import | `const Editor = dynamic(() => import('@layermetry/media-editor/react').then(m => m.ImageEditor), { ssr: false })` |
| Browser custom element | `<media-editor-image id="e" style="height:100vh"></media-editor-image>` after importing package |

### Essential props (both editors)

| Prop | Type | Required | Purpose |
|------|------|----------|---------|
| `licenseKey` | string | ✅ | JWT token, checked in browser without network call, safe in client code |
| `onClose` | `() => void` | ✅ | Callback when user closes editor |
| `apiUrl` | string | ❌ | Override license validation endpoint (default: `https://api.kloudleads.com/license/validate`) |
| `theme` | `Record<string, string>` | ❌ | Custom colors: `'background.primary'`, `'text.primary'`, `'accent.primary'`, etc. |
| `showThemeCreator` | boolean | ❌ | Show theme UI to users (set `false` for production) |

### ImageEditor-specific props

| Prop | Type | Purpose |
|------|------|---------|
| `files` | File | Initial image file to load |
| `callback` | `(result, extras?) => void` | Export callback receives `{ base64, width, height, template? }` |
| `brands` | BrandDetails[] | Brand presets for styling |
| `defaultTemplate` | Template | Load template on startup |

### VideoEditor-specific props

| Prop | Type | Purpose |
|------|------|---------|
| `defaultVideo` | File | Initial video file to load |
| `onExport` | `(result) => void` | Export callback receives `{ videoUrl, thumbnail, duration, width, height, fps }` |
| `export` | `{ experimental: true }` | Opt into 4.4x faster export path (off by default) |

### Video editor CORS headers (critical)

Add to `next.config.js`:
```javascript
async headers() {
  return [{
    source: '/editor/:path*',
    headers: [
      { key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
      { key: 'Cross-Origin-Embedder-Policy', value: 'require-corp' },
    ],
  }];
}
```

Verify in browser console: `window.crossOriginIsolated === true`

### Theme keys (sample)

```javascript
{
  'background.primary': '#0f172a',
  'background.secondary': '#1e293b',
  'text.primary': '#ffffff',
  'accent.primary': '#3b82f6',
  'accent.secondary': '#06b6d4',
  'border.default': '#334155',
  'button.primary': '#3b82f6',
  'input.background': '#1e293b',
  'toolbar.background': '#0f172a',
  'canvas.background': '#1a202c',
}
```

## Decision guidance

### When to use ImageEditor vs VideoEditor

| Need | Use | Reason |
|------|-----|--------|
| Fast load, mobile support, instant export | ImageEditor | ~500ms load, works on mobile, <100MB memory |
| Multi-track timeline, audio, subtitles, 4K | VideoEditor | Full timeline control, but ~2s load, desktop only, 500MB+ memory, 1-2min export |
| Lightweight integration | ImageEditor | No WASM files, no special headers needed |
| Complex video workflows | VideoEditor | Trim, split, speed, overlays, SRT subtitles, karaoke captions |

### When to use mount() vs React components

| Scenario | Use | Reason |
|----------|-----|--------|
| React/Next.js app | React components | Props-based, cleaner state management |
| Vue, Angular, Svelte | `mount()` function | Framework-agnostic, custom element |
| Plain HTML | Browser tag or `mount()` | No build step needed |
| Headless/programmatic | `mount()` with `calls` array | Full control over operations |

### When to use custom AI endpoints vs layermetry-provided

| Scenario | Use | Reason |
|----------|-----|--------|
| Privacy critical, media never leaves browser | Custom endpoint | Route AI calls to your proxy, media stays local |
| Simple integration, no privacy concerns | Layermetry-provided | Default models, no setup required |
| Running own models | Custom endpoint | OpenAI-compatible format, works with local models |

## Workflow

### Integrating ImageEditor into Next.js

1. **Install and configure webpack**: `npm install @layermetry/media-editor`, update `next.config.js` to alias `canvas: false` and `fs: false`
2. **Import styles**: Add `@import "@layermetry/media-editor/dist/index.css"` to `app/globals.css`
3. **Dynamic import**: Use `next/dynamic` with `ssr: false` to load editor only in browser
4. **Set up state**: Track selected file, editor visibility, and exported result
5. **Handle file selection**: Accept image file, set state, show editor
6. **Implement export callback**: Receive `{ base64, width, height }`, download or upload
7. **Apply theme** (optional): Pass `theme` object and set `showThemeCreator={false}`
8. **Test**: Verify editor loads, filters/text/shapes work, export produces correct output

### Integrating VideoEditor into Next.js

1. **Install package**: `npm install @layermetry/media-editor`
2. **Add CORS headers**: Configure `next.config.js` with `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy`
3. **Copy WASM files**: Run `cp node_modules/@layermetry/media-editor/dist/*.wasm public/` and copy worker files
4. **Add URL rewrites** (optional): If editor is at `/studio/video`, add rewrites to serve WASM from root
5. **Dynamic import**: Use `next/dynamic` with `ssr: false`
6. **Set up state**: Track video file, editor visibility, export progress
7. **Handle file selection**: Accept video file, show editor
8. **Implement export callback**: Receive `{ videoUrl, thumbnail, duration }`, download or upload
9. **Show loading overlay**: Display progress during export (1-2 minutes typical)
10. **Test**: Verify WASM loads, timeline works, export completes without SharedArrayBuffer errors

### Troubleshooting integration

1. **Check browser console**: Most errors show detailed messages
2. **Check Network tab**: Look for 404s (missing WASM), CORS errors, failed license validation
3. **Verify setup**: Follow integration guide step-by-step, compare with example project
4. **Restart dev server**: After config changes, kill process and restart
5. **Hard refresh browser**: Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows)
6. **Check environment variables**: Ensure `NEXT_PUBLIC_LICENSE_KEY` and `NEXT_PUBLIC_API_URL` are set
7. **Verify license key**: Confirm JWT token is valid and domain is whitelisted
8. **Test CORS headers**: Run `console.log(window.crossOriginIsolated)` for video editor

## Common gotchas

- **Package name is `@layermetry/media-editor`, not `@distralabs/media-editor`**: Old package name is out of date. Update imports and package.json.
- **React 18 and React 19 both work**: Do not pin `react@18.2.0` for version 2. Remove any existing pins.
- **No ffmpeg in version 2**: Version 1 shipped 31 MB of WebAssembly. Version 2 ships none. Do not add `ffmpeg.wasm`.
- **Dynamic import with `ssr: false` is mandatory**: Editor uses browser-only APIs (Canvas, WebAssembly, Web Workers). SSR will fail. Always use `next/dynamic` with `{ ssr: false }`.
- **Video editor needs CORS headers**: Without `Cross-Origin-Opener-Policy: same-origin` and `Cross-Origin-Embedder-Policy: require-corp`, video export fails with SharedArrayBuffer error. Image editor does not need them.
- **WASM files must be in `public/` folder**: VideoEditor cannot load WASM from node_modules. Copy files and add URL rewrites if editor is in a subdirectory.
- **License validation happens without network call**: Key is signed and checked in browser. It fails open—if layermetry is unreachable, editor keeps working. Safe to put in `NEXT_PUBLIC_` variables.
- **API URL path is appended with `/license/validate`**: If your endpoint is `https://localhost:3030/social/license/validate`, use `apiUrl="https://localhost:3030/social"`, not the full path.
- **Video export is slow**: 1080p 30s video takes ~2 minutes. Show loading overlay and warn users. Desktop only; mobile not supported.
- **Image editor is fast**: ~500ms load, instant export, works on mobile.
- **Theme keys are strings, not objects**: Pass `{ 'background.primary': '#0f172a' }`, not nested objects.
- **Callbacks are required**: `onClose` is mandatory. `callback` (ImageEditor) and `onExport` (VideoEditor) are optional but needed to get results.
- **No MCP server shipped**: There is no MCP endpoint. Drive verbs through the SDK directly.

## Verification checklist

Before submitting work:

- [ ] Package installed: `npm list @layermetry/media-editor` shows 2.0.0
- [ ] SDK CSS imported in `app/globals.css` or equivalent
- [ ] Dynamic import used with `ssr: false` (Next.js)
- [ ] License key provided and valid (check browser console for validation errors)
- [ ] `onClose` callback implemented
- [ ] Export callback (`callback` or `onExport`) implemented to handle results
- [ ] Theme applied (if custom branding required) and `showThemeCreator={false}` set
- [ ] For video editor: CORS headers configured in `next.config.js`
- [ ] For video editor: WASM files copied to `public/` and accessible (check Network tab)
- [ ] For video editor: URL rewrites added if editor is in subdirectory
- [ ] Dev server restarted after config changes
- [ ] Browser hard-refreshed (Cmd+Shift+R / Ctrl+Shift+R)
- [ ] Editor loads without console errors
- [ ] File selection works (image or video)
- [ ] Editor UI renders correctly with custom theme (if applied)
- [ ] Export produces correct output (base64 for image, videoUrl for video)
- [ ] Download or upload flow works end-to-end

## Resources

- **[llms.txt](https://layermetry.com/docs/llms.txt)** — Complete page-by-page navigation for all documentation
- **[Installation Guide](https://layermetry.com/docs/installation.md)** — Framework-specific setup (React, Next.js, Vue, Angular, Svelte, plain HTML)
- **[API Reference](https://layermetry.com/docs/api-reference/introduction.md)** — Complete prop documentation, theme keys, callbacks, templates
- **[Troubleshooting FAQ](https://layermetry.com/docs/troubleshooting/faq.md)** — Common errors, WASM loading, license validation, video processing issues

---

> For additional documentation and navigation, see: https://layermetry.com/docs/llms.txt