Maintenance

October 10, 2025 · View on GitHub

Project Logo

Snake Game

A modern implementation of the classic Snake game using vanilla JavaScript with ES6 modules, featuring a clean architecture and automated build system.

Features

  • Modern JavaScript: ES6 classes, arrow functions, and modules
  • Clean Architecture: Separated concerns (Game, Snake, Renderer)
  • Automated Build: Gulp-based build system with minification
  • Live Reload: BrowserSync for instant feedback during development
  • Responsive Design: Adapts to different screen sizes
  • Progressive Difficulty: Speed increases as you score
  • Intuitive Controls: Keyboard controls with pause/resume functionality

Project Structure

snake_game/
├── src/                    # Source files
│   ├── css/               # Stylesheets
│   │   └── style.css
│   ├── js/                # JavaScript modules
│   │   ├── Game.js        # Main game logic
│   │   ├── Snake.js       # Snake class
│   │   ├── Renderer.js    # Rendering engine
│   │   ├── AudioManager.js # Audio management
│   │   └── main.js        # Entry point
│   ├── assets/            # Static assets
│   └── index.html         # HTML template
├── docker/                # Docker configuration
│   ├── Dockerfile         # Production image
│   ├── Dockerfile.dev     # Development image
│   └── nginx.conf         # Nginx configuration
├── tests/                 # Test files
├── dist/                  # Built files (generated)
├── docker-compose.yml     # Docker Compose configuration
├── gulpfile.js           # Build configuration
├── Makefile              # Build and Docker commands
└── package.json          # Dependencies

Getting Started

Prerequisites

  • Node.js (v18 or higher)
  • npm
  • Docker & Docker Compose (for containerized development)

Installation

Option 1: Local Development

  1. Clone the repository:
git clone https://github.com/jonathanbrenman/snake-game.git
cd snake-game
  1. Install dependencies:
make install
# or
npm install

If you are running installs in an environment where package lifecycle scripts may start services (for example CI or a workspace with project scripts), install dependencies without running package scripts:

npm install --ignore-scripts

Development

Option 1: Local Development

Start the development server with live reload:

make serve
# or
npm run serve

The game will be available at http://localhost:3000

Use the convenient Makefile commands for Docker management:

# Start development environment with hot reloading
make docker-up

# View logs in real-time
make docker-logs

# Stop development environment
make docker-down

# Clean Docker resources (containers, volumes, images)
make docker-clean

Or use docker-compose directly:

# Start development environment
docker-compose up -d

# Stop development environment
docker-compose down

The development environment includes:

  • Hot Reloading: Changes to source files are automatically reflected
  • Volume Mounting: Local src/ directory is mounted for live editing
  • BrowserSync: Automatic browser refresh on file changes
  • Port 3000: Accessible at http://localhost:3000

Production Build & Testing

Build and test the production Docker image:

# Build production Docker image
make docker-build

# Build and run production container (port 8080)
make docker-prod

Production environment features:

  • Optimized Build: Minified and compressed assets
  • Nginx: High-performance static file serving
  • Security Headers: Production-ready security configuration
  • Port 8080: Accessible at http://localhost:8080
  • Multi-stage Build: Efficient Docker image with minimal attack surface

Docker Architecture

The project includes a comprehensive Docker setup for both development and production:

Development Environment (docker-compose.yml)

  • Base Image: Node.js 18 Alpine
  • Hot Reloading: BrowserSync with file watching
  • Volume Mounting: Live code editing without rebuilds
  • Development Tools: Full development dependencies included
  • Port: 3000 (with automatic browser refresh)

Production Environment (docker/Dockerfile)

  • Multi-stage Build: Separate build and runtime stages
  • Runtime: Nginx Alpine for optimal performance
  • Security: Non-root user execution
  • Optimization: Minified assets and compressed delivery
  • Health Checks: Built-in container health monitoring
  • Port: 8080

Docker Management

All Docker operations are available through the Makefile:

# Development workflow
make docker-up    # Start development environment
make docker-logs  # Monitor real-time logs
make docker-down  # Stop containers

# Production workflow  
make docker-build # Build optimized production image
make docker-prod  # Run production container

# Maintenance
make docker-clean # Remove all Docker resources

Testing

Run the comprehensive test suite with Jest:

# Run all tests with coverage report
make test

# Run tests in watch mode for development
make test-watch

The test suite includes:

  • Unit Tests: Individual component testing
  • Coverage Reports: Generated under coverage/ directory
  • Audio Testing: Mocked AudioContext for reliable testing
  • Game Logic: Snake movement, collision detection, scoring
  • Rendering: Canvas operations and UI interactions

For CI/CD environments, tests run with --runInBand to avoid parallel runner issues.

Code Quality & Linting

Maintain code quality with comprehensive linting:

# Run all linters (JavaScript, CSS, HTML)
make lint

# Run specific linters
make lint-js    # ESLint for JavaScript
make lint-css   # Stylelint for CSS  
make lint-html  # HTMLHint for HTML

The project includes:

  • ESLint: JavaScript code quality and style enforcement
  • Stylelint: CSS/SCSS linting with modern standards
  • HTMLHint: HTML validation and best practices
  • Consistent Configuration: Unified rules across the codebase

Audio (SFX)

This version includes lightweight sound effects:

  • A short "peep" when the snake eats food.
  • A descending buzzer on game over.

Implementation notes:

  • Sounds are implemented with the WebAudio API inside src/js/Game.js and are created lazily (the AudioContext is initialized on first play) to comply with browser autoplay/gesture policies.
  • In some browsers the first audio playback must follow a user gesture (tap/click/keydown). If you don't hear audio immediately, interact with the page (press Enter or tap) and try again.
  • The code degrades gracefully in environments without WebAudio (for example during unit tests or on platforms that block audio) — audio failures are ignored so gameplay is unaffected.

Disable audio during testing or CI:

  • The tests included in this repository mock AudioContext where needed. If you want to disable audio manually in a browser build, you can modify src/js/Game.js or patch prepareEatSound()/prepareGameOverSound() to no-op, or open the devtools console and set window.AudioContext = undefined before loading the page (advanced).

Build

Build the project for production:

make build
# or
npm run build

Available Commands

Development Commands

  • make or make all - Install dependencies and build
  • make install - Install project dependencies
  • make build - Build the project (minify and optimize)
  • make watch - Watch for changes and rebuild
  • make serve - Start development server with live reload
  • make clean - Remove build artifacts and dependencies

Quality Assurance Commands

  • make test - Run tests with coverage report
  • make test-watch - Run tests in watch mode
  • make lint - Run all linters (JS, CSS, HTML)
  • make lint-js - Lint JavaScript files only
  • make lint-css - Lint CSS files only
  • make lint-html - Lint HTML files only

Docker Commands

  • make docker-up - Start Docker containers in background
  • make docker-down - Stop Docker containers
  • make docker-build - Build production Docker image
  • make docker-prod - Build and run production container (port 8080)
  • make docker-clean - Clean Docker resources (containers, volumes, images)
  • make docker-logs - Show Docker container logs

Utility Commands

  • make help - Show all available commands with descriptions

Controls

  • Arrow Keys: Move the snake (Up, Down, Left, Right)
  • Space: Pause/Resume game
  • Enter: Start/Restart game
  • Start Button: Begin or restart the game

Notes: The Start button was removed in recent versions — use Enter to start or restart. On mobile, tap to start/pause and swipe to change direction.

Architecture

The project follows a modular architecture with clear separation of concerns:

  • Snake.js: Handles snake movement, growth, and collision detection
  • Renderer.js: Manages all canvas drawing operations
  • Game.js: Coordinates game state, scoring, and game loop
  • main.js: Entry point that initializes the game

Key Design Decisions

  1. ES6 Modules: Better code organization and dependency management
  2. Class-based Architecture: Encapsulation and reusability
  3. Arrow Functions: Consistent this binding and cleaner syntax
  4. Separation of Concerns: Each class has a single responsibility
  5. Build System: Automated minification and optimization

Game Rules

  1. Control the snake to eat food (yellow, round)
  2. Each food eaten increases your score and the snake's length
  3. Speed increases every 5 points
  4. Game ends if the snake hits the wall or itself
  5. Try to achieve the highest score possible!

Browser Compatibility

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Note: ES6 modules require a modern browser or build step.

Code Quality Tools

This project includes comprehensive linting and testing tools for maintaining code quality. Use the convenient Makefile commands:

Linting Commands

  • make lint — run all linters (ESLint, Stylelint, HTMLHint)
  • make lint-js — run ESLint for JavaScript files
  • make lint-css — run Stylelint for CSS files
  • make lint-html — run HTMLHint for HTML files

Testing Commands

  • make test — run Jest test suite with coverage
  • make test-watch — run tests in watch mode for development

Alternative npm Scripts

For direct npm usage (useful in CI/CD):

  • npm run lint:js — ESLint
  • npm run lint:css — Stylelint
  • npm run lint:html — HTMLHint
  • npm run lint — all linters
  • npm test — Jest with coverage

Auto-fix: Add --fix flags when supported: npm run lint:js -- --fix

Deployment / CI

This repository includes a GitHub Actions workflow that builds the project and deploys the dist/ directory to GitHub Pages.

  • Workflow file: .github/workflows/gh-pages.yml
  • Trigger: push to the main branch or manual dispatch from Actions tab

What the workflow does:

  • Checks out the repository
  • Sets up Node.js (18)
  • Installs dependencies with npm ci
  • Runs npm run build (this uses the project's Gulp-based build and outputs into dist/)
  • Uploads the build output as an artifact and deploys it to the gh-pages branch using the official Pages deploy action

How to enable GitHub Pages for this repo:

  1. Go to your repository Settings → Pages.
  2. Under "Build and deployment", select "GitHub Actions".
  3. Make sure the gh-pages branch is allowed as the deployment source.
  4. After the first successful run of the workflow the Pages site will be published.

Notes:

  • The workflow uses the repository's GITHUB_TOKEN (automatically provided in Actions) to push the deployment branch. No extra secrets are required for basic Pages deployment.
  • If you prefer to publish to a custom domain, add the domain in the Pages settings and include a CNAME file in src/assets (it will be copied to dist/assets by the build).

License

MIT