Skip to main content

Project Structure

MistWarp is a multi-repository workspace. Each package is its own Git repository. scratch-gui builds on its own, and you only clone the other packages next to it when you want to change them. The parent directory itself is not a repository.

mistwarp/
├── scratch-gui/ # editor + community site (one Vite build)
├── scratch-vm/ # runtime and compiler; blocks are defined here
├── scratch-blocks/ # the block editor (Blockly fork)
├── scratch-render/ # WebGL stage renderer
├── scratch-paint/ # costume and backdrop editor
├── scratch-audio/ # Web Audio playback
├── packager/ # standalone project packager
├── unpackager/ # inverse of the packager
├── mistwarp-api/ # community platform backend
├── turbowarp-desktop/ # desktop wrapper for the editor
└── docs/ # this documentation site (Docusaurus)

The packages​

Scratch is split into packages that each implement one part of the app. MistWarp forks several of them.

  • scratch-gui implements most of the interface (menu bar, sprite list, tabs), wires everything together, and is where addons live. It is a set of React components plus a Redux store. Uniquely to MistWarp, the same build also ships the community site.
  • scratch-vm runs projects. It holds the block definitions (src/blocks/scratch3_*.js), the extensions (src/extensions/), and the compiler that turns blocks into JavaScript (src/compiler/).
  • scratch-render draws the stage: sprites, pen, text bubbles, and collision blocks like "touching". Note that overlays such as variable monitors are drawn by scratch-gui, not scratch-render.
  • scratch-blocks is the block palette and workspace, a fork of Google Blockly. Edits under its core/ directory require a Closure recompile (see Building and Running).
  • scratch-paint is the costume and backdrop editor.
  • scratch-audio handles sound playback.

Two more support packages are pulled in as npm dependencies rather than local checkouts, but you will see them referenced: scratch-parser (validates sb2/sb3 files) and @turbowarp/scratch-storage (a fetch abstraction for downloading assets).

Inside scratch-gui​

scratch-gui is where most editor work happens. The important source directories:

scratch-gui/src/
├── components/ # presentation React components (foo/foo.jsx + foo.css)
├── containers/ # Redux-connected wrappers around components
├── reducers/ # Redux reducers, one file per state slice
├── lib/ # the shared service layer, HOCs, themes, persistence
├── addons/ # the addon system (settings store, window system, addons)
├── playground/ # page entry points (editor, player, community, embed, ...)
└── community/ # the community single-page app
  • components/ holds pure UI. Each component is a folder with a .jsx and a matching CSS module.
  • containers/ connects components to the Redux store. See The Container Pattern.
  • reducers/ is the Redux state. See State Management.
  • lib/ is the largest directory: higher-order components under lib/components/, the theme engine under lib/themes/, project persistence under lib/persistence/, plus the MistWarp service layers lib/community/ and lib/rotur/ used by both the editor and the community site.
  • addons/ is the addon framework, ported from Scratch Addons. See The Addons System.

The build produces several pages, whose entry points live in src/playground/: editor, player, community, fullscreen, embed, addon-settings, and credits. vite.config.mjs maps them to HTML files and URLs: /editor serves the editor, /embed.html the embed player, /addons the addon settings, and every other extensionless path, such as /explore or /p/<slug>, the community app. The community page is only included when MW_COMMUNITY=true.

scratch-gui depends on the engine forks as tarballs of a specific commit on GitHub, so a fresh clone installs them like any other dependency. To work on a fork, clone it next to scratch-gui and link it:

pnpm run link

This replaces the installed copy in node_modules with a symlink to each sibling checkout that exists, so changes to, for example, scratch-vm show up in the editor without publishing anything. pnpm run unlink or another pnpm install restores the pinned copies. pnpm run deps:sync moves the pins to each fork's latest develop. See Building and Running.

The MistWarp-only services​

Two pieces are not Scratch or TurboWarp code at all:

  • mistwarp-api is the community backend (accounts, projects, comments, notifications, settings sync). It is written in OSL and stores data as flat JSON, using Cloudflare R2 for project blobs. The frontend talks to it at https://api.mistwarp.org/v1.
  • Identity and social features run through Rotur. Signing in exchanges a Rotur token for a MistWarp session; social features (posts, likes, follows) go to https://api.rotur.dev.

You do not need either running to work on the editor itself. They matter when you are working on the community site.

See also​