Self-hosted travel check-in tracker. Beautiful, privacy-first, works on any device. No backend needed.
When Foursquare shut down their Swarm API, millions of check-ins became trapped in a closed ecosystem. DroPin is the open-source alternative: a beautifully designed, privacy-focused check-in tracker you own and control.
Deploy in 5 minutes to Netlify (free). No backend, no database, no tracking β just your travel memories, beautifully visualized and safely synced across devices.
- πΊοΈ Interactive Global Map β Visualize all check-ins with clustering and smooth animations
- β‘ Quick Check-in β Location-based check-in finds nearby venues instantly via Google Places API
- π Manual Entry β Drag-to-position pin placement with auto-geocoding
- π Smart Search β Search pins by name/city, or fly to any city worldwide via Nominatim geocoding
- π¨ Minimalist Design β Clean, Apple-inspired interface
- π± Mobile-First β Fully tested on iOS Safari and Android Chrome
- π‘οΈ PWA Mode β Triple redundancy: IndexedDB + localStorage + Google Drive auto-backup
- βοΈ Cross-device Sync β Push/Pull your master CSV via Google Drive, merge without data loss
- π CSV Mode β Simple static file mode, great for getting started
- πΎ Offline-First β Works without internet in PWA mode
- π Auto-Recovery β Restores data from localStorage if IndexedDB is wiped
- π Travel Statistics β Choropleth world map, top countries chart, city rankings, distance insights
- π Read-only Sharing β Share
view.htmlwith family/friends for a public map (no editing) - π€ Export/Import β Full CSV export, import from any CSV source including Foursquare exports
- π Your data, your storage β Everything stays in your browser + your Google Drive
- π Zero Backend β Pure HTML/CSS/JS, deploy on any static host
- π° Free Hosting β Netlify free tier is more than enough
- π No Tracking β Zero analytics, no cookies, no third-party data collection
The simplest setup β reads check-ins from a static CSV file:
git clone https://github.com/pingou100/DroPin.git
cd DroPin/src
cp config.example.js config.js
# Edit config.js: set STORAGE_MODE to 'csv' and add your API keysThen drag the src/ folder to Netlify Drop.
Full check-in app with Google Drive sync across all your devices:
- Clone and configure as above, but set
STORAGE_MODE: 'pwa'in config.js - Create a Google OAuth 2.0 Client ID at Google Cloud Console:
- Application type: Web application
- Authorized JavaScript origins:
https://your-netlify-domain.netlify.app - Authorized redirect URIs: (none needed β we use implicit flow)
- Enable the Google Drive API in your project
- Add your
GOOGLE_DRIVE_CLIENT_IDto config.js - Deploy to Netlify
Important: The sync feature requires the https://www.googleapis.com/auth/drive scope so that files pushed from one device can be read by another. The old drive.file scope will not work for cross-device sync.
| Page | URL | Description |
|---|---|---|
| Map | index.html |
Main map with filters, search, clustering |
| Check In | checkin-now.html |
GPS-based venue search and quick check-in |
| Add | add-checkin.html |
Manual check-in with draggable pin |
| Stats | stats.html |
Travel statistics dashboard |
| Import/Export | import-export.html |
CSV import and export |
| Sync | sync.html |
Google Drive Push/Pull sync |
| View | view.html |
Read-only shareable map (no auth required) |
The sync page (sync.html) keeps all your devices in sync via a single master CSV on Google Drive:
Device A (mobile) Google Drive Device B (laptop)
β β β
βββ Push βββββββββββββββΊ DroPin-Master.csv β
β β β
β β βββββββββββββββ Pull ββββββ€
β β β
β Preview diff (new check-ins only) β
β β β
β β ββββ Merge βββββββββββββββΊβ
- Push β uploads your local check-ins as the new master file (
DroPin-Master.csvin the "DroPin Backups" folder) - Pull & Merge β downloads the master, shows you a diff preview, and merges only new check-ins (nothing deleted)
- Conflict-free β deduplication is by
checkin_id, so merging is always safe
First time setup: On each device, go to Sync β Connect β sign in with the same Google account.
In PWA mode, every check-in is saved to three independent layers:
Every check-in β
β
Layer 1: IndexedDB (primary, 50MB+, offline)
β
Layer 2: localStorage (backup, last 200 check-ins)
β
Layer 3: Google Drive (permanent, auto-upload every 5 check-ins)
If your browser cache is cleared, the app detects the empty IndexedDB and offers to restore from the localStorage backup. For a full restore, use Sync β Pull.
stats.html shows:
- World choropleth map β countries colored by visit intensity, click to zoom in
- Top 10 Countries β horizontal bar chart
- Top 20 Cities β click any city to fly the map there
- Distance insights β furthest from home, average journey, longest single-day trip
The "home" location is hardcoded to Brussels in
js/stats/GeoStatsCalculator.js. ChangehomeLocationto your city coordinates.
Share your travels without exposing your check-in interface. view.html:
- Reads directly from
checkins_with_addresses.csv - No navigation menu, no editing, no authentication
- Full search (pins + worldwide geocoding) and filters
- Shows "π View only" banner
Share the direct URL: https://your-domain.netlify.app/src/view.html
checkin_id,venue_name,venue_type,date,time,year,month,
latitude,longitude,street_address,city,state,
postal_code,country,country_code,full_address,
foursquare_url,venue_id,notes,is_privateDownload a template from the Import/Export page, or use the Foursquare/Swarm CSV export directly (column mapping may need adjustment).
- Frontend: Vanilla JavaScript (ES6 modules), no framework
- Maps: Leaflet.js with MarkerCluster
- Stats map: Leaflet + Natural Earth GeoJSON (via GitHub CDN)
- Charts: Chart.js
- Storage: CSV files OR IndexedDB + localStorage (PWA mode)
- Sync: Google Drive API v3 (direct REST, no SDK)
- OAuth: Google Identity Services (GIS) β implicit token flow
- Geocoding: Geoapify (addresses) + Nominatim (map search)
- Places: Google Places API v1 (New)
- Hosting: Netlify, Vercel, GitHub Pages, or any static host
- No third-party servers β API calls go directly to Google/Geoapify from your browser
- No analytics β zero tracking, no cookies set by DroPin itself
- Google Drive scope β uses
drivescope (required for cross-device file discovery). Files are stored in a dedicated "DroPin Backups" subfolder - Your keys stay local β
config.jsis in.gitignoreand never committed
config.js with real API keys to a public repo
β
Restrict API keys by domain in Google Cloud Console
β
Keep your instance in a private GitHub repo
β
Add test users in Google OAuth consent screen if app is in "Testing" mode
Completed β
- Interactive map with clustering, filters, year slider
- GPS-based quick check-in via Google Places API v1
- Manual check-in with draggable pin + auto-geocoding
- Smart search: pin search + worldwide Nominatim geocoding
- PWA triple redundancy (IndexedDB + localStorage + Google Drive auto-backup)
- Cross-device sync via Google Drive Push/Pull with merge preview
- Travel statistics dashboard (world map, charts, city rankings, distance stats)
- Read-only shareable map (
view.html) - CSV import/export with iOS paste support
- iOS click/touch fixes
Coming Soon π
- Dark mode
- Service Worker for full PWA installability (home screen icon, offline caching)
- Photo attachments
- Import from Foursquare/Swarm CSV export (column auto-mapping)
- Settings panel (backup status, manual backup trigger)
β
iOS Safari 14+
β
Chrome 90+
β
Firefox 88+
β
Edge 90+
β
Mobile browsers (tested on iPhone and Android)
Requires HTTPS for Google OAuth and geolocation. Netlify/Vercel provide this automatically.
Contributions welcome! Whether you found a bug, have a feature idea, or want to improve the docs:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -m 'Add my feature') - Push to the branch (
git push origin feature/my-feature) - Open a Pull Request
- Inspired by Foursquare/Swarm's check-in experience
- Maps by Leaflet + Leaflet.markercluster
- Map tiles by CARTO / OpenStreetMap
- World borders GeoJSON by Natural Earth via nvkelso/natural-earth-vector
- Geocoding by Geoapify and Nominatim
- Places data by Google Places API
- Auth via Google Identity Services
MIT License β see LICENSE for details.
- π Bug reports: GitHub Issues
- π¬ Discussions: GitHub Discussions
- β Star the repo if you find it useful!
Get Started β’ Sync Setup β’ Report Bug
Made with β€οΈ for travelers and explorers worldwide