Spoke: a browser editor for building 3D spaces for Hubs
Easily create custom 3D environments
At a glance
- What is it?
- Spoke is a web editor that lets you assemble a 3D space for Hubs without external 3D software, drawing on media from Sketchfab and Google Poly and publishing the result to Hubs from the browser. It is derived from the three.js editor, it is a private package whose manifest and repository disagree about the licence, and its last release tag is a production snapshot rather than a version.
- Who is it for?
- Spoke suits editors and community builders who publish to Hubs and want to compose a scene in the browser rather than in a modelling tool, and it also serves as a readable fork of the three.js editor with WebXR in mind. It is the wrong tool if you need a general purpose 3D authoring suite, since the feature set is aimed at Hubs spaces rather than modelling workflows.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 61 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A scene editor that only exists in the browser
Spoke exists to make custom 3D environments for Hubs, and it does so by removing the two usual obstacles. The first is tooling. The README states that no external software or 3D modelling experience is required, because the scenes are built with the Spoke web editor, so the whole authoring loop happens in a browser tab. The second is sourcing content. The Discover feature searches for images, videos and 3D models from around the web without opening a new tab, and it carries media integrations with Sketchfab and Google Poly, which is where the material for a scene comes from. The audience is therefore people who need a space to talk or meet in, not people who need to model a character for a game. The final step is Share, which publishes the content to Hubs immediately so other people can be invited into the space. Three verbs, discover, create, share, and the whole product is the path between them.
Where the code came from: the three.js editor
The credits section names the ancestry, and it matters for anyone assessing the code. Parts of the project are derived from the three.js editor, with thanks to Mr.doob and the three.js contributors. That is the honest origin of the editor, its scene graph, its gizmos and its material handling, and it means a developer reading Spoke is reading something close to a well-known JavaScript 3D editor with Hubs specific parts added. The second credit is more specific. Navigation mesh generation is done via recast.wasm, courtesy of Recast and but0n's RecastCLI wrapper, which is what lets an agent or a visitor walk around the space you built instead of sliding through it. So Spoke is a fork in the meaningful sense: an editor inherited from another project, extended with navigation meshes, with WebXR, with glTF handling, and with the Hubs publishing flow, all inside the same JavaScript codebase.
A private package with a version and a start script
The manifest tells you how the project is meant to be run, and it is explicit about the runtime and the shape of the build. The package name is spoke, the product name is Spoke, the version is 0.8.6, and the entry point for the server is lib/server/index.js, with lib/, dist/ and LICENSE as the published files. The engine requirement is modest:
"engines": {
"node": ">=10"
},The development workflow runs through webpack and cross-env. The start script launches webpack-dev-server in development mode, and there is a start-moz variant that sets IS_MOZ=true, which suggests a separate path for Mozilla based browsers. The most interesting script is run-local-reticulum, which sets NODE_TLS_REJECT_UNAUTHORIZED=0, points ROUTER_BASE_PATH at /spoke, sets BASE_ASSETS_PATH to a local hubs.local address and points HUBS_SERVER and RETICULUM_SERVER at hubs.local:4000 before starting the dev server. In other words, a developer can run the whole stack against a local Hubs instance rather than a hosted one. The environment files for that arrangement are in the tree as .env.defaults, .env.prod and .env.test, and the webpack configuration is the single webpack.config.js at the root.
Linting, tests and the storybook
The quality tooling is a JavaScript project of the older style, and it is complete. A precommit script runs lint-staged, lint runs eslint over ./src through the lint:js script, and lint:css runs stylelint over the styles inside the JavaScript sources. The test script runs two suites at once with concurrently, using the success first and kill others options so the faster side wins, pairing test-all, which is ava with verbose output, against test-server, which starts a webpack-dev-server in test mode serving fixtures from test/fixtures. There are narrower entry points too, unit-tests for ava over test/unit, integration-tests that run the integration folder together with the test server, and update-test-snapshots for refreshing stored expectations. A separate test-ci script runs ava in serial mode and pipes TAP output through tap-xunit into test/reports/ava.xml, which is the shape a continuous integration job needs. Storybook is available for developing and deploying components in isolation, and the repository also carries a .storybook/ directory, a Jenkinsfile, a .circleci/ directory and a .github/ directory, so there is more than one continuous integration path configured. A .babelrc, an .eslintrc.js, a .prettierrc.json and a .stylelintrc sit alongside them, and a .prettierignore and .eslintignore mark the paths that are exempt.
Two licence statements that do not match
Here is the detail to settle before you build anything on top of this. The package manifest declares the licence as MPL-2.0, in the same file as the name and the version. The repository's own licence field, however, is classified as a custom licence that GitHub cannot categorise, and points at the LICENSE file for the terms. The README also says to see the LICENSE file for details, and the file is present at the root of the tree. Since the manifest and the LICENSE file are both present and they are not obviously the same instrument, the file is the one that governs what you may do with the code. MPL-2.0 is a file-level copyleft licence, and the project is derived from the three.js editor, which carries its own MIT terms, so the resulting distribution has more than one layer of attribution and licence obligations. That is a question for your own counsel, not one this article can settle. The manifest also marks the package as private, meaning it is not published to a registry as a consumable library, so redistribution happens through the repository rather than through a package manager.
Version 0.8.6, a dated production tag, and a quiet branch
The version story is a little untidy, and it is worth knowing before you pin anything. The manifest reports version 0.8.6. The only release listed for the repository is prod-2025-12-17, dated 2025-12-17, which is a snapshot tag rather than a semantic version, so there is no tag that lines up with 0.8.6. The last push to the default branch was on 2026-08-23, so the branch has moved since that production snapshot without a corresponding release. For a project whose output is published as a spatial experience, that distinction is not academic: the bundle in the prod tag and the bundle you would build from master are not the same artefact. Other supporting files in the tree give the context of how the project is run, including a CODE_OF_CONDUCT.md, a CONTRIBUTING.md that the README points to for contribution information, a docs/ folder with additional developer documentation, a PROMOTION.md, a REMIXING.md, and a habitat/ directory, which is where the Hubs hosting and configuration material lives. The RetPageOriginDockerfile and the scripts/ directory cover the container side of deployment.
Editorial conclusion
Spoke suits editors and community builders who publish to Hubs and want to compose a scene in the browser rather than in a modelling tool, and it also serves as a readable fork of the three.js editor with WebXR in mind. It is the wrong tool if you need a general purpose 3D authoring suite, since the feature set is aimed at Hubs spaces rather than modelling workflows. Before building on it, read the LICENSE file directly, because the manifest declares MPL-2.0 while the repository records a custom licence that GitHub cannot classify, and check the version, since the manifest says 0.8.6 while the only release tag is a dated production snapshot.
Frequently asked questions
What is Spoke and who is it for?
Spoke is a web editor for creating custom 3D environments for Hubs. It is aimed at people who want to publish a space to Hubs for meetings or events, and it needs no external 3D software or modelling experience.
Where does Spoke get images, videos and 3D models from?
The Discover feature searches for media from around the web without opening a new tab, and it includes media integrations with Sketchfab and Google Poly.
How do you run Spoke locally?
The start script in the package manifest runs webpack-dev-server in development mode, and the manifest requires Node 10 or newer. There is also a run-local-reticulum script that points the dev server at a local Hubs instance on hubs.local:4000, and environment files .env.defaults, .env.prod and .env.test cover the configuration.
Is Spoke derived from an existing project?
Yes. The README states that parts of the project are derived from the three.js editor, and that navigation mesh generation uses recast.wasm, courtesy of Recast and but0n's RecastCLI wrapper.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hubs-foundation-spoke)Was this useful?