A directory and interactive map of Georgia's craft beer scene — breweries, bars, and retailers across Tbilisi, Batumi, and beyond — built for travellers and locals trying to find good beer in a country better known for wine. Each venue lives as a plain text file with its coordinates and contact details, which the site turns into map markers, a filterable sidebar, and a dedicated page for every location, all pre-rendered as static HTML so it loads fast anywhere.
GeoBeerMap
A static directory and interactive Leaflet map cataloguing craft beer venues across Georgia, built for travellers and locals navigating a wine-centric country. Every venue is a plain-text file with coordinates and contact details, pre-rendered into fast pages and filterable markers.

GeoBeerMap
Live
Introduction

The Challenge
Georgia is better known for its wine culture than craft beer, leaving visitors and locals with no central resource to discover breweries, bars, and beer retailers across Tbilisi, Batumi, and beyond. The challenge was to aggregate scattered venue information into a single searchable directory and map that would load quickly anywhere, stay easy to update, and remain viable as a solo-maintained side project without a backend or database infrastructure.
The Outcome
Launched a searchable directory and interactive map of craft beer venues across Georgia.
Tech Stack
Frontend
- React
- Mapbox
- Gatsby
- Leaflet
- React-Leaflet
- CSS Modules
- React Helmet
Language
- GraphQL
- JavaScript
- MDX
Backend
- Sharp
CMS
- Netlify CMS
DevOps
- Netlify
- GitHub
Tooling
- Remark
- Google Analytics
- Gatsby 2 + React 17 static site generator, chosen so a data-heavy directory can be compiled to static pages at build time rather than queried at runtime
- GraphQL as the internal data layer — venue and blog content is sourced from the filesystem and queried in
gatsby-node.jsto generate pages - MDX content files (
entries/for venues,blog/for posts) processed through Remark plugins for responsive images and iframes - Leaflet + React-Leaflet for the interactive map, with Mapbox tiles
- Netlify CMS (
netlify-cms-app) with GitHub authentication, giving a browser-based editing UI that commits straight back to the repo - CSS Modules for component-scoped styling, one stylesheet per component directory
- React Helmet for per-page SEO metadata, plus Gatsby's sitemap and robots.txt plugins
- Sharp image processing via
gatsby-plugin-sharp/gatsby-imagefor venue logos and photos - Google Analytics through
gatsby-plugin-google-gtag, configured withanonymize_ipandrespectDNT - Deployed on Netlify, with build behaviour driven by Netlify's deploy-context environment variables
Key Implementation Details
Files-as-database content model
- Every venue is an MDX file with structured frontmatter: coordinates, address, city, country, opening status, beer list, and links to website, Facebook, Instagram, Untappd, and Google Maps
- A custom
createSchemaCustomizationstep declares the fullMdxFrontmattertype explicitly, so optional fields (e.g. a venue with no Instagram) don't break the GraphQL schema or the build - Editors never touch the code — Netlify CMS writes new entries as commits, which triggers a fresh Netlify build
Programmatic page generation from two content sources
- A single GraphQL query in
gatsby-node.jssplits content by file path regex —/blog/for posts,/entries/for venues — and pipes each set into its own React template - Venue entries are filtered on the
openfield so incomplete or unpublished records are excluded from the build - Blog posts are sorted by frontmatter date, and pages are created with only an
idin context, letting each template fetch exactly the fields it needs
Map, sidebar, and search as one connected view
MapContainercoordinates a Leaflet map, customMapMarkerpopups, aMapSidebarlist, and aSearchBox, so filtering by category (brewery, bar, retailer) updates both the list and the markers- Coordinates parsed out of frontmatter are reused on individual entry pages to render a location-specific map
gatsby-plugin-react-leaflethandles the CDN stylesheet loading that Leaflet normally requires manual setup for
Deploy-context-aware crawling and SEO
gatsby-config.jsreads Netlify'sCONTEXT,URL, andDEPLOY_PRIME_URLvariables to compute the canonical site URL per environmentgatsby-plugin-robots-txtemits a permissive policy in production but a fulldisallowwith no sitemap on branch deploys and deploy previews, preventing staging URLs from being indexed- A shared
SEO.jscomponent with React Helmet centralises titles (via atitleTemplate), descriptions, and social images fromsiteMetadata
Responsive navigation built from scratch
- The hamburger menu is split into container, button, and panel components, each with its own CSS Module
- A custom
MenuCloseHookhandles outside-click/route-change dismissal, keeping the state logic reusable and out of the markup
What I Contributed
- Architected a files-as-database content model where each venue is an MDX file with structured frontmatter (coordinates, contact details, social links), enabling non-technical updates through Netlify CMS that trigger automatic rebuilds without touching code.
- Built a unified map and directory view coupling Leaflet markers, a filterable sidebar, and a search box so category selections (brewery, bar, retailer) update both the list and the map in sync.
- Implemented programmatic page generation in gatsby-node.js by querying all MDX files, splitting them by path regex into venues and blog posts, and piping each set into dedicated React templates with a custom GraphQL schema to handle optional frontmatter fields.
- Configured deploy-context-aware SEO and robots.txt policies that read Netlify environment variables to allow crawling in production while blocking branch deploys and previews from being indexed.
Outcome
-
Earned strong organic search visibility for craft beer searches relating to Georgia.
-
Received direct feedback from multiple users and brewery owners describing the platform as useful and requesting updates to venue information.
The directory has earned strong organic search visibility for craft beer searches relating to Georgia. Multiple users and brewery owners have contacted me to request updates to venue information and say how useful they find the platform. It remains live, with a backlog of venue-information updates to work through.