GeoStess is a free geography game built in the open. Play on desktop or mobile, challenge friends on the same device, or create an online room and play from separate devices.
Play GeoStess · Report a bug or request a feature
| Mode | What you do | Local play | Online rooms |
|---|---|---|---|
| Countries | Find a country on the world map | Yes | Yes |
| Cities | Locate a city as accurately as possible | Yes | Yes |
| Population Guess | Estimate a country's population | Yes | Not yet |
| Population Rank | Guess a country's population ranking | Yes | Not yet |
| Flag Recognition | Identify a country from its flag | Yes | Not yet |
Local games support one to ten players sharing a device. Online rooms support up to ten players, with synchronized questions, turns, scores, and final rankings.
GeoStess also includes:
- a learning mode for practice
- adjustable difficulty and an expert option for city questions
- local game statistics
- responsive controls for phones, tablets, and desktop browsers
- installable PWA support
After the first successful load, every local game mode can run without an internet connection. The app, map, questions, and local statistics are stored on the device by the service worker.
Online multiplayer still requires a connection because rooms and scores are synchronized through the backend.
- Node.js
20.19+or22.12+. Node.js 22 is recommended. - npm
git clone https://github.com/estevecastells/geostess.git
cd geostess
npm install
npm run db:migrate:local
npm run devOpen the local URL printed by Vite, normally http://127.0.0.1:8080.
The database migration is only needed for online room development. All five local modes work without it.
| Command | Purpose |
|---|---|
npm run dev |
Start the app and backend in development mode |
npm run build |
Create the production client and Worker build |
npm run preview |
Run the production build locally |
npm run lint |
Check the code with ESLint |
npm test |
Run the browser-side and multiplayer Worker test suites |
npm run test:watch |
Run browser-side tests in watch mode |
npm run test:coverage |
Run browser-side tests and enforce coverage thresholds |
npm run test:worker |
Run the multiplayer API tests with a local D1 database |
npm run test:all |
Run coverage checks followed by Worker tests |
npm run db:generate |
Generate a migration after changing the Drizzle schema |
npm run db:migrate:local |
Apply D1 migrations to the local database |
GeoStess uses Vitest for browser-side logic and component tests, plus Cloudflare's Vitest integration for the multiplayer Worker.
Coverage reports are written to coverage/ in text, HTML, and LCOV formats. The suite enforces minimum coverage thresholds for the main game logic and components.
Worker tests run locally in Miniflare with an isolated D1 database. Migrations from drizzle/ are applied automatically, so the tests never use the deployed database or the normal local development database.
The frontend is built with React, TypeScript, Vite, Tailwind CSS, and shadcn/ui. The interactive map uses d3-geo and TopoJSON.
Local games run entirely in the browser. The PWA service worker is generated with vite-plugin-pwa and Workbox.
Online rooms use a Cloudflare Worker API with D1 for persistent room state. The database schema lives in db/schema.ts, and Drizzle generates the SQL migrations in drizzle/.
src/components/ Game screens, map, controls, and shared UI
src/data/ Countries, cities, and population data
src/pages/ Public routes, statistics, and multiplayer
src/lib/ Browser statistics and multiplayer API client
worker/ Multiplayer API
db/ Drizzle schema
drizzle/ D1 migrations
Issues and pull requests are welcome.
- Fork the repository and create a branch for your change.
- Keep changes focused and explain the reason for them.
- Add or update tests when behavior changes.
- Test affected flows on both desktop and mobile when the interface changes.
- Run
npx tsc --noEmit,npm run test:all, andnpm run buildbefore opening a pull request. - Include screenshots for visual changes and note any database migration.
Use the issue tracker for bugs, feature proposals, or questions about contributing.
This repository does not have a license file yet. The source is public, but reuse and redistribution terms have not been defined. An explicit open-source license should be added before others reuse the project outside GitHub's standard viewing and forking permissions.
GeoStess was created by Jessie and Esteve.
World boundaries come from Natural Earth through the world-atlas TopoJSON package.