CLI tool
patorjk/JavaScript-Snake avatar
patorjk/JavaScript-Snake

JavaScript Snake: a decade-old DOM game that still runs

The game of Snake written in JavaScript.

597 stars679 forksJavaScriptMIT

At a glance

What is it?
JavaScript-Snake is a DOM based game of Snake written in plain JavaScript with no external libraries, which means it still works after more than ten years. It comes with a CodeSandbox you can edit live, a Parcel build, and an AI mode that hands the snake's decisions to a callback of your own.
Who is it for?
JavaScript-Snake suits a developer who wants a small, self contained JavaScript game to read, fork or embed in a page, and who would rather not pull a game framework into a project for the sake of a snake. It is a poor fit as a foundation for a real game project, because there is no test suite, the build tooling is a single Parcel configuration, and the code carries a decade of accumulated assumptions about the DOM.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 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 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Plain DOM, no libraries, over ten years old

JavaScript-Snake is a DOM based game of Snake written in JavaScript over a decade ago, and the author says it was made to have sort of a nostalgic feel to it. The original game lives at patorjk.com/games/snake, and the repository is the source of it.

The detail that matters for anyone considering using it is the absence of dependencies. The readme is explicit: the rest of the code does not use any external libraries, and the game still works the same after over a decade. The author contrasts that with the churn in the JavaScript world, which is a pointed remark from someone who watched that world change several times over and chose not to follow it.

That has a practical consequence. There is no framework to keep current, no build step you must run to make the game work, and no transitive dependency that can break under you. The library is the code in `src`, and the browser is the runtime. The repository top level is small to match: a `src` directory, `package.json`, `package-lock.json`, a `.parcelrc`, an `.all-contributorsrc` and the licence file.

The licence is MIT, the default branch is `main`, and there are no GitHub releases, so the repository is a single snapshot rather than a versioned stream.

Dropping a board into any container

The readme says the index.html file should give an idea of how to use the code, and then shows how to initialize the game into any div on a page:

javascript
    const mySnakeBoard = new SNAKE.Board( {
                                            boardContainer: "game-area",
                                            fullScreen: false,
                                            width: 580,
                                            height:400
                                        });

That is the whole API surface for the common case. The container is given as an element id rather than as a DOM node, the board can be told to run full screen or not, and the width and height are set explicitly at 580 by 400 in the example.

The `fullScreen` option is the one that changes the shape of the integration, because a full screen board takes over the viewport rather than sitting inside a layout, which is a different thing to drop into an existing page. The dimensions, meanwhile, are what the game draws into, and since the rendering is DOM based rather than canvas based, the sizes determine how much layout the page has to give up.

A project that wants to embed the game therefore needs three things: the source, a container element with the id it names, and a decision about whether the board is inline or full screen. The board is constructed with a single `new` call and no further configuration is documented, which is what a decade-old example project looks like.

Parcel is the whole build system

Running it locally is a Parcel command, and the readme gives the recipe: clone the project, then at the command line run `npx parcel src/index.html`, which serves the game on http://localhost:1234.

code
npx parcel src/index.html

The package manifest is consistent with that. The dev dependencies are `parcel` at ^2.13.3 and `parcel-reporter-static-files-copy` at ^1.5.3, and the scripts are `start`, which runs `parcel src/index.html --open`, and `build`, which runs `parcel build src/index.html`. There is also a `staticFiles` configuration that copies the `src/css` directory to `css` in the output, which is what the static files reporter plugin is there for.

So the build exists, but it is a packaging convenience rather than a compile step. Nothing is transpiled and nothing is bundled into a framework runtime; Parcel is serving the files and copying the styles. That is why the game keeps working: nothing in the pipeline can rot, because there is almost no pipeline.

The third script is the default stub that every npm package starts with. The test script runs `echo "Error: no test specified" && exit 1`, which means running the test command fails on purpose. There is no test suite in this repository, and for a project that is a single self-contained game that is a defensible choice rather than an omission, but it does mean a fork has to start its own testing if it grows.

The AI mode is a callback, not an algorithm

If you want the snake driven by an algorithm, the readme points to the `ai-init.js` and `ai-example` files. The integration is deliberately thin: you run `params.startAIGame()` when initializing, and you pass in a `moveSnakeWithAI` method which is run before the snake does each move.

The callback receives the grid, the snake head, the current direction, whether this is the first move of the game, and a `setDirection` function, and it returns the direction to take. The example implementation in the readme is a look-up table of a hamiltonian cycle:

javascript
  moveSnakeWithAI: ({
                      grid,
                      snakeHead,
                      currentDirection,
                      isFirstGameMove,
                      setDirection,
                    }) => {

The direction encoding in that example is a small number, 0 for up, 1 for right, 2 for down and 3 for left, drawn as a compass in the comment. The grid is indexed by row and column, and the callback looks up the next cell in its cycle and calls `setDirection` with the value found there.

The author is careful about the accuracy of the example, noting in a comment that this is not a real hamiltonian cycle and that it misses some values, and that it is included as an example of a look-up type table you could do. That is a good thing to know before you copy it: the shape of the approach is the lesson, not the table.

Because the hook runs before each move and the game state is handed to it, you can write anything that returns a direction, from a wall-following rule to a pathfinding search.

Two rough edges the readme admits to

The readme is honest about the two things that annoy people trying the project, and both are worth knowing before you file an issue.

The first is styling in CodeSandbox. A note dated 2025 says the CSS inside the sandbox is not working properly, while in the game itself it works fine. Since the live sandbox is the most convenient way to try the project without cloning it, that means the first impression in the browser is a partly unstyled board. The original game at patorjk.com/games/snake is the one where the styles are right.

The second is a first load problem: sometimes the game frame does not load correctly, and you need to press the refresh icon above the display panel to get the game to show. That is a symptom of the game frame being sized or positioned before the styles have applied, and the manual refresh is the workaround.

Both of these are the kind of detail that only appears in a project that has been running for years in the open, and mentioning them in the readme rather than in an issue thread is a point in the project's favour. If you are embedding the game in your own page, you will hit the same class of problem, and the fix is in your own CSS rather than in the game.

Documentation comments from another era

One thing that will puzzle you when you open the source is the comment format. The readme explains that the comments within the source code are formatted a little strange because the author was playing around with YUI Doc, which generates documentation from code, and calls the churn in the JavaScript world a sore point.

It is a small archaeological detail with a real effect on a reader. Inline documentation that was generated for a tool from that period does not read the way a modern hand-written comment does, and someone new to the project will spend a moment working out which comments are prose and which are artefacts of the generator. The source itself is fine, and the comments still say useful things about the parameters.

The other thing the readme notes is that the code does not use any external libraries, and that the game still works the same after over a decade. That combination, a decade-old generator's comment style next to dependency-free code that still runs, is a fair summary of what this repository is: a small piece of web history that has aged better than the tools around it.

The contributors are listed with the standard all-contributors table, driven by the `.all-contributorsrc` file, and the readme thanks them by name.

Editorial conclusion

JavaScript-Snake suits a developer who wants a small, self contained JavaScript game to read, fork or embed in a page, and who would rather not pull a game framework into a project for the sake of a snake. It is a poor fit as a foundation for a real game project, because there is no test suite, the build tooling is a single Parcel configuration, and the code carries a decade of accumulated assumptions about the DOM. Before you base anything on it, read `src/index.html` to see how the board is wired, and check the CSS behaviour in CodeSandbox, where the readme says the styles do not render correctly even though they do in the game itself.

Frequently asked questions

How do I add the JavaScript-Snake game to a webpage?

Construct a board against a container element id, for example `new SNAKE.Board({ boardContainer: "game-area", fullScreen: false, width: 580, height: 400 })`. The index.html file in the repository shows the full setup.

How do I run JavaScript-Snake locally?

Clone the repository and run `npx parcel src/index.html` at the command line, which serves the game on http://localhost:1234. The package scripts also include `start`, which runs the same command with the browser opened, and `build` for a production build.

Does JavaScript-Snake need any libraries?

No. The readme states that the code does not use any external libraries, and that the game still works the same after over a decade. Parcel is used to serve and build the files, not to supply a runtime dependency.

How do I let an AI play the snake?

Look at the `ai-init.js` and `ai-example` files. You call `params.startAIGame()` when initializing and pass a `moveSnakeWithAI` method that receives the grid, snake head, current direction and a `setDirection` callback, and is run before each move.

Is the CodeSandbox version of JavaScript-Snake styled correctly?

Not always. A note in the readme from 2025 says the CSS inside the sandbox is not working properly, while in the game itself it works fine. There is also a note that on first load the game frame may not load correctly and you need to press the refresh icon above the display panel.

Official sources

  1. Issues
  2. License: MIT
  3. patorjk/JavaScript-Snake on GitHub
  4. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/patorjk-javascript-snake.svg)](https://hysenlabs.com/projects/patorjk-javascript-snake)

Was this useful?