A production-ready Next.js 16 starter template with vanilla Leaflet integration. Build modern, interactive map applications with a Google Maps-inspired UI.
📖 Read the full story: I Built a Google Maps Clone Using Next.js 16 + Leaflet
- Modern Map Interface — Google Maps-inspired UI with smooth animations
- Multiple Tile Providers — OpenStreetMap, Satellite (Esri), and Dark mode (CARTO)
- Theme-Aware Basemaps — Auto-switches map style based on light/dark theme
- GeoJSON Support — Render and style geographic features with fly-to animations
- Country Search — Debounced search with keyboard navigation (↑↓ Enter Esc)
- Map Controls — Zoom, fullscreen, geolocation, and reset view
- Responsive Design — Mobile-first approach with adaptive layouts
- Server Components — Next.js 16 App Router with optimized client boundaries
- Full CRUD Operations — Create, read, update, and delete custom places
- 14 Category Types — Food & Drink, Shopping, Transport, Lodging, Health, Entertainment, Nature, Services, Education, Religion, Business, Tourism, Emergency, Utilities
- Interactive Location Picker — Click-to-select with live cursor tracking and crosshair cursor
- LocalStorage Persistence — Your places are saved automatically
- GeoJSON Import/Export — Share and backup your places
- Category Filtering — Filter places by category with color-coded markers
- Fly-to Animation — Smooth navigation to any saved place
- Mobile-Optimized — Drawer UI on mobile, side panel on desktop
- Toast Notifications — Beautiful, colorful feedback for all actions
- Context Menu — Right-click for quick actions (copy coordinates, add marker, measure, save place)
- Measurement Tools — Distance and area measurement with interactive drawing
- User Markers — Add custom markers anywhere on the map
- Real-time Coordinate Display — Live lat/lng tracking when selecting locations
- Dark Mode Support — Seamless theme switching with persistent preferences
- Error Boundaries — Graceful error handling with fallback UI
| Category | Technology |
|---|---|
| Framework | Next.js 16.0.7 (App Router) |
| UI | React 19.2.1, Tailwind CSS 4, shadcn/ui |
| Maps | Leaflet 1.9 (vanilla, no wrapper) |
| Icons | Lucide React |
| Theming | next-themes |
| Notifications | Sonner (toast notifications) |
| Drawers | Vaul (mobile-optimized) |
| Language | TypeScript 5 |
# Clone the repository
git clone https://github.com/wellywahyudi/nextjs-leaflet-starter.git
cd nextjs-leaflet-starter
# Install dependencies
npm install
# Start development server
npm run devOpen http://localhost:3000 to view the landing page, then navigate to /map for the interactive map.
├── app/
│ ├── api/countries/ # Country search API
│ ├── map/ # Map page (Server Component)
│ └── page.tsx # Landing page
├── components/
│ ├── landing/ # Hero, navigation, tech stack
│ ├── map/ # Map components (controls, layers, search)
│ └── ui/ # shadcn/ui components
├── contexts/ # MapContext, ThemeContext
├── hooks/ # useLeafletMap, useMapControls, useMapTileProvider
├── constants/ # Map config, tile providers
└── types/ # TypeScript definitions
| Component | Description |
|---|---|
LeafletMap |
Core map container with initialization |
LeafletTileLayer |
Dynamic tile layer switching |
LeafletGeoJSON |
GeoJSON rendering with styling |
LeafletMarker |
Custom markers with popups |
MapControls |
Zoom, fullscreen, location, reset |
MapTileSwitcher |
Tile provider switcher with previews |
MapSearchBar |
Country search with autocomplete |
MapContextMenu |
Right-click menu for quick actions |
MapPOIPanel |
POI management with CRUD operations |
MapMeasurementPanel |
Distance and area measurement tools |
MapDetailsPanel |
Country information with REST Countries API |
MapErrorBoundary |
Error handling with fallback UI |
Edit constants/map-config.ts:
export const DEFAULT_MAP_CONFIG: MapConfig = {
defaultCenter: [-2.911154, 120.074263], // Indonesia
defaultZoom: 5,
minZoom: 3,
maxZoom: 18,
};Edit constants/tile-providers.ts:
export const TILE_PROVIDERS: TileProvider[] = [
{
id: "custom",
name: "Custom Map",
url: "https://your-tile-server/{z}/{x}/{y}.png",
attribution: "© Your Attribution",
maxZoom: 19,
category: "standard",
},
// ...existing providers
];npm run dev # Start development server
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint- Install Vercel CLI:
npm i -g vercel- Deploy:
vercel- Follow the prompts to link your project
No environment variables required for basic deployment. The app uses public GeoJSON data from the /public/data directory.
This starter is production-ready with:
- ✅ Error boundaries and graceful fallbacks
- ✅ Optimized bundle size with code splitting
- ✅ Memory leak prevention with proper cleanup
- ✅ Toast notifications instead of blocking alerts
- ✅ TypeScript strict mode
- ✅ Responsive design (mobile-first)
- ✅ Accessibility features (ARIA labels, keyboard navigation)
- ✅ Dark mode support
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License — feel free to use this starter for personal or commercial projects.
