No description
  • JavaScript 61.9%
  • CSS 28.2%
  • HTML 9.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-08 15:13:26 +03:00
deploy Initial commit 2026-09-08 15:13:26 +03:00
public Initial commit 2026-09-08 15:13:26 +03:00
src Initial commit 2026-09-08 15:13:26 +03:00
.gitignore Initial commit 2026-09-08 15:13:26 +03:00
package-lock.json Initial commit 2026-09-08 15:13:26 +03:00
package.json Initial commit 2026-09-08 15:13:26 +03:00
README.md Initial commit 2026-09-08 15:13:26 +03:00
server.js Initial commit 2026-09-08 15:13:26 +03:00

City Map (2GIS-style)

A self-hosted web map with a 2GIS-like layout: search bar, category browsing (cafes, pharmacies, ATMs, etc.), a results list, and a clean map view. Built with Node.js + Express on the backend and vanilla JS + Leaflet on the frontend — no build step, so it runs on a plain Ubuntu server with nothing but Node installed.

Included, per your notes:

  • Geolocation prompt a custom "Turn on your location" modal appears on first visit, explaining why, before the real browser permission dialog fires. There's also a locate button on the map for later. Dismissal is remembered per-browser so it won't nag every visit.
  • Visit logging every page load and API call is logged with timestamp, IP, method, path, user agent, and referer to logs/visits.log (one JSON object per line).

How it works

  • Map tiles come from OpenStreetMap (free, no API key).
  • The search box proxies to the free Nominatim geocoding API.
  • Category chips (cafes, pharmacies, ATMs...) proxy to the free Overpass API, queried live for whatever's inside the current map view.
  • Your Express server sits between the browser and these APIs, so you can swap either one for a paid provider later without touching the frontend.

Requirements

Ubuntu with Node.js 18 or newer:

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v   # should print v18+

Setup

unzip 2gis-style-map.zip
cd 2gis-style-map
npm install
npm start          # -> http://your-server-ip:3000

For local development with auto-restart on file changes:

npm run dev

Configuration

  • public/js/config.js default map center/zoom and the category chip list. Center defaults to Moscow; change DEFAULT_CENTER to your city's [lat, lon].
  • src/routes/search.js update the User-Agent contact email. Nominatim's usage policy requires a real identifier and can block requests that don't have one.

Logs

Each line in logs/visits.log looks like:

{"time":"2026-09-08T12:00:00.000Z","ip":"203.0.113.4","method":"GET","path":"/","userAgent":"Mozilla/5.0 ...","referer":null}

The folder is created automatically on first run. Static assets (css/js/images) aren't logged — only page loads and API calls — so the file stays readable. Watch it live with tail -f logs/visits.log.

One heads-up: IP addresses count as personal data under GDPR, which matters if you're serving EU visitors. If this goes live, it's worth a line in a privacy policy plus rotating/deleting old logs rather than keeping them forever — deploy/logrotate.example is a ready-made config for that.

Running it in production on Ubuntu

See the deploy/ folder:

  • mapapp.service a systemd unit so the app survives reboots and restarts itself if it crashes.
  • nginx.conf.example reverse proxy config so you can put a domain and HTTPS (via certbot --nginx) in front of port 3000.
  • logrotate.example keeps the visit log from growing forever.

Scaling beyond the free APIs

Nominatim and Overpass's public instances are rate-limited — fine for low or moderate traffic, a demo, or an internal tool, but not for heavy production use. If this gets real traffic, the options are to self-host Nominatim/Overpass or switch to a paid provider (MapTiler, LocationIQ, Mapbox). Either way, you'd only need to change the two files under src/routes/.

Where to take it next

  • Swap logs/visits.log for a small SQLite/Postgres table if you want to query or filter visits later.
  • Add a "favorites" or "recently viewed" list using the same localStorage pattern as the geolocation prompt.
  • Add routing/directions — OSRM has a free public API with the same rate-limit caveats as Nominatim/Overpass.