A modern, responsive interactive map application built with React, TypeScript, and Leaflet. Explore locations, manage custom pins with categories, search and filter places, and get route directions between points.
- Interactive Map: OpenStreetMap tiles with smooth pan, zoom, and click interactions for seamless exploration
- Pin Management: Add, view, edit, and delete location pins with custom details including title, description, address, and rating
- Category System: 6 distinct categories with custom icons and colors (Restaurant, Hotel, Attraction, Shopping, Transport, Other)
- Search & Filter: Real-time search by title, description, or address with category filtering support
- Route Directions: Get driving, walking, or cycling directions between any two pins via Mapbox Directions API
- Responsive Design: Fully responsive layout that works seamlessly on desktop, tablet, and mobile devices
- Persistent Storage: All pins are automatically saved to local storage for data persistence
- Form Validation: Robust form validation using Zod schema for reliable pin creation
- Beautiful UI: Modern, clean interface with Tailwind CSS styling and Lucide icons
The main interface displays an interactive map with a collapsible sidebar containing pin list, search functionality, and category filters.
Click anywhere on the map to add a new pin. Fill in the details including title, description, category, and optional address.
Select any two pins to calculate and display the route between them with distance and duration information.
- React 18: Modern React with hooks for building the user interface
- TypeScript: Type-safe development with full TypeScript support
- Vite: Lightning-fast build tool and development server
- Zustand: Lightweight state management for global app state
- React Hook Form: Performant form handling with minimal re-renders
- Zod: Schema validation for type-safe form validation
- React Router v6: Client-side routing for navigation
- Leaflet + React-Leaflet: Interactive map library with React bindings
- OpenStreetMap: Free map tiles for the base layer
- Mapbox Directions API: Route calculation and navigation
- Tailwind CSS: Utility-first CSS framework for styling
- Lucide React: Beautiful, consistent icon library
- clsx + tailwind-merge: Utility functions for conditional class names
Make sure you have the following installed on your system:
- Node.js 18 or higher
- npm or yarn package manager
- Clone the repository:
git clone https://github.com/Serkanbyx/interactive-map.git
cd interactive-map- Install dependencies:
npm install- Create environment file:
cp .env.example .env- (Optional) Add your Mapbox token for route directions:
VITE_MAPBOX_ACCESS_TOKEN=your_mapbox_token_hereGet your free Mapbox token at: https://account.mapbox.com/access-tokens/
- Start the development server:
npm run dev- Open http://localhost:5173 in your browser.
- Explore the Map: Pan and zoom around the map to explore different locations
- View Pins: Click on any marker to view pin details in a popup
- Add a Pin: Click the "Add Pin" button, then click anywhere on the map to place a new pin
- Fill Pin Details: Enter title, description, select a category, and optionally add an address
- Search Pins: Use the search bar in the sidebar to find pins by name, description, or address
- Filter by Category: Click category buttons to filter pins by type
- Get Directions: Select a starting pin and destination pin to see the route on the map
- Delete Pins: Click on a pin and use the delete button to remove it
The application uses Zustand for efficient state management:
interface PinState {
pins: Pin[]; // All map pins
selectedPin: Pin | null; // Currently selected pin
routeData: RouteData | null; // Active route data
filters: FilterState; // Search and category filters
isAddingPin: boolean; // Pin creation mode
}Each pin contains the following information:
interface Pin {
id: string;
title: string;
description: string;
category: PinCategory;
coordinates: { lat: number; lng: number };
address?: string;
rating?: number;
createdAt: string;
updatedAt: string;
}Routes are calculated using the Mapbox Directions API and decoded using the polyline algorithm for display on the map.
src/
├── components/
│ ├── layout/ # Layout components (MobileNav)
│ ├── map/ # Map components (Map, Markers, RouteLine)
│ ├── pin/ # Pin components (PinForm, PinCard)
│ ├── route/ # Route components (RoutePanel)
│ ├── sidebar/ # Sidebar components (Sidebar, Filters)
│ └── ui/ # Reusable UI components (Button, Input, etc.)
├── hooks/ # Custom React hooks
├── lib/ # Utility functions
├── pages/ # Page components
├── schemas/ # Zod validation schemas
├── services/ # API services (Mapbox)
├── store/ # Zustand store
├── types/ # TypeScript types
├── App.tsx # Main app component
├── main.tsx # Entry point
└── index.css # Global styles
| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Build for production |
npm run preview |
Preview production build |
npm run lint |
Run ESLint for code quality |
Edit the src/types/index.ts file to add new categories:
export const CATEGORIES: CategoryMeta[] = [
{ id: 'restaurant', label: 'Restaurant', color: '#ef4444', icon: 'utensils' },
{ id: 'hotel', label: 'Hotel', color: '#8b5cf6', icon: 'bed' },
// Add your custom category here
{ id: 'museum', label: 'Museum', color: '#0ea5e9', icon: 'building-2' },
];Modify the default map center in src/components/map/Map.tsx:
const DEFAULT_CENTER: [number, number] = [40.7128, -74.0060]; // New York
const DEFAULT_ZOOM = 13;Update Tailwind configuration in tailwind.config.js to change the color scheme.
| Variable | Required | Description |
|---|---|---|
VITE_MAPBOX_ACCESS_TOKEN |
Optional | Mapbox API token for route directions |
VITE_API_BASE_URL |
Future | Backend API URL (for future integration) |
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
✅ Interactive map with pan and zoom
✅ Pin CRUD operations (Create, Read, Update, Delete)
✅ 6 category types with custom icons and colors
✅ Real-time search functionality
✅ Category filtering
✅ Route directions via Mapbox API
✅ Responsive mobile-first design
✅ Local storage persistence
✅ Form validation with Zod
✅ Clean, modern UI with Tailwind CSS
- User authentication and accounts
- Backend API integration
- Pin sharing and collaboration
- Import/export pins as JSON or CSV
- Custom map tile providers
- Offline mode support
- Pin clustering for better performance
- Image upload for pins
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create your feature branch:
git checkout -b feature/amazing-feature- Commit your changes with semantic commit messages:
git commit -m 'feat: add amazing feature'Commit Message Prefixes:
| Prefix | Description |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
docs: |
Documentation changes |
style: |
Code style changes (formatting, etc.) |
refactor: |
Code refactoring |
test: |
Adding or updating tests |
chore: |
Maintenance tasks |
- Push to the branch:
git push origin feature/amazing-feature- Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Serkanby
- 🌐 Website: serkanbayraktar.com
- 💻 GitHub: @Serkanbyx
- 📧 Email: serkanbyx1@gmail.com
- OpenStreetMap - Free map tiles
- Mapbox - Directions API
- Leaflet - JavaScript map library
- React-Leaflet - React components for Leaflet
- Lucide - Beautiful icon library
- Tailwind CSS - Utility-first CSS framework
- Zustand - State management library
- 📝 Issues: GitHub Issues
- 📧 Email: serkanbyx1@gmail.com
- 🌐 Website: serkanbayraktar.com
⭐ If you like this project, don't forget to give it a star!