A prime-radiant timeline prototype: an interactive 3D visualization of branching narratives, rendered with React Three Fiber and custom GLSL shaders. Nodes unfold along a tree of possible futures; the camera follows the user's focus while a particle field traces the edges between states.
npm install unfold-graphReact, three.js, and the react-three ecosystem are peer dependencies — install them alongside if you don't already have them:
npm install react react-dom three @react-three/fiber @react-three/drei @react-three/postprocessing postprocessingimport { Unfold, type UnfoldData } from "unfold-graph";
const data: UnfoldData = {
nodes: [{ id: "root" }, { id: "a" }, { id: "b" }],
edges: [
{ id: "e1", source: "root", target: "a" },
{ id: "e2", source: "root", target: "b" },
],
};
export function App() {
return (
<div style={{ width: "100%", height: "100vh" }}>
<Unfold
data={data}
onSelectionChange={(nodeIds) => console.log("selected", nodeIds)}
/>
</div>
);
}<Unfold> is the single entry point; positions are auto-laid-out when omitted. Focus, selection, and expansion are each controllable or uncontrolled per-prop. See src/lib/types.ts for the full prop surface (theme, style, layout, cameraMode, the selected*/focused* state, and the on* callbacks).
- React 18 + TypeScript
- Vite
- @react-three/fiber, drei, postprocessing
- Custom vertex/fragment shaders for nodes and the particle field
src/main.tsx— React entry; mounts the demo gallerysrc/lib/— the Unfold libraryindex.ts— public API surface (re-exports)Unfold.tsx— top-level component (Canvas, bloom, error boundary)types.ts— public types (UnfoldData,UnfoldNode,UnfoldEdge, theme/style, …)internal/— Three.js scene, shaders, GPU mirrors, camera follow, layout (layout/), picking (picking/), and shared timeline types
src/demos/— the demo gallery SPADemoSite.tsx,Landing.tsx,DemoPage.tsx— shell, landing page, per-demo pageregistry.ts— the catalog of demos- one folder per demo (
hello-world/,deep-tree/,edge-flows/, …) _data/— shared demo fixtures (demoData.ts)
npm install
npm run devVite serves the app at the URL it prints (default http://localhost:5173). HMR is on; edits to src/ reload in place.
npm run build— typecheck (tsc -b) and produce a production bundle indist/npm run preview— serve the built bundle locally for a final check