World Geography Game
I long wanted to implement a game to help learning and remembering the countries of the world. Sure, there is already a plethora of similar games already available online, but the motivation was more in the development aspect.
Code available on GitHub
Principles
The principles planned for the first release were kept quite simple.
- Group the countries by area
- Support three game modes (country name, capital city or flag)
- Challenge the user to find a country within a defined area
- Set a timeout for each question
- Keep track of the current game score
- Show the answers to the questions at the end

Update 05/02/2018
The v2 focused on bringing multi languages support with 20 languages.

Data
Data v1
Data sources:
The data was crunched together in the Countries GeoJson data processor project. The output is under the following format: (abbreviated for simplicity)
{
"properties": {
"id": "ITA",
"name": "Italy",
"continent": "Europe",
"populationEstimate": 58126212,
"lastCensus": 2012,
"capital": "Rome",
"latlng": [
42.83333333,
12.83333333
],
"area": 301336,
"translations": {
"deu": {
"official": "Italienische Republik",
"common": "Italien"
},
// ...
},
"flag": "dist/flags/ITA.svg"
},
"geometry":{
"type":"MultiPolygon",
"coordinates":[
// ...
]
}
}
propertiesused by some core game features but also to provide more info about the country.geometryused to show the countries’ shape and implement the interactive feature.translationswill be used in the second release which should support multiple languages.
Data v2
Data sources:
- Unicode CLDR
- Country containment (equiv: Continent => Region => Country)
- Translated names for:
- Languages
- Continents
- Regions / Sub-regions
- Countries / territories
- Capitals
- Ash Kyd
- Geo Json geometries
- Mohammed Le Doze
- area
- borders
- capital city (en only)
- latlng
- flag
The data for v2 was reorganized into two groups:
- translation sensitive data (country names, capital)
- generic data (geojson, flag, etc)
The data was crunched together in the World Geography data processor project. The languages to target in the extraction are passed as params, making painless the selection of supported locales.
Output folder structure
flags/
ABW.svg
AFG.svg
AGO.svg
...
geo-json/
africa.json
asia.json
europe.json
...
locales/ --- localized data
bg/ --- by locale code
africa.json --- by continent
asia.json
europe.json
...
ca/
cs/
...
status.json --- support of one language compared to English (count, pct, missing)
locales.json
Localized data sample for English:
{
"IE": {
"name": "Ireland",
"continent": "Europe",
"locatedIn": [
"Europe",
"Northern Europe"
],
"capital": "Dublin"
}
}
Implementation
It has been a while I wanted to get my hands dirty with React and Redux. The learning curve was greatly reduced thanks to Dan Abramov who published two series of great tutorials available for free on Egghead.io.
- Getting Started with Redux
- A Dummy’s Guide to Redux and Thunk in React by Matt Stow
- A Beginner’s Guide to Redux Middleware by Valeri Karpov
The App skeleton and the build are handled by Create React App.
Localization
Added on 05/02/2018
The App localization was achieved with react-localize-redux (see author’s article)
The loading of the translated data is done using async ES6 import to allow chunking of the bundle and reduce bandwidth usage.
Map
A core part of the game and a key to its usability is the interactive map.
It was implemented with the components from React Leaflet (wrapper for Leaflet) and uses the tiles from the free Mapbox service.
Geo JSON layer
The GeoJSON layer component is used to display the geometry (mentioned above), style the area or to listen to the different mouse events.

Marker layer
The Marker layer component is used to display the results at the end of the game. Each marker is placed on the coordinates pointed by properties.latlng and listens to the click event. On click, the map shows a custom popup with the country flag and information.

Analytics
Having insights on the game usage and popularity is a great source of motivation. No longer than a few days after the first beta version was deployed, users from 4 countries already visited the page. It is for sure a motivator to prioritize multi languages support.
I added Google Analytics to the App router to gather insights on the page views and audience of the game. The library react-ga helped a lot and the integration was quick.
The component below logs the page views during development and sends the data to the service in production.
if (NODE_ENV_PRODUCTION) {
ReactGA.initialize(gaTrackingId);
}
class GoogleAnalytics extends Component {
static onRouteChange() {
const location = window.location,
page = location.pathname + location.hash;
if (!NODE_ENV_PRODUCTION) {
console.log('ReactGA', {page: page});
return;
}
ReactGA.set({page: page});
ReactGA.pageview(page);
}
componentDidMount() {
this.stopListening = this.props.history.listen(GoogleAnalytics.onRouteChange);
GoogleAnalytics.onRouteChange();
}
componentWillUnmount() {
this.stopListening();
}
// ...
}
export default withRouter(connect()(GoogleAnalytics));
Deploy to GitHub pages
GitHub provides a way to serve static files from a repository directory or branch GitHub Pages. It was a very convenient way to deploy the game without additional complication.
The deployment is managed with the CLI utility of npm gh-pages.
The only required configuration is on the package.json:
"scripts": {
"deploy": "gh-pages -d build"
}
The app routing did not work correctly on GitHub pages after the first deployment. The issue was coming from GitHub pages not being configured to support the BrowserRouter (React Router).
Few solutions were possible, changing to HashRouter was the most straight forward.
Credits
A big thanks to the authors of these libraries / resources:
Libraries:
- React
- Redux
- Bootstrap
- React Router
- React Leaflet
- Leaflet
- Create React App
- gh-pages (NPM)
- redux-logger
- redux-thunk
- react-ga
- v1
- react-ionicons
- ionicons
- v2
- react-icons
- React Localize Redux
Images: