A dynamic, interactive map application built with Next.js and Leaflet that allows users to create and manage locations and regions on a custom map with rich text editing capabilities and a comprehensive timeline system. Perfect for world-building, fantasy maps, historical mapping, or any interactive mapping project.
- Interactive Map Interface: Built with Leaflet and react-leaflet for smooth, responsive map interactions
- Custom Map Background: Support for custom map images with flexible sizing and positioning options
- Location Management: Create, edit, and delete point locations with custom icons and colors
- Region Management: Create, edit, and delete polygon regions with custom styling and labels
- Rich Text Editing: Full-featured text editor using TipTap for location and region descriptions
- Custom Fields: Add unlimited key-value pairs to both locations and regions for additional metadata
- Type System: Categorize locations and regions with free-form types (Cities, Kingdoms, Forests, etc.)
- General Settings Panel: Comprehensive settings interface accessible via the settings button
- Map Image Controls:
- Upload custom map images via file upload
- Set map images from URLs
- Choose from image gallery
- Adjust map image roundness (0-100%)
- Configure map scale (km per pixel)
- Size options: Cover, Contain, Auto, or Custom dimensions
- Position control: 9-directional positioning
- Aspect ratio locking for custom dimensions
- Background Image Settings:
- Upload custom background images
- Set background images from URLs
- Choose from image gallery
- Background images always cover the viewport
- Map Name System:
- Rich text map name editor with full formatting options
- Show/hide toggle for map name visibility
- Position options: Center (with fade on zoom), corners
- Smooth fade animation on zoom level changes
- Edit Mode Toggle:
- Enable/disable editing capabilities
- When disabled, context menus are completely disabled
- Perfect for presentation mode or view-only access
- Persistent setting across sessions
- Zoom-based UI Controls: Timeline and settings buttons can be configured to show/hide based on zoom level
- "Show timeline when zoomed" setting
- "Show settings when zoomed" setting
- Maintains UI cleanliness at different zoom levels
- Dynamic Font Sizing: Region labels automatically scale based on polygon area
- Mention System: Link locations and regions within descriptions using @mentions
- Prominence System: Advanced visibility-based system with prominence ranges (lower/upper bounds)
- Context Menu: Right-click context menus for quick actions on map elements
- Move Mode: Drag-and-drop functionality for relocating locations
- Polygon Drawing: Interactive drawing mode for creating custom regions
- Toast Notifications: User feedback for element visibility and actions
- Scale Bar: Visual scale indicator on the map
- Smooth Zoom: Enhanced zoom experience with smooth wheel zoom
- Icon Gallery: Extensive collection of themed icons (castles, dungeons, landmarks, etc.)
- Search Functionality: Full-text search across locations and regions with relevance scoring
- Unified Geometry Storage: Single PostGIS geometry column replaces separate position columns
- Spatial Indexing: GIST indexes for fast spatial queries on locations and regions
- Area Calculations: Accurate polygon area calculations using PostGIS ST_Area()
- Spatial Containment: Efficient point-in-polygon and polygon-in-polygon queries
- Spatial Relationships: Find parent regions, child regions, and contained locations
- Centroid Calculations: Precise polygon center calculations using PostGIS ST_Centroid()
- Performance Optimization: Database-level spatial operations for better performance
- Reduced Storage: Eliminates duplicate position data by using only PostGIS geometry
- Fallback Support: Manual calculations as fallback when PostGIS is unavailable
- Interactive Timeline Navigation: Comprehensive timeline system for managing map states across different years
- Timeline Slider: Compact, minimalistic timeline interface with smooth navigation controls
- Year-based Navigation: Navigate between specific years with precise year selection
- Change-based Storage: Efficient progressive change storage system that only stores differences between years
- Epoch Management: Create and manage time periods with custom names, colors, and date ranges
- Timeline Notes: Add contextual notes to specific years with rich text editing
- Progressive Changes: Track how locations and regions evolve over time
- Creation Year Tracking: Elements are only visible after their creation year
- Label Collision Strategies: Three strategies for handling overlapping labels:
None
: Show label regardless of overlap (default)Hide
: Hide this label if it overlaps with anotherConquer
: Show this label and hide the other if they overlap
- Dynamic Label Scaling: Labels scale with zoom level for optimal readability
- Custom Label Offsets: Adjustable distance between element and label
- Prominence Ranges: Elements use lower and upper prominence bounds instead of single values
- Flexible Visibility: Set minimum and maximum zoom levels for element visibility
- Real-time Prominence Display: Current prominence level shown on map
- Toast Notifications: Informative messages when elements are outside visibility range
- Framework: Next.js 15.3.3 with React 19
- Map Library: Leaflet 1.9.4 with react-leaflet 5.0.0
- Rich Text Editor: TipTap 2.13.0 with multiple extensions
- Styling: Tailwind CSS 4 with SASS
- Icons: React Icons 5.5.0 and Lucide React 0.513.0
- Type Safety: TypeScript 5
- API: tRPC 11.4.3 for type-safe API communication
- Database: PostgreSQL with PostGIS spatial extension
- State Management: Zustand for UI state, React Query for server state
- UI Components: Custom components with Floating UI for tooltips
- Notifications: React Toastify for user feedback
dynamap/
βββ public/ # Static files and data
β βββ uploads/ # User uploaded images
β βββ media/ # Map images and assets
βββ src/
β βββ app/ # Next.js app directory
β β βββ api/ # API routes
β β β βββ trpc/ # tRPC API endpoints
β β β βββ [trpc]/ # tRPC handler
β β βββ components/ # React components
β β β βββ dialogs/ # Modal dialogs
β β β βββ map/ # Map-related components
β β β βββ markers/ # Location and region markers
β β β βββ panels/ # Side panels
β β β βββ timeline/ # Timeline components
β β β βββ ui/ # UI components
β β βββ contexts/ # React contexts
β β βββ providers/ # App providers
β β βββ utils/ # Utility functions
β βββ css/ # Stylesheets
β βββ hooks/ # Custom React hooks
β βββ lib/ # Database and tRPC setup
β βββ stores/ # Zustand stores
β βββ types/ # TypeScript type definitions
βββ scripts/ # Database setup and migration scripts
βββ @types/ # Custom type definitions
- Node.js 18+
- PostgreSQL 14+ with PostGIS extension
- npm or yarn
-
Clone the repository
git clone <repository-url> cd dynamap
-
Install dependencies
npm install
-
Set up PostgreSQL database
# Create the database createdb -U postgres dynamap # Set up database schema npm run setup-db
-
Configure environment variables Create a
.env.local
file in the root directory:DB_USER=postgres DB_HOST=localhost DB_NAME=dynamap DB_PASSWORD=your_password DB_PORT=5432
-
Set up database with PostGIS
npm run setup-postgis
-
Start the development server
npm run dev
-
Open your browser Navigate to http://localhost:3000
npm run dev
- Start development server with Turbopacknpm run build
- Build for productionnpm run start
- Start production servernpm run lint
- Run ESLintnpm run setup-db
- Set up PostgreSQL database schema (legacy)npm run setup-postgis
- Set up database with PostGIS geometry columns (recommended)npm run migrate-postgis
- Migrate existing data to PostGIS (legacy)
PostgreSQL runs as a background service. You can manage it based on your workflow:
Option 1: Keep PostgreSQL Running (Recommended for frequent development)
- PostgreSQL will start automatically with your system
- No need to start/stop when working on the project
- Uses minimal resources when idle (~50-100MB)
Option 2: Start/Stop PostgreSQL as Needed (Recommended for memory-conscious users)
When starting work:
# Start PostgreSQL
brew services start postgresql@14
# Start your development server
npm run dev
When stopping work:
# Stop your development server (Ctrl+C)
# Stop PostgreSQL
brew services stop postgresql@14
Useful PostgreSQL Commands:
# Start PostgreSQL
brew services start postgresql@14
# Stop PostgreSQL
brew services stop postgresql@14
# Check status
brew services list | grep postgresql
# Restart PostgreSQL
brew services restart postgresql@14
Note: Your data is safely persisted to disk, so stopping PostgreSQL won't affect your Dynamap data.
The application uses PostgreSQL with the following main tables:
- locations - Point locations on the map
- regions - Polygon regions on the map
- timeline_entries - Timeline entries for each year
- timeline_changes - Progressive changes between years
- epochs - Time periods/eras
- notes - Timeline notes
- settings - Application settings
- Enable Edit Mode: Click the settings button and ensure "Edit Mode" is enabled
- Add Locations: Right-click on the map and select "Add Location"
- Add Regions: Use the polygon drawing tool or right-click to add regions
- Customize: Use the rich text editor to add descriptions and custom fields
- Open Timeline: Click the timeline button (clock icon)
- Navigate Years: Use the timeline slider or year navigation buttons
- Add Epochs: Create time periods to organize your timeline
- Add Notes: Add contextual notes to specific years
- Upload Map Image: Use the settings panel to upload or configure map images
- Adjust Settings: Configure map scale, roundness, and positioning
- Customize Background: Set background images for the viewport
- Configure UI: Adjust which UI elements show at different zoom levels
The application follows a modern architecture with:
- Frontend: Next.js with React 19 and TypeScript
- API: tRPC for type-safe API communication
- Database: PostgreSQL with efficient change-based storage
- State Management: React Query for server state, Zustand for UI state
- Styling: Tailwind CSS with custom SASS components
- Progressive Enhancement: Timeline changes are stored incrementally
- Type Safety: Full TypeScript coverage with tRPC for end-to-end type safety
- Component Composition: Modular component architecture with clear separation of concerns
- Performance: Efficient rendering with React Query caching and optimized map interactions
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please open an issue on GitHub or contact the maintainers.