npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fundamental-engine/three

v0.5.1

Published

Three.js authoring surface for Fundamental — run the reciprocal field engine headless and render its swarm as a THREE.Points layer (the particle bridge), plus threeHost() and threeBackend() (a RenderBackend) for binding the engine to a WebGL scene.

Readme

@fundamental-engine/three

The Three.js door to @fundamental-engine/core — run the reciprocal field engine headless and render its swarm as a THREE.Points layer in your own WebGL scene. The same physics the <field-root> element and @fundamental-engine/{vanilla,react} wrap, bound to a 3D scene instead of the DOM.

→ Live manual, Lab, and gallery at fundamental-engine.com.

Install

npm i @fundamental-engine/three three

three is a peer dependency — you bring your own version (≥ 0.147, the tested floor). The package touches only long-stable three APIs (the newest are InstancedMesh, r109, and Object3D.clear(), r123); it is built against modern three (0.169) and r147 is verified live in a real integration.

No build step? (CDN / single-file pages)

The package is plain ESM, so a page with no bundler consumes it straight from a CDN. Pin the three peer to the same revision your page already uses so the library and your scene share one Three.js:

<script type="module">
  // ?deps pins the peer; match it to your page's three version
  import * as FieldUI from "https://esm.sh/@fundamental-engine/[email protected][email protected]";
  window.FieldUI = FieldUI;                          // hand it to classic scripts
  window.dispatchEvent(new Event("fieldui-ready"));  // module scripts are deferred — signal readiness
</script>
<script>
  // a classic script can't await the module — start on the ready signal
  function startField() {
    const layer = window.FieldUI.createFieldLayer({ /* … */ });
    // scene.add(layer.object); tick in your render loop
  }
  if (window.FieldUI) startField();
  else window.addEventListener("fieldui-ready", startField, { once: true });
</script>

Prefer a fully offline page? Bundle once with esbuild and commit the artifact, mapping the peer onto your page's global THREE:

echo "module.exports = window.THREE" > three-shim.cjs
npx esbuild node_modules/@fundamental-engine/three/dist/index.js --bundle --format=iife \
  --global-name=FieldUI --alias:three=./three-shim.cjs --outfile=vendor/Fundamental-three.js

The particle bridge

The engine runs in signals-only mode (render: 'none') and exposes its particle pool through FieldHandle.readParticles(). FieldLayer pulls that each frame and writes it onto a THREE.Points geometry via a FieldProjection.

import * as THREE from 'three';
import { createFieldLayer, PlaneProjection } from '@fundamental-engine/three';

const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ antialias: true });

const layer = createFieldLayer({
  projection: new PlaneProjection({ relief: 2 }), // the field on a plane, z lifted from heat
  renderer,                                       // reads the device-pixel ratio
  accent: '#4da3ff',
});
scene.add(layer.object);

renderer.setAnimationLoop(() => {
  layer.tick();                 // the engine self-steps; tick() pulls the latest swarm
  renderer.render(scene, camera);
});

FieldLayer implements the full FieldHandle surface, so layer.burst(), layer.flowTo(), layer.setFormation(), and layer.seed() drive the 3D layer exactly as they drive the DOM field.

Flat plane or real volume

FieldProjection maps the engine's CSS-pixel field space to 3D world space:

  • PlaneProjection — the field on a quad; z is lifted stylistically from per-particle heat. The right choice for a flat field.
  • VolumeProjection — maps the engine's real depth lane (z ∈ [0, depth), the opt-in z axis) onto a world depth range, for a genuinely volumetric swarm.

Pass depth and the layer defaults to a VolumeProjection automatically — bodies stay on the page plane (z = 0) while free matter drifts through the volume and is pulled gently back, reading as depth and parallax around the content:

const layer = createFieldLayer({ depth: 300, renderer, accent: '#4da3ff' });

Both projections implement one interface, so FieldLayer and threeBackend are unchanged by the choice.

RenderBackend (diagnostic overlays)

threeBackend implements the engine's structural drawing seam (RenderBackend), so the diagnostic overlays — streamlines, field-lines, grid, contours, force-vector arrows — draw as scene geometry. Inject it via the lower-level createThreeField:

import { createThreeField, threeBackend, PlaneProjection } from '@fundamental-engine/three';

const projection = new PlaneProjection();
const overlay = threeBackend({ projection });
scene.add(overlay.object);

const field = createThreeField({
  viewport: () => ({ ...projection.size(), dpr: renderer.getPixelRatio() }),
  overlayBackend: overlay,
  overlay: 'streamlines',
});

The line overlays render fully; numeric label sprites (the data reading) are a tracked follow-up.

Bodies — meshes that bend the field

A scene object can be a body (a force source). layer.addBody(object3d, spec) registers it: it bends the field and the swarm responds, while density/load/lit feedback flows back to the mesh (drive a uniform from onFeedback). A body carries a data record (a genome, an inventory), so a mesh can be a meaningful agent, not just a force — and it can be tagged (species) and selective (affects) so several ecologies share one field.

const bloom = layer.addBody(blossomMesh, {
  tokens: 'attract', strength: 0.8, range: 260, // field px
  species: 1,                                    // this is "pollen-1" matter…
  data: genome,                                  // …carrying its genome
  onFeedback: (ch) => glow.material.opacity = ch.density ?? 0,
});
bloom.set({ strength: 0.3 }); // live — no re-create

Agents — creatures the engine moves

layer.addAgent(object3d, opts) makes a mesh a field agent: the engine steps it (it lives in the particle pool, so it feels every force the swarm feels — body forces and the particle-level hunt/align/cohesion) and drives the object's position each frame. This is the engine-stepped successor to FieldAgent (which samples + integrates itself).

const bee = layer.addAgent(beeMesh, {
  maxSpeed: 95,          // field px/frame
  species: 1,            // tagged bodies (affects) steer it selectively
  faceVelocity: true,
  hover: { amp: 0.12, freq: 3 },
});
// layer.tick() now also advances the engine that moves the bee — no hand-rolled motion loop.
bee.remove();

Building your own field visuals

The package re-exports the engine's field samplers — forceAt and netField — so you can drive your own 3D visuals (streamline tubes, vector grids, density volumes) from the live field without a second import. For forage-by-gradient, layer.sampleScalar(x, y) returns the smooth diffused density ∈ [0,1] (enable it with createFieldLayer({ heatmap: true })); its gradient — unlike a nearest-body readout — stays meaningful right at a source.

License

MIT © Zach Shallbetter