DEV Community

Fernando Paladini
Fernando Paladini

Posted on

Build an Offline Spatial Reasoning Trainer with OpenFold

Build an Offline Spatial Reasoning Trainer with OpenFold

TL;DR

If you want to practice mental rotation without uploading attempts to a hosted service, OpenFold is an interesting open-source example. It generates cube-net folding problems locally, renders them with Three.js, stores practice telemetry in IndexedDB, and exposes a React web app. This tutorial checks out the current main branch, builds the app, runs its test suites, and explains where its offline boundary comes from.

The problem: spatial practice is often difficult to inspect

Spatial reasoning practice needs more than a collection of static images. A useful exercise should generate new problems, distinguish equivalent cube rotations from genuinely different answers, give feedback, and let you review progress.

That creates an engineering problem: the generator, 3D view, answer validation, and local history must agree. If they use different geometry rules, a visual answer can look correct while the checker rejects it. If the app sends attempts to a server, the learner also loses a simple privacy boundary.

OpenFold addresses that problem as a local-first educational simulator. Its README describes procedural cube-net exercises, a TypeScript core, a Three.js renderer, a React web app, IndexedDB telemetry, and a Rust desktop shell. The repository is public and MIT licensed.

This walkthrough uses the repository's current main branch. The README and changelog describe a v1.0.0 scope, but the v1.0.0 Git ref was not resolvable during verification, so do not treat that label as a downloadable release here.

Prerequisites

You need:

  • Node.js 20 or newer.
  • pnpm 10 or newer.
  • Git.
  • A modern browser if you want to run the web app.

The Node and pnpm requirements come from the repository README and root package metadata. The desktop wrapper additionally requires a Rust toolchain, but it is not needed for the web build.

1. Check out and install the project

Clone the repository and install its pinned dependency graph:

git clone https://github.com/paladini/OpenFold.git
cd OpenFold
pnpm install
Enter fullscreen mode Exit fullscreen mode

The workspace contains three relevant packages: @openfold/core, @openfold/render, and @openfold/web. The core and render packages are private workspace packages rather than published npm packages, so a source checkout is the normal path for this tutorial.

2. Build the browser application

Run the workspace build:

pnpm -w build
Enter fullscreen mode Exit fullscreen mode

This compiles the TypeScript packages and creates the Vite production bundle for the web app. To try the application locally, start the documented development server:

pnpm --filter @openfold/web dev
Enter fullscreen mode Exit fullscreen mode

Open the local URL printed by Vite. The browser version does not require an account or an API key. The app's storage layer uses IndexedDB for local sessions and attempts, and the desktop bridge is a no-op in a plain browser.

3. Understand the generated problem

The most useful boundary in OpenFold is the core package. Its public generateProblem function accepts a seed and either generation parameters or a difficulty preset. Internally, the current implementation:

  1. validates the seed and resolves the preset;
  2. creates a deterministic random-number generator;
  3. generates a cube net;
  4. folds the net into a cube state;
  5. creates non-equivalent distractors;
  6. shuffles the answer pool; and
  7. returns the correct answer index plus metadata for the distractors.

That sequence matters because the renderer and the answer checker can share the same folded representation. The code also retries generation when a distractor set cannot be built, then throws a GenerationError after its bounded redraw limit. A bounded failure is easier to test and diagnose than an infinite retry loop.

The current core API is documented directly in packages/core/src/index.ts. The implementation exports helpers for canonicalization, equivalence checks, presets, net generation, and seeded random numbers, which makes the geometry rules testable without opening a browser.

4. Verify the important behavior

Run the checks used by the repository's workspace scripts:

pnpm -w typecheck
pnpm -w lint
pnpm -w test
Enter fullscreen mode Exit fullscreen mode

In my source checkout of the current main branch, the checks completed successfully. The core package reported 112 passing tests, the render package reported 76, and the web package reported 264.

The tests cover more than whether functions return objects. The core suite checks that alternatives are pairwise non-equivalent, that the correct answer is not positionally biased across seeded samples, and that generated problems remain valid across difficulty presets. The render suite compares its folded state with the core result. The web suite exercises rounds, keyboard-only play, local persistence, dashboards, and training explanations.

The repository also defines a Playwright configuration for browser tests and an accessibility audit. Those checks are separate from the fast workspace test command and require the browser test setup, so a green unit and integration test run should not be described as a complete cross-browser or WCAG certification.

Why the offline boundary is useful

OpenFold's local-first design is concrete rather than just a marketing label:

  • The web app persists attempts through IndexedDB.
  • The README describes no network calls for problem generation and local training data.
  • There are no user accounts or cloud-sync features in the documented v1 scope.
  • The desktop bridge exists for the native shell, while a browser can run without it.

This gives a learner a clear operational model: install the code, open the app, practice, and keep the resulting history in the local browser profile. The tradeoff is equally important. Local storage is not a backup service. Clearing browser data, changing profiles, or uninstalling a portable desktop build can make history unavailable unless you export it first.

Failure modes and limitations

The project documentation lists several limits that should shape your expectations:

  • The exercise type is cube-net folding. It is not a general spatial-ability trainer.
  • Difficulty uses deterministic tiers rather than adaptive IRT.
  • The web experience is English-only at the documented scope.
  • The desktop distribution is portable rather than a signed native installer.
  • Cross-engine behavior on macOS and Linux webviews still needs manual verification according to the release notes.
  • The production web bundle emits a large-chunk warning during Vite build. That is a packaging optimization issue, not evidence that the build failed.

The security boundary is also narrow. Offline generation and local IndexedDB storage reduce the need to send practice data elsewhere, but they do not protect a compromised machine or browser profile. The repository's own release checklist calls for reviewing credentials, path traversal, XSS, dependency licenses, and audit results. Those are review tasks, not guarantees supplied by the README.

FAQ

Is OpenFold available as an npm package?

The workspace packages are marked private in their package metadata. Use the repository checkout and pnpm workspace commands for development.

Do I need Rust to try the app?

No. Rust is required for the desktop wrapper. The React and Vite web app can be built and served with Node.js and pnpm.

Does a seed make every visual result identical everywhere?

The core generator is seeded and tested for deterministic geometry, but the changelog distinguishes web verification from manual verification of other webview engines. Treat cross-platform visual equivalence as a claim to test on the target platform.

Is local storage the same as private storage?

No. It means the application is designed to keep data on the local device. Anyone or any software with access to that browser profile or machine may still access it.

Takeaway

OpenFold is a compact case study in making an educational simulator inspectable: deterministic generation, shared geometry rules, local telemetry, and tests that connect the core to the UI. Start with the web workspace, run the typecheck, lint, build, and test commands, then inspect the core package before changing the visual layer.

The project describes a v1.0.0 scope, but its release tag was not verifiable in this run. If you use OpenFold, pin the commit you tested and keep that distinction visible in your own notes.

What would you improve first: adaptive difficulty, additional spatial exercise types, or a more portable desktop release process?

AI assistance disclosure

This tutorial was researched and edited with AI assistance. Repository facts, commands, source links, and verification results were checked against the public OpenFold repository and a local source checkout before publication.

Top comments (0)