# openScope: an HTML5 air traffic control simulator built on canvas and Gulp

> A JavaScript air traffic control simulator that runs in the browser, with airport data as the main content, a local Node build pipeline pinned to old engine versions, and a licence file the repository metadata cannot categorise.

**openscope/openscope** — openScope Air Traffic Control Simulator

- Repository: https://github.com/openscope/openscope
- Website: http://www.openscope.io
- Stars: 839 · Forks: 225
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/openscope-openscope

## Air traffic control as a canvas game with data files at its core

openScope is described in its package.json as "An ATC simulator in HTML5", and the repository topics name canvas, flight simulation and aviation rather than web tooling. The playable product is not a service: the README points at http://www.openscope.io to start playing, and the rest of the repository is the source for that application plus the tooling that builds it.

The distinguishing content is the airport data. The README directs newcomers to the tutorial, to a command reference at documentation/commands.md, and to an airport guide at documentation/airport-guides/airport-guide-directory.md. Contributors who do not write JavaScript are pointed at the Airport Format Documentation and the Airport File Standards Documentation, which shows where most of the project's work actually sits: describing runways, approaches and procedures in structured files rather than changing engine code.

The intended audience is therefore two groups. One is the player or trainee who wants to work a radar scope in a browser tab. The other is the community contributor who adds or corrects an airport, and who can do so without touching application logic.

## The build is Gulp driven and outputs a plain Node server

package.json describes a small toolchain with a clear division of duties. The build scripts call Gulp: `npm run build` maps to `gulp build --prod`, `npm run build:dev` maps to `gulp build`, and `npm run gulp` simply calls `gulp build` again. The Gulpfile.js sits at the top level of the repository, next to .babelrc and .eslintrc, which tells you the client code is transpiled through Babel and linted with ESLint before it reaches the browser.

The server side is not a framework application. The start script is `node public/assets/scripts/server/index.js`, a script inside the built asset tree, and the `server` script is just an alias for `npm run start`. The build therefore has to run before the server can serve anything, which is why the quick start orders `npm run build` ahead of `npm run start`.

The server listens on a fixed port. The README shows the expected terminal output after starting it:

```bash
> node ./public/assets/scripts/server/index.js

Listening on PORT 3003
```

Port 3003 is hard coded in that message rather than taken from an environment variable, so running a second copy locally means editing configuration rather than passing a flag.

## Cloning and building on your own machine

The developer quick start asks for two prerequisites, Git and Node, and then says installation directions for those are out of scope because they have been written about too often already. From a terminal, or GitBash on Windows, the sequence is five commands:

```bash
git clone https://github.com/openscope/openscope.git
cd openscope
npm install
npm run build
npm run start
```

The `npm install` step reads package-lock.json and .npmrc at the repository root. What you should see afterwards is the server message quoted above, on port 3003. If you do not see it, the README points you to the project Slack for troubleshooting rather than offering a checklist.

Before you try, note the engines field in package.json: `node` is `11.3.0` and `npm` is `6.4.0`. Those are the versions the project declares for itself. On a machine with a current Node and npm release, the install may still work, but the declared floor is nearly six years behind what package managers now ship, and the mismatch surfaces as install or build failures rather than as a warning.

## Tests, linting and coverage run as separate npm scripts

The scripts block in package.json exposes the quality tooling without folding it into the build. `npm test` runs `nyc ava --concurrency=5`, so AVA is the test runner and nyc produces the coverage data. The posttest hook then calls `npm run report`, which writes coverage in cobertura and lcov formats. The `coveralls` script pipes a text lcov report into Coveralls, and the repository carries a coverage badge pointing at the develop branch.

The AVA configuration points the runner at the spec files under the test directory and excludes mocks, fixtures and test helpers from the source list. Its require array loads @babel/register plus three helper files from test/testHelpers, covering global properties, local storage and browser environment setup. That last entry explains the shape of the project: the client is a browser application, so the test harness has to synthesise a browser environment rather than run against a real one.

Two more scripts are worth noting for contributors. `npm run lint` runs ESLint over the client scripts, and `npm run validator` runs `validator -a`, which is the airport data validator referenced by the airport file standards documentation. Data quality is checked by a dedicated command, not just by the unit tests.

## Branching is GitFlow and contributions come through the organization

The contributing section makes an unusual request of contributors. The project does not use forks. Instead, contributors are added to the openScope organization so that branches stay local to the organization and pull request testing integrations keep working. The README asks people who want to contribute to message Erik Quinn or NateGeslin on Slack to be added.

Branching follows the GitFlow Branching Model, and the README states that contributors are expected to use branch names based on that methodology, with help available if the naming is unclear. The default branch of the repository is develop, and the coverage badge and status badges reference develop and master, so the release branch layout follows the same model.

For an outside contributor this is the practical friction point in the whole project. The usual open source path of fork, branch, pull request does not apply here, and a first-time contributor cannot open a pull request from a personal fork without first being added as an organization member.

## The licence file and the metadata field do not agree

The README links an MIT License at LICENSE.md, the badge in the README reads MIT, and package.json sets `"license": "MIT"`. The licence classification carried by the repository listing is not one GitHub can categorise, which points at a custom licence file rather than a stock one. Anyone deploying openScope inside an organisation that tracks licence identifiers automatically should open LICENSE.md and read it, rather than trusting either the badge or the package.json field.

The topic of what the game sends over the network is documented separately. The privacy disclosures section states that Google Analytics is used to gather data about how the app is used, with details in documentation/event-tracking.md. For a simulator that people use to practise procedures, that is a detail worth knowing before deploying it on a shared network.

The repository also ships static.json and app.json at the top level, which are the usual deployment descriptors for a Node app on a platform such as Heroku. The exact host is not named in the documentation shown here, so treat those two files as a hint about deployment shape rather than a guarantee.

## Tags stopped in 2022 while the repository kept moving

The recent releases are v6.28.0 dated 2022-07-03, v6.27.0 dated 2022-03-18 and v6.26.0 dated 2021-12-01. The version in package.json is `6.29.0-BETA`, so the current tree sits one version past the newest tag and has not been cut as a release. The repository is not archived, and the last push was on 2026-09-10, so commits have continued well after the last tagged build.

That gap has a concrete effect for users. The public site at http://www.openscope.io is what most people actually play, and the README badges point at a current release on the releases page, which by the tag list means v6.28.0. Anyone who clones and builds gets the develop tree with the beta version, not the tagged release, and there is no upgrade path described in the documentation because there is no released 6.29.0 to upgrade to.

The upgrade cost for a fork therefore depends on which branch you track: the tag for a stable snapshot, the default branch for work in progress. The CHANGELOG.md at the repository root is the place to compare the two.

## Conclusion

Use openScope if you want to practise or teach radar vector control in the browser or want to contribute airport files, and expect to run its own Gulp build rather than a packaged application. Do not pick it if you need a maintained release train, a current Node toolchain, or a simulator with professional procedural fidelity, since the newest tagged release is v6.28.0 from 2022-07-03 while package.json still reads 6.29.0-BETA. Before your first run, check that LICENSE.md matches what your organisation expects, since the repository licence classification does not match the MIT licence named in the README and package.json.

## FAQ

### How do I set up openScope locally?

Clone the repository, then run `npm install`, `npm run build` and `npm run start` from the project directory. The server script prints `Listening on PORT 3003` when it is up.

### Which Node version does openScope expect?

The engines field in package.json declares `node` as `11.3.0` and `npm` as `6.4.0`. The README lists Git and Node as the only prerequisites and leaves their installation to the reader.

### What licence does openScope use?

The README links an MIT License at LICENSE.md and package.json sets `"license": "MIT"`, while the repository licence classification is one GitHub cannot categorise. Read LICENSE.md directly before redistributing the code.

### How do I contribute an airport to openScope?

The project does not use forks. The README asks contributors to message Erik Quinn or Nate Geslin on Slack so they can be added to the openScope organization, and points new airport contributors at the Airport Format Documentation and the Airport File Standards Documentation.

### Does openScope collect usage data?

Yes. The privacy disclosures section states that Google Analytics is used to gather data about how the app is used, with details in documentation/event-tracking.md.

## Sources

- [Issues](https://github.com/openscope/openscope/issues)
- [openscope/openscope on GitHub](https://github.com/openscope/openscope)
- [Project website](http://www.openscope.io)
- [README](https://github.com/openscope/openscope/blob/develop/README.md)
- [Releases](https://github.com/openscope/openscope/releases)

---

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