Design 3D gradient waves in your browser: the glossy, twisting wave of light from Stripe's designs. Tweak one live, then export a code snippet that drops straight into your app.
โถ Open the studio ยท runs in the browser, nothing to install.
- Play. Open the studio and tweak a preset until it looks right.
- Export. Click โจโฉ Export code, pick your framework, and hit Copy. Grab Download poster.png while you're there as it will be used as a fallback.
-
Install. The snippet's top line is the command to run, e.g.
pnpm add @wave3d/react three. - Paste. Drop the snippet into your app. What you saw in the studio is what renders.
A wave is a strip swept along a curve, driven by one JSON config. The panel lets you:
- Shape it: spine sweep, twist, taper, width, edge feather, and light.
- Color it: linear, radial, conic, or mesh gradients, palettes, and image maps.
- Finish it: grain, blur, glow, sheen, and hue / contrast / saturation.
- Layer it: multiple strands with per-strand overrides, plus presets, randomize, and undo/redo.
Prefer to run it locally? pnpm install && pnpm dev opens the studio at the printed localhost URL (needs Node 18+ and pnpm).
Pick a size in Output, then export any of these:
| Export | What you get |
|---|---|
| โจโฉ Code | A copy-paste snippet for React, Vue, Svelte, vanilla JS, or a CDN <script>, with your config baked in and an optional inline poster. |
| ๐ท Image | An exact-size PNG, WebP, or JPEG still. PNG and WebP keep transparency. |
| ๐ฌ Video / GIF | A WebM or MP4 clip, an animated GIF, or a full-color animated WebP. |
| ๐ Embed | A self-contained .html page with the runtime inlined. Nothing else to ship. |
| ๐ผ๏ธ Wallpaper | A folder of device-sized stills for desktop and mobile. |
| โ๏ธ Config | The .json config. Save it, reload it, or copy a share link. |
Skipping the studio? The engine ships as framework-agnostic packages:
pnpm add @wave3d/react three # React convenience wrapper
pnpm add @wave3d/element three # <wave-3d> for Vue, Svelte, or plain HTMLimport { Wave3D } from "@wave3d/react";
<Wave3D preset="Hero" poster="/wave.png" style={{ width: 480, height: 270 }} />;Or one <script> from a CDN, with three bundled in:
<script type="module">
import { mountWave } from "https://esm.sh/@wave3d/core/standalone";
mountWave(document.getElementById("wave"), {
/* your exported config */
});
</script>Every package is poster-first: it shows a still, then upgrades to live WebGL only when the browser can handle it, and falls back to the poster on no-WebGL, Save-Data, reduced motion, or a lost context. three.js is code-split out of the initial load to minimize performance impact.
three is a peer dependency (>=0.180 <1); add @types/three for TypeScript. Per-package docs: @wave3d/core, @wave3d/react, @wave3d/element.
Each strand is a wave swept along a smooth curve, carried by parallel transport, twisted around the tangent, and extruded to a tapering width, then colored by a gradient with a satin sheen and a soft-focus blur. The renderer, the studio panel, and every export all read from the same config. As a background it behaves: it clamps DPR, pauses when offscreen or hidden, and honors prefers-reduced-motion.
Built by Amir Abushanab with Three.js, Tweakpane, and Vite.
