Maintenance
October 10, 2025 · View on GitHub
![]() |
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
- Clone the repository:
git clone https://github.com/jonathanbrenman/snake-game.git
cd snake-game
- 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
Option 2: Docker Development (Recommended)
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.jsand 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
AudioContextwhere needed. If you want to disable audio manually in a browser build, you can modifysrc/js/Game.jsor patchprepareEatSound()/prepareGameOverSound()to no-op, or open the devtools console and setwindow.AudioContext = undefinedbefore loading the page (advanced).
Build
Build the project for production:
make build
# or
npm run build
Available Commands
Development Commands
makeormake all- Install dependencies and buildmake install- Install project dependenciesmake build- Build the project (minify and optimize)make watch- Watch for changes and rebuildmake serve- Start development server with live reloadmake clean- Remove build artifacts and dependencies
Quality Assurance Commands
make test- Run tests with coverage reportmake test-watch- Run tests in watch modemake lint- Run all linters (JS, CSS, HTML)make lint-js- Lint JavaScript files onlymake lint-css- Lint CSS files onlymake lint-html- Lint HTML files only
Docker Commands
make docker-up- Start Docker containers in backgroundmake docker-down- Stop Docker containersmake docker-build- Build production Docker imagemake 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
- ES6 Modules: Better code organization and dependency management
- Class-based Architecture: Encapsulation and reusability
- Arrow Functions: Consistent
thisbinding and cleaner syntax - Separation of Concerns: Each class has a single responsibility
- Build System: Automated minification and optimization
Game Rules
- Control the snake to eat food (yellow, round)
- Each food eaten increases your score and the snake's length
- Speed increases every 5 points
- Game ends if the snake hits the wall or itself
- 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 filesmake lint-css— run Stylelint for CSS filesmake lint-html— run HTMLHint for HTML files
Testing Commands
make test— run Jest test suite with coveragemake test-watch— run tests in watch mode for development
Alternative npm Scripts
For direct npm usage (useful in CI/CD):
npm run lint:js— ESLintnpm run lint:css— Stylelintnpm run lint:html— HTMLHintnpm run lint— all lintersnpm 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
mainbranch 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 intodist/) - Uploads the build output as an artifact and deploys it to the
gh-pagesbranch using the official Pages deploy action
How to enable GitHub Pages for this repo:
- Go to your repository Settings → Pages.
- Under "Build and deployment", select "GitHub Actions".
- Make sure the
gh-pagesbranch is allowed as the deployment source. - 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 todist/assetsby the build).
License
MIT
