This guide is for contributors, fork authors, and developers who want to run Reze Studio locally — whether to add a feature, fix a bug, experiment with the architecture, or simply explore the codebase with a live dev server. The production build at reze.studio requires no local setup, but if you want to make changes and see them reflected immediately, follow the steps below.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AmyangXYZ/reze-studio/llms.txt
Use this file to discover all available pages before exploring further.
The dev server starts on port 4000, not the Next.js default of 3000. Keep that in mind when opening browser tabs or configuring any local proxy.
Prerequisites
You will need the following before you begin:- Node.js — any recent LTS release (Node 18, 20, or 22). The project has no hard engine version requirement, but the lockfile was generated with a modern LTS.
- A WebGPU-capable browser — Reze Studio renders exclusively via WebGPU. Chrome 113+, Edge 113+, or Safari 18+ are all supported. See the Tech Stack page for a full breakdown of browser support.
Getting Started
Install dependencies
reze-engine, Next.js 16, React 19, shadcn/ui, and Tailwind CSS v4.Start the dev server
http://localhost:4000 with hot module replacement enabled. Changes to React components and TypeScript files are reflected immediately without a full page reload.Open in a WebGPU-capable browser
Navigate to http://localhost:4000 in Chrome 113+, Edge 113+, or Safari 18+. The default Reze model and sample VMD animation load automatically so you can start exploring the editor right away.
Available Scripts
All scripts are defined inpackage.json and run via npm run:
| Script | Command | Description |
|---|---|---|
dev | next dev --port 4000 | Start the development server with HMR on port 4000 |
build | next build | Create a production-optimised build in .next/ |
start | next start | Serve the production build (run build first) |
lint | eslint | Run ESLint across the project using eslint-config-next |
Project Structure
The repository follows the Next.js App Router convention. Here are the directories you will work with most:| Directory / File | Purpose |
|---|---|
app/ | Next.js App Router entry point. Contains layout.tsx (global HTML shell, Vercel Analytics) and page.tsx (mounts the provider tree and <StudioPage>). |
components/ | All React components. Key files: studio.tsx (StudioPage layout + file handlers), engine-bridge.tsx (headless engine effects), timeline.tsx (dopesheet + curve editor), properties-inspector.tsx (pose sliders + interpolation editor). |
context/ | External store implementations. studio-context.ts owns document + selection state (the undo/redo target); playback-context.ts owns transport state (currentFrame, playing, currentFrameRef). |
lib/ | Pure utility modules. animation.ts — bone group definitions, channel descriptors, quaternion/Euler conversion. utils.ts — clip helpers, keyframe upsert, cloneAnimationClip, simplifyBoneTrack. materials.ts — NPR material auto-classification heuristic. |
components/ui/ | shadcn/ui primitives generated into the repo. Button, Menubar, Tabs, Slider, Input, and other Radix-backed components live here. Edit with care — these are regenerated by shadcn add. |
public/models/ | Bundled PMX model loaded on startup. The default model folder contains a .pmx file and its texture assets. |
public/animations/ | Bundled sample VMD animation (miku.vmd) loaded alongside the default model on first boot. |
Architecture Notes for Contributors
Before adding a new interaction, read the Architecture page. The single most important rule is: hot paths must not callsetState at pointer-move or rAF frequency.
Concretely:
- Drag interactions (keyframe drag, pose slider drag, gizmo drag) should follow the preview/commit split: mutate the live
clipobject in place during the gesture, callcommit()exactly once onpointerup. Seecomponents/axis-slider-row.tsxand the gizmo drag handler incomponents/engine-bridge.tsxfor reference implementations. - Any new rAF-driven update should write into a ref or call an imperative canvas handle — not
setState. If React state must reflect the result, update it once when the loop stops. - New state fields that change frequently (>10Hz) belong in a new external store (or as a ref in an existing one), not in
useStateinside a component that is a parent of many children. - Selectors should be narrow.
useStudioSelector(s => s.selectedBone)is correct;useStudioSelector(s => s)subscribes to the entire store and will re-render on every action.
License
Reze Studio is released under the GNU General Public License v3.0 (GPLv3). Any fork or derivative work distributed publicly must also be released under GPLv3. See theLICENSE file in the repository root for the full license text.