Skip to content
nomunomu0504.dev

BLOG #NEXTJS

minnama.beer: a map that finds bars by the beer on tap

Hiroki Nomura 4 MIN READ nextjs supabase postgis indie-dev
On this page

One experience only

“A bar pouring Sapporo Black Label on draft within a five-minute walk of Shinjuku station”, found in three seconds, with a menu photo to confirm it is on tap right now. The MVP of みんなの生ビールマップ (minnama for short) was built to deliver that one sentence.

So a lot was left out. No likes, follows or feeds. No rankings or trust scores. No venue management, reservations, payments or coupons. You search by the beer you want, not by the bar’s name, and users build the data by posting photos of what they found on tap.

The minnama.beer front page
minnama.beer. The front page has one path: from a beer to a place

How it is built

  • Next.js (App Router) with Tailwind and TanStack Query. It installs as a PWA; there is no native app
  • Supabase: Postgres with PostGIS for radius search, Google as the only auth provider, images served through Storage’s transformations, RLS on every table
  • Maps with MapLibre GL JS on OSM tiles
  • Hosted on Vercel, with posts and reports notified to Slack

You can post without an account. Signing in with Google adds favourites, editing your own posts and a public page listing your posts. Browsing and search never require sign-in.

Three minnama.beer screens
From left: the map, an area page, a place page. It is a PWA, so these are web screens

Showing freshness

A beer map lives or dies on “is it on tap now”. Travel to a bar on a year-old post and find the beer gone once, and you never use the map again.

So every bar shows how long it has been since the last confirmation, in four bands: within 30 days, 31 to 90, 91 to 365, more than a year. Lists sort bars with recent confirmations first. When information is wrong, a post from someone who actually visited overrides it as the latest. The design does not have the operator vouch for correctness; it shows exactly how old each piece of information is.

The four freshness tiers
Four colour tiers for the time since the last confirmation

Staying inside the Google Places terms

Venue entry uses Google Places Autocomplete (New) to make typing a name easy. Storing Places API responses as they come, though, violates the terms. After reading them, the storage and display rules came out like this.

Data Handling
place_id May be stored permanently (an explicit exception in the terms)
Name, address, coordinates Stored as values the user confirmed or edited
The Places response itself Never stored

In the posting flow, picking a suggestion pre-fills the form, and the user confirms or edits it before posting. At that point it becomes user-provided content. Only values from the database are ever displayed; nothing from Places is shown, and the Google attribution appears only while suggestions are on screen. Since no Places data reaches the map, OSM tiles are fine.

The autocomplete is behind an abstraction so it can be swapped for Nominatim if the interpretation of the terms changes.

Operating an alcohol service

Some things went in from day one because the subject is alcohol.

  • A permanent footer notice that drinking under 20 is prohibited by law in Japan, and an age confirmation with its timestamp on the first post
  • Reports in five categories, forwarded to Slack, handled from an admin area that only users with role = admin can enter
  • Account deletion by anonymization: posts stay, the link to the author is removed
  • The brand master cannot be grown freely. Users submit suggestions into a pending state, and an admin promotes them and merges spelling variants

Next

Around 70 brands are registered, each with a column on its history and taste. Editing and deleting posts and end-to-end tests are still to do. The PWA remains the answer to “where is the native app”. minnama.beer

  1. LaterHub: turning read-later into team knowledge 4 min
  2. Cherimo: rebuilding an app for the small things from usage data 5 min
  3. Stacky: an iOS clipboard app designed from the OS constraints 6 min
Hiroki Nomura @nomunomu0504 · CTO, MIRAI STUDIO

Flutter, AWS, homelab. A few side projects and open-source tools. For architecture questions or collaboration, reach out via X DM or the About page. About

COMMENTS · GISCUS