Needle Engine

Needle Engine is a web-first 3D framework built on three.js for building games, configurators, AR/VR experiences, and interactive websites.

Built-in: Rapier Physics | WebXR (incl. iOS) | Multiplayer & VOIP | Blender & Unity Integration

Built on three.js and the glTF standard, Needle Engine delivers flexible, extensible web experiences with built-in collaboration and XR support. Use it standalone with npm or with powerful editor integrations for Unity and Blender.

Changelog | Documentation | Samples | Showcase | API Reference

npm install @needle-tools/engine

Try it now on StackBlitz | Getting Started Guide

import { Behaviour, serializable } from "@needle-tools/engine";

export class MyComponent extends Behaviour {

@serializable()
speed: number = 1;

start() {
console.log("Component started on:", this.gameObject.name);
}

update() {
this.gameObject.rotateY(this.context.time.deltaTime * this.speed);
}
}
import { Behaviour, Rigidbody, BoxCollider } from "@needle-tools/engine";

export class PhysicsBox extends Behaviour {

awake() {
// Add a physics body — Rapier is built in, no extra install needed
const rb = this.gameObject.addComponent(Rigidbody);
rb.useGravity = true;

// Add a collider
this.gameObject.addComponent(BoxCollider);
}
}
import { Behaviour, syncField } from "@needle-tools/engine";

export class SyncedCounter extends Behaviour {
// Automatically synced across all connected clients
@syncField()
count: number = 0;

onPointerClick() {
// Reassign to trigger sync (this is required for sync to work)
this.count = this.count + 1;
}
}
import { onStart, onUpdate } from "@needle-tools/engine";

onStart((context) => {
console.log("Engine started!");
});

onUpdate((context) => {
// Called every frame
});

WebXR & AR — immersive experiences on Android and iOS

  • WebXR support including WebXR on iOS
  • WebXRImageTracking — AR image targets with full tracking lifecycle
  • WebXRPlaneTracking — AR surface detection
  • Interactive QuickLook for AR on Vision Pro

Scene & Asset Management

  • SceneSwitcher — load different scenes / hierarchies by URL
  • AssetReference — runtime asset loading by URL
  • Multi-scene support with dynamic content loading

Physics & Interaction — Built-in Rapier physics engine

  • Rigidbody, BoxCollider, SphereCollider, MeshCollider — full physics simulation
  • DragControls — click-and-drag 3D objects with zero code
  • SpatialTrigger — proximity and enter-zone detection

Multiplayer & Networking — real-time collaboration out of the box

  • SyncedRoom + @syncField() — automatic state synchronization
  • Voip — built-in WebRTC voice chat
  • PlayerSync — player object sync on join/leave
  • SyncedCamera — camera sync for observer sessions
  • Low level networking events for full control

Rendering & Effects

  • Advanced PBR rendering with lightmap support
  • Post-processing (Bloom, DepthOfField, SSAO, ChromaticAberration, Tonemapping and more)
  • Progressive texture and mesh loading with automatic LOD generation

Animation & Media

  • Animation state machines and timeline animations
  • VideoPlayer — full video playback component
  • AudioSource — 3D spatial audio
  • Animate anything via KHR_animation_pointer

Framework Integration — works with React, Vue, Svelte, or vanilla JS/TS

See all features

Needle Engine works standalone with just npm — no editor required. For asset-heavy workflows, use our editor integrations:

Preview Example Description Links
Multiuser Cross device experience, Desktop, AR & VR (Sandbox) Real-time collaborative multiplayer sandbox experience with WebXR on Android and iOS
Image Tracking AR AR image tracking example (iOS and Android). See docs
Scrollytelling Bike Example Timeline Animation using ScrollFollow, ViewBox and FocusRect Project on Github
See-Through Walls See-Through component sample
Cursor Follow Cursor Follow sample
Animate Anything Interactive animation system Code on Stackblitzthree.js Example
Postprocessing Effects Custom magnifier effect with post-processing Code on Stackblitz
Unity ShaderGraph to MaterialX & mtlx materials Using @needle-tools/materialx
Camera Focus DIV 1 Responsive layout with camera focus Code on Stackblitz
Camera Focus DIV 2 Click-to-move camera focus example Code on Stackblitz
FastHDR Loading 10x faster than EXR, non-blocking, 95% less GPU memory Code on StackblitzLearn more
Scrollytelling Example Scroll, physics and cursor interaction: a playful 3D interactive scrollytelling website Included in Samples Package
AR Restaurant Interactive AR restaurant experience Code on Github
Custom Loading Overlay Wait for LODs with custom loading states Code on Stackblitz
React Shopping Cart E-commerce integration with React Code on Stackblitz

👋 More examples on samples.needle.tools, docs.needle.tools and in the Needle Engine Stackblitz Collection


Contact ✒️

🌵 NeedleGithubTwitterDiscordForumYoutube


Recent Changes

Fixed

  • SyncedTransform: added world scale support — networked objects now keep the correct scale across clients, even when nested under scaled parents, with smooth interpolation
  • AR & XR improvements: networked avatars now use the correct scale, stale avatars are reliably removed after a peer disconnects, and remote hands display correctly in Screen AR

Your glTF and GLB scenes now come with auto-generated TypeScript types. Access nodes, components, and properties with full autocomplete and type checking via ctx.sceneData or the new needle shorthand — no configuration required. Types regenerate automatically whenever your scene files change, and it works with local files, remote URLs, and Needle Cloud assets alike.

const cam   = ctx.sceneData.MyScene.MainCamera.$object;                      // THREE.PerspectiveCamera
const orbit = ctx.sceneData.MyScene.MainCamera.$components.OrbitControls; // typed!
orbit.autoRotate = true;

Needle Engine now feels at home in any modern web stack. SSR support lets you import the engine in SvelteKit, Next.js, and Nuxt without crashes, JSX type declarations bring full autocomplete to React, Preact, SolidJS, and friends, and the new needle shorthand gives you instant access to the current context from anywhere — components, button handlers, or plain JavaScript.

import { needle } from "@needle-tools/engine";
needle.scene.traverse(obj => { ... }); // access the three.js scene
needle.renderer; // access the WebGLRenderer

Drop a published Needle Engine app into any web page with a single element — no build setup, custom code, or framework required. It handles cross-origin loading for you and works inside iframes.

<needle-app src="https://your-app.needle.run"></needle-app>

A new set of builder APIs lets you create animations, animator controllers, and timelines entirely in code, with typed keyframes and inline track definitions. Great for procedural content, runtime-generated sequences, and tooling.

const timeline = TimelineBuilder.create("MyTimeline")
.animationTrack("Walk", animator).clip(walkClip, { duration: 2 })
.activationTrack("FX", vfxObject).activate({ start: 1, duration: 0.5 })
.build();
director.playableAsset = timeline;

DragControls received a major overhaul with a new constraint system: keep-scale, two-touch scaling with min/max limits, refined hit regions, and a dedicated screen-space drag mode for AR. Single-touch dragging is now more predictable, and reliability is improved across snapping, side views, and multi-input scenarios.

The bundled MaterialX runtime jumps to 1.7.0 with faster environment lighting (new radiance sampling modes and PMREM support), better Three.js integration, and overall performance improvements.

A new autoCleanup API and a typed Context.events bus make it easy to write components that tidy up after themselves. Many subscription APIs — input, networking, and XR events — now return an unsubscribe function that pairs perfectly with autoCleanup.

onEnable() {
this.autoCleanup(this.context.input.addEventListener("pointerdown", evt => { ... }));
this.autoCleanup(this.context.connection.beginListen("my-event", data => { ... }));
}

Added

  • Scene Bindings — auto-generated, fully typed access to your scenes via ctx.sceneData / needle.sceneData
  • SSR support for SvelteKit, Next.js, and Nuxt, plus JSX type declarations for React, Preact, SolidJS and more
  • needle shorthand for quick access to the current engine context from anywhere
  • <needle-app> — embed a published Needle Engine app in any web page (docs)
  • Context.events — a typed event bus for decoupled component communication:
    context.events.on("scene-content-changed", e => console.log(e.object));
    context.events.emit<{ pts: number }>("scored", { pts: 10 });
  • autoCleanup on Behaviour — register disposables and cleanup tied to the component lifecycle
  • Builder APIs (preview)TimelineBuilder, AnimatorControllerBuilder, and AnimationBuilder for defining timelines, controllers, and animations in code with typed keyframes and inline tracks
  • DragControls: new constraint system with keepScale, two-touch scale limits, refined hit regions, a screen-space AR drag mode, and EventList support
  • Skybox: new background-rotation / environment-rotation attributes and background-image-loaded / environment-image-loaded events
  • WebXRImageTracking: per-frame imageTracked event with typed access to the tracked object, plus resetImage / resetAllImages to re-arm markers without restarting XR:
    imageTracking.imageTracked.addEventListener(evt => console.log(evt.object, evt.image));
    
  • AudioClip type with standalone playback control, AudioSource spatial blend and .opus support
  • context.lights array and context.mainLight getter for quick access to scene lighting
  • NeedleXRSession.appClipUrl — launch a custom-branded Needle AppClip experience on iOS AR (provide your registered appclip.needle.tools/x/… URL or experience id) for your own App Clip card title and image (custom branding requires PRO — see Custom Branding for iOS AR)
  • Physics raycast includeTriggers option
  • Unsubscribe functions returned from Input, Networking, and XR event subscriptions
  • needlePlugins() can now be called without arguments — the Vite command is resolved automatically:
    export default defineConfig({ plugins: [sveltekit(), needlePlugins()] });
    

Changed

  • OrbitControls now uses lookAtTarget / lockLookAtTarget, with smoother focus and camera transitions
  • Postprocessing moved to core (context.postprocessing); tonemapping-only setups skip the extra pass
  • Timeline track classes renamed for consistency (e.g. AnimationTrackHandlerTimelineAnimationTrack)
  • GroundProjectionEnv.applyOnAwake now defaults to true, matching Unity and Blender

Fixed & Improved

  • Major DragControls reliability improvements across snap points, AR drag, side views, and multi-input handover
  • More reliable camera handling (fallback camera, fitCamera, scene clearing)
  • More efficient Skybox attribute handling and load deduplication
  • Smoother, more reliable progressive LOD loading and disposal, including texture-only LODs that update correctly with camera distance
  • AudioSource on iOS now survives a device lock / audio-session interruption and resumes automatically
  • SceneSwitcher: ?scene= honored for in-scene object references, with prefab preview support
  • VoIP improvements including better iOS mic handling and shared AudioContext
  • Faster initial loading via improved dependency chunking
  • Updated MaterialX runtime to 1.7.0 with faster environment lighting and PMREM support
  • General reliability and stability improvements throughout the engine and Vite plugin

Fixed

  • Progressive loading: texture LODs no longer get stuck for meshes that only have texture LODs (no mesh LODs); screen coverage is computed unconditionally again so texture LODs update with camera distance

Added

  • <needle-app> — embed a published Needle Engine app in any web page (with custom code etc) (docs)

Changed

  • <needle-app>: improved cross-origin handling and src parsing
  • ScrollFollow: now works inside an iframe (uses the top window)

Fixed

  • iOS audio: AudioSource playback now survives a device lock / audio-session interruption and resumes automatically on unlock
  • SceneSwitcher: ?scene= is now honored for scenes referenced as in-scene Object3Ds; scene preview loading supports prefabs and correct parenting under the SceneSwitcher
  • DragControls: widened the two-pointer scale clamp range and now reads world scale from the matrix columns
  • EventList: corrected the arguments passed to overridden methods
  • serializeObject: fixed Color / Euler / object-reference serialization, and OneEuroFilter.reset()
  • Prevented a TypeError when a scene-data error proxy is coerced to a string