A retro-style 18-hole browser minigolf game built with React and TypeScript.
Play now: https://mguttmann.github.io/minigolf-2000/
- 18 unique holes with progressive difficulty
- Easy (Holes 1-6): Simple layouts for beginners
- Medium (Holes 7-12): More complex with obstacles
- Hard (Holes 13-18): Challenging precision courses
- Realistic physics - velocity, friction, bouncing
- Obstacles - walls, sand traps, water hazards, bumpers
- Touch & mouse controls - drag to aim, release to shoot
- Score tracking - par comparison, hole-in-one detection
- Sound effects - synthesized audio, no external files
- Fully responsive - works on desktop and mobile
- Click/tap near the ball to start aiming
- Drag away from the ball to set direction and power
- Release to shoot
- Get the ball in the hole in as few strokes as possible!
| Score | Meaning |
|---|---|
| Hole in One | 1 stroke on any hole |
| Albatross | 3 under par |
| Eagle | 2 under par |
| Birdie | 1 under par |
| Par | Expected strokes |
| Bogey | 1 over par |
| Double Bogey | 2 over par |
- React 18 - UI framework
- TypeScript - Type safety
- Vite - Build tool
- Tailwind CSS - Styling
- HTML5 Canvas - Game rendering
- Web Audio API - Sound effects
- Bun (or Node.js 18+)
# Clone the repository
git clone https://github.com/mguttmann/minigolf-2000.git
cd minigolf-2000
# Install dependencies
bun install
# Start development server
bun run dev| Command | Description |
|---|---|
bun run dev |
Start dev server at localhost:5173 |
bun run build |
Build for production |
bun run preview |
Preview production build |
bun run lint |
Run ESLint |
src/
├── components/
│ ├── GameCanvas.tsx # Main game canvas with rendering
│ └── HUD.tsx # UI overlays (score, menus)
├── game/
│ ├── GameContext.tsx # React context for game state
│ ├── physics.ts # Physics engine (collision, movement)
│ ├── courses.ts # 18 hole definitions
│ └── sounds.ts # Web Audio synthesizer
├── types/
│ └── game.ts # TypeScript interfaces
├── App.tsx # Main app component
└── main.tsx # Entry point
Courses are defined in src/game/courses.ts. Each course has:
interface Course {
id: number
name: string
par: number
ballStart: Vector2D
hole: Hole
walls: Wall[]
obstacles: Obstacle[] // sand, water, bumper
bounds: { width: number, height: number }
}Add or modify courses by editing this file.
Tweak gameplay in src/types/game.ts:
export const PHYSICS = {
FRICTION: 0.985, // Ball slowdown per frame
MIN_VELOCITY: 0.1, // Speed to stop
MAX_POWER: 15, // Maximum shot power
POWER_MULTIPLIER: 0.30, // Shot strength
BOUNCE_DAMPING: 0.7, // Energy loss on bounce
SAND_FRICTION: 0.95, // Extra friction in sand
}The game auto-deploys to GitHub Pages on every push to master.
Workflow: .github/workflows/deploy.yml
MIT License - feel free to use, modify, and distribute.
Built with React, TypeScript, and retro vibes.
Play the game: https://mguttmann.github.io/minigolf-2000/