Getting Started With ThreeUI
Set up ThreeUI in React, add an animated 3D hero background, fix runtime asset paths, and manage performance with lazy loading and reduced-motion fallbacks.
ThreeUI is a React component catalog by Meng To, published at threeui.com and on npm as @designcodeio/threeui. Each component brings its own animated renderer (Three.js, raw WebGL or Canvas 2D, depending on the component), so you add an animated 3D hero background by importing a component instead of building a scene, camera and materials.
You want a hero that stops the scroll, but a Three.js tutorial starts with scene graphs, lighting rigs and render loops before anything shows up on screen. This guide covers installing ThreeUI, rendering one background component behind a hero, fixing the asset-path problem, and deciding whether the extra weight is worth it on your page.
Key Takeaways
- Install ThreeUI with
npm install @designcodeio/threeuiand import@designcodeio/threeui/style.cssonce from your app entrypoint. - ThreeUI lists
reactandreact-dom(18 or 19) andthreeas peer dependencies. - Components that render a full HTML document load runtime files from root-relative URLs, so copy them from
node_modules/@designcodeio/threeui/lib-dist/assets/or setsourceUrlorassetBaseUrl. - Anything beyond a component’s exposed variants and controls means editing its source.
- Lazy-load ThreeUI components, skip them when
prefers-reduced-motionis set, and use a static image when the 3D effect adds nothing.
What Is ThreeUI and Who Is It For?
ThreeUI gives you ready-made animated sections (heroes, backgrounds, interactive elements) that you drop into an ordinary React page. You don’t need to know how a scene graph works. You pick a component, render it and set its props.
Several unrelated projects are called three-ui, including poki-archive/three-ui and nirholas/three-ui. This guide is about Meng To’s ThreeUI from threeui.com and the MengTo/threeui repository.
ThreeUI comes in two tiers: Community and Pro. Community components are MIT licensed and install from npm. Pro components are not on npm: you download them as source into your project with npx @designcodeio/threeui-cli after signing in with an active paid plan. The project is young (Community was open-sourced in August 2026), so expect the API to change.
Install the ThreeUI Package
Install one npm package, then import its stylesheet once. The ThreeUI installation page walks through setup. The published package lists react and react-dom from version 18 up to, but not including, 20, plus three from 0.149, as peer dependencies. npm 7 and later installs missing peers for you. The Pro CLI needs Node.js 20 or later.
npm install @designcodeio/threeui
Where the stylesheet import goes depends on your framework:
| Framework | Where the CSS import goes |
|---|---|
| Vite | src/main.jsx |
| Next.js App Router | app/layout.jsx |
// src/main.jsx (Vite)
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "@designcodeio/threeui/style.css";
import App from "./App";
createRoot(document.getElementById("root")).render(
<StrictMode>
<App />
</StrictMode>
);
Drop In One Component
To render a ThreeUI component, import it by name and place it in your JSX. The README’s example uses AtTheHorizon, but that component isn’t exported by the current 1.2.0 package, so this guide uses EmeraldHorizonBackground, an animated Three.js background that sits behind a hero section:
import { EmeraldHorizonBackground } from "@designcodeio/threeui";
export function Hero() {
return <EmeraldHorizonBackground />;
}
The root import is the simplest option. The package also offers a per-component subpath, which pulls in less code while you develop:
import { EmeraldHorizonBackground } from "@designcodeio/threeui/components/EmeraldHorizonBackground";
Props differ from one component to the next. Look them up on each component’s threeui.com page. For example, Brand Orbs takes variant, size, mode, speed and paused. Don’t guess props. To add an interaction without depending on any props, use state in the surrounding component:
import { useState } from "react";
import { EmeraldHorizonBackground } from "@designcodeio/threeui";
export function Hero() {
const [show3D, setShow3D] = useState(true);
return (
<section>
{show3D ? (
<EmeraldHorizonBackground />
) : (
<img src="/hero-fallback.jpg" alt="Product hero" />
)}
<button onClick={() => setShow3D((v) => !v)}>
{show3D ? "Show static image" : "Show 3D"}
</button>
</section>
);
}
The ThreeUI Asset Gotcha
Some ThreeUI components render a full HTML document. They fetch their runtime files from fixed paths at the root of your site, the same paths the ThreeUI preview site uses. Landscape, for example, asks for /landscape.html by default. If your app doesn’t serve a file at that path, the component breaks. You can fix this in two ways. Copy the files you need from node_modules/@designcodeio/threeui/lib-dist/assets/ into your public folder. Or, if the component has a sourceUrl or assetBaseUrl prop, point it at wherever you host the files.
# Check the network tab for the exact paths the component requests,
# then mirror that layout under public/.
cp -R node_modules/@designcodeio/threeui/lib-dist/assets/. public/
// Only if the component's page lists this prop:
// <SomeComponent assetBaseUrl="/threeui/" />
| Symptom | Fix |
|---|---|
| Component area renders empty; network tab shows 404s under the root path | Copy the needed assets into public/ at matching paths |
| Assets live on a CDN or a sub-path | Set sourceUrl or assetBaseUrl where the component exposes it |
How ThreeUI Sits With Plain Three.js
ThreeUI hides the renderer. In the Three.js-based components, the scene, camera, renderer, materials and animation loop all live inside the component. Other components use raw WebGL or Canvas 2D. The cost of that convenience is control: ThreeUI exposes each component’s variants and controls, and changing anything they don’t cover means editing the component’s source. You can read Community source in node_modules and on GitHub. The Pro CLI copies Pro source into your project.
If you expect to go past the exposed controls, learn the underlying library. Building 3D animations using JavaScript and Three.js covers the fundamentals.
ThreeUI Performance, Honestly
Every ThreeUI component runs a live animated canvas, which costs JavaScript, asset downloads and GPU time. Mobile GPUs feel that cost the most. Load components lazily, skip them for visitors who set prefers-reduced-motion, and use a static image anywhere the 3D effect adds nothing to the page.
React.lazy expects a default export, so map the named export:
import { lazy, Suspense, useEffect, useState } from "react";
const EmeraldHorizonBackground = lazy(() =>
import("@designcodeio/threeui").then((m) => ({ default: m.EmeraldHorizonBackground }))
);
function useReducedMotion() {
const [reduced, setReduced] = useState(false);
useEffect(() => {
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
setReduced(mq.matches);
const onChange = (e) => setReduced(e.matches);
mq.addEventListener("change", onChange);
return () => mq.removeEventListener("change", onChange);
}, []);
return reduced;
}
function hasWebGL() {
const canvas = document.createElement("canvas");
return Boolean(canvas.getContext("webgl2") || canvas.getContext("webgl"));
}
const fallback = <img src="/hero-fallback.jpg" alt="Product hero" />;
export function Hero() {
const reduced = useReducedMotion();
const [webgl, setWebgl] = useState(false);
useEffect(() => setWebgl(hasWebGL()), []);
if (reduced || !webgl) return fallback;
return <Suspense fallback={fallback}><EmeraldHorizonBackground /></Suspense>;
}
The Hero component above reads the prefers-reduced-motion media feature through window.matchMedia and checks for a context with HTMLCanvasElement.getContext. Some components handle reduced motion themselves. Brand Orbs, for example, has speed and paused props, and its source checks prefers-reduced-motion and pauses when it’s out of view. Check each component’s page for what it covers.
In Next.js, use next/dynamic. The ssr: false option only works inside a Client Component, and Next.js throws an error if you use it in a Server Component. Turning off server rendering is a safe default for canvas code that only runs in the browser:
"use client";
import dynamic from "next/dynamic";
const EmeraldHorizonBackground = dynamic(
() => import("@designcodeio/threeui").then((m) => m.EmeraldHorizonBackground),
{ ssr: false, loading: () => <img src="/hero-fallback.jpg" alt="Product hero" /> }
);
export default function Hero() {
return <EmeraldHorizonBackground />;
}
See the Next.js lazy loading guide for details. Run your build tool’s bundle analyzer to see what ThreeUI actually adds to your bundle. Lab tests only show part of the picture, though. A session replay tool such as OpenReplay lets you watch real visits, so you can spot a hero that stays blank or stutters on slower phones. If you need more control than a prebuilt component gives you, the lower-level options are covered in WebGPU vs WebGL: Why the Industry Is Moving On.
Pin the ThreeUI package version. Per the README’s release rules, a Community release goes out when a maintainer merges the reviewed sync pull request, and removing a public component, variant or control triggers a major version. AtTheHorizon is an example: it shipped in 0.3.0 and is gone from the 1.x releases. Review the release notes before you upgrade.
Conclusion
ThreeUI gets you a working 3D hero background with one npm install, one stylesheet import and one component. Budget time for serving the runtime assets, and keep in mind that it trades control for speed. Start by rendering one Community component behind a lazy boundary with a reduced-motion fallback. Then measure the bundle and test on a mid-range phone before you decide it stays on the page.
FAQs
Can I use ThreeUI Community components in a commercial project?
Yes. ThreeUI Community application code, component code and ThreeUI-authored imagery are MIT licensed, which allows commercial use as long as you keep the license notice. Bundled open fonts remain under the SIL Open Font License 1.1, and bundled Three.js runtime files remain MIT licensed. Pro components are a separate paid product, so check the Pro terms before shipping them.
What happens if I rerun the ThreeUI Pro CLI after editing a downloaded component?
The ThreeUI Pro CLI won't replace files you've edited unless you add the --force flag, for example npx @designcodeio/threeui-cli add cross-beam --dir ./src --force. Using --force replaces your edits with the downloaded source, so commit your changes first and merge them back by hand. Run npx @designcodeio/threeui-cli --help to see the other commands and flags, including login and logout.
Why don't ThreeUI Pro components appear in package.json or npm update?
Pro components are not an npm dependency. The ThreeUI CLI copies their source straight into your project, so they are not listed in package.json, and npm update, npm outdated and lockfile-based dependency scanners do not track them. Treat Pro files as vendored code: keep them in version control and download them again with the CLI when you want a newer version.
Does every ThreeUI component need WebGL?
No. Some ThreeUI components draw with Canvas 2D instead of WebGL. The DesignCode preset of Brand Orbs, for example, draws its dot field with Canvas 2D. A blanket WebGL check hides these components from browsers that could run them, so apply a getContext('webgl2') or getContext('webgl') guard only to components whose threeui.com page describes a Three.js or WebGL renderer.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k