# Twine (klembot/twinejs): The Electron and Browser Build of the Nonlinear Story Editor

> Twine is a GUI for creating nonlinear stories, shipped as a browser app and an Electron desktop app for Windows, macOS and Linux. This review covers the source build, the story format split, and where the desktop build can damage your files.

**klembot/twinejs** — Twine, a tool for telling interactive, nonlinear stories

- Repository: https://github.com/klembot/twinejs
- Website: https://twinery.org
- Stars: 2,890 · Forks: 414
- Language: TypeScript
- License: GPL-3.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/klembot-twinejs

## What twinejs is and who actually needs it

Twine is a GUI for creating nonlinear stories. That is the description in package.json, and it is precise: the project is an editor, not a runtime. You author passages on a canvas, draw links between them, and export an HTML file that a story format renders. The README calls this repository a port of Twine to a browser and Electron app, and points to twinery.org for more information.

The people who need it are writers and designers working on branching narrative: interactive fiction, choice-driven games, dialogue trees, teaching material with alternate paths. They want to see the shape of the story, not only the prose. A second group is developers extending the editor, because the repository ships EXTENDING.md and DESIGN_GOALS.md at the top level.

If your goal is a general-purpose game engine with physics, sprites or a scene graph, this is the wrong layer. Twine produces a story graph and a compiled HTML artifact. Everything that happens inside a passage is the story format's job.

## The architecture: a React editor, an Electron shell, and formats kept elsewhere

The dependency list in package.json tells you most of the design. React 16 and react-dom render the editor. CodeMirror 5, through react-codemirror2, is the passage text editor. react-draggable and segseg handle the passage map and its connection geometry. Fuse.js powers fuzzy search, i18next and react-i18next handle localization, and react-router-dom drives routing. State is managed with react-hook-thunk-reducer rather than a larger store library.

The repository is TypeScript, built with Vite (vite.config.mts) and tested with Jest (jest.config.js) plus Playwright (playwright.config.ts, e2e/). Two tsconfig files exist: tsconfig.json for the web target and tsconfig.electron.json for the desktop target. Electron packaging is configured in electron-builder.config.js.

The story formats are the interesting split. The README states that the minified formats under story-formats/ live in separate repositories: Harlowe, Paperthin, Snowman and SugarCube. Twine therefore ships compiled copies rather than owning their source. That keeps the editor independent of any one format's release cycle, but it also means a format bug is fixed upstream, not here, and the version bundled with a Twine release is whatever was vendored at build time.

## Installing twinejs and running the editor locally

Most users never build from source. The README says binary packages are available on the Releases tab for Windows, MacOS and Linux, and notes that community builds exist on other platforms such as the Snap Store or the Arch User Repository, with the warning to only install from sources you trust.

For a source checkout, package.json requires Node 20 or newer and npm 10 or newer. The README gives the install step as a single command at the top level of the directory:

```bash
npm install
```

After that, the development server is started with npm start, which the README describes as serving a development version of Twine locally that updates automatically as you make changes.

```bash
npm start
```

To run the desktop app in development, the README gives a second command, and attaches a warning to it:

```bash
npm run start:electron
```

The README states plainly that running this can damage files in your Twine stories folder and that you should take a backup copy of that folder before proceeding. It also notes that most of the app updates automatically as you work, but that restarting the process is required if you want the app to read story files initially again.

Tests run with npm test, and npm run clean deletes existing files in electron-build/ and dist/.

## Building a release, and the environment variables that decide notarization

Release builds come from npm run build, with finished files under dist/. The README notes that building Windows apps on macOS or Linux requires Wine and makensis, which is a real constraint if your CI runs on Linux and you want a Windows installer.

The build also produces a file named 2.json under dist/ containing information for the autoupdater process, currently posted to https://twinery.org/latestversion/2.json. That is the update channel the desktop app consults, so anyone forking the project has to decide whether to keep pointing at that URL or host their own.

macOS notarization is driven by four environment variables, and the README is explicit that if any of them are unset, the build process skips notarizing, which means users will need to right-click the application and open it manually. The variables are APPLE_APP_ID, APPLE_ID, APPLE_ID_PASSWORD and APPLE_TEAM_ID.

The README adds that the full Xcode app must be installed to notarize, not just the Xcode command line tools. Documentation work is separate again: the README says building the docs requires mdbook, which is not a Node-based project and must be installed from its website or an operating system package manager.

## Where Twine stops being the right tool

The clearest limitation is the one the README states itself: the development Electron build can damage files in your Twine stories folder. That is not a caveat about an exotic flag. It is a warning attached to the standard desktop development command, and it means anyone hacking on the Electron side should treat their story library as disposable and keep a copy elsewhere.

The second limit is scope. Twine edits and exports. Rendering, macros, save systems and styling belong to Harlowe, Snowman, SugarCube or Paperthin, each maintained in its own repository. If you need to change how a story behaves at runtime, you are reading a different codebase.

The third is deployment shape. This is a desktop and browser editor. The related searches include "Twine Android", but nothing in the README or package.json describes a mobile build, and the packaging configuration targets Windows, macOS and Linux. Treat a mobile Twine app as something the repository does not provide.

Finally, collaboration. Nothing here describes a hosted multi-user mode or accounts. The related search "Twine login" has no counterpart in the repository: stories are local files. Teams that need simultaneous editing are looking at the wrong project.

## Twine against a general-purpose engine like Godot

The natural comparison is not another Twine fork but an engine such as Godot. Godot gives you a scene tree, a scripting language, physics, animation and an export pipeline to many platforms. Twine gives you a passage graph and an HTML file.

The difference in approach matters for what you can change later. In Godot, the branching logic is code you write and own. In Twine, the branching structure is data the editor manipulates, and the behaviour inside a passage is delegated to a story format that is versioned separately. That delegation is why a Twine project can be handed to a writer who does not program, and it is also why a Twine project cannot easily grow into something with real-time movement or a 3D scene.

There is a middle path worth naming: Twine exports HTML, and that HTML can be embedded or extended by hand. The project's own EXTENDING.md exists for people who want to push past the editor, but that is a different activity from authoring, and it puts you back in the position of maintaining code.

## Licence, upgrade cost and what the repository commits to

The licence is GPL-3.0, stated in package.json and in the LICENSE file at the top level. That matters if you plan to embed the editor in a product, because the GPL's copyleft obligations attach to distribution. This is a description of what the repository declares, not legal advice; if you intend to ship a modified Twine, have a lawyer read the licence rather than an article.

Upgrade cost is low for users and moderate for builders. Users get binaries from the Releases tab, and the desktop app has an autoupdater fed by 2.json. Builders inherit a large dependency tree pinned in package-lock.json, with React 16 and CodeMirror 5 among the older entries, plus a separate Electron toolchain and, for Windows artifacts on non-Windows hosts, Wine and makensis.

The maintenance picture: the repository is not archived, and the last push was on 2026-09-05. The most recent release listed is 2.12.0 from 2026-04-10, following 2.11.1 and 2.11.0 in November 2025. Releases are not frequent, which is normal for a mature editor and worth knowing before you file an issue expecting a quick patch.

## Conclusion

Adopt Twine if you write branching narrative and want a visual passage graph plus plain-text export rather than a game engine. Do not adopt it if you need a hosted collaborative editor, a mobile app, or a runtime that renders stories itself: Twine edits and publishes, the story formats do the rendering. Before committing to a source build, verify that Node 20 and npm 10 are available, that npm install completes, and that npm start serves the editor locally. If you work on the Electron app, copy your Twine stories folder first, because the README warns that running the development Electron build can damage files there.

## FAQ

### Is Twine free to use?

Yes. The project is licensed GPL-3.0, as stated in package.json and the LICENSE file, and binary packages for Windows, MacOS and Linux are available on the Releases tab at no stated cost.

### Does Twine require coding?

The editor itself is a visual tool for creating passages and links, so writing prose and connecting passages does not require code. Anything beyond that depends on the story format you choose, since Harlowe, Snowman, SugarCube and Paperthin are maintained in separate repositories and define their own syntax.

### Where can I play Twine games?

Nothing in the README or package.json describes a hosting service or game directory. Twine exports stories as HTML files, so where a story is playable depends on where its author published that file.

### Does Twine use AI?

The dependency list in package.json contains no AI or model-related packages; it lists React, CodeMirror, Fuse.js for fuzzy search, and similar UI and utility libraries. The README describes the project as a port of Twine to a browser and Electron app.

## Sources

- [klembot/twinejs on GitHub](https://github.com/klembot/twinejs)
- [License: GPL-3.0](https://github.com/klembot/twinejs/blob/develop/LICENSE)
- [Project website](https://twinery.org)
- [README](https://github.com/klembot/twinejs/blob/develop/README.md)
- [Releases](https://github.com/klembot/twinejs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/klembot-twinejs
