# AI Coding Assistant Prompt: Next.js MVP for Tolkien's Middle-earth Interactive Map
## 1. PROJECT OVERVIEW:
Develop a fully functional, multi-page Next.js MVP application called "MappaLore" (Lore Mapper). This web application aims to provide fans of J.R.R. Tolkien's works (The Lord of the Rings, The Hobbit, etc.) with an immersive and interactive experience of Middle-earth. The core value proposition is to deepen the user's connection to the lore by visualizing events, character journeys, and geographical details on a high-definition, zoomable map. Users can plot key events, trace character paths, measure distances, and explore a chronological timeline. The application will leverage LLM capabilities for potential lore expansion and data enrichment (future scope, but architecture should allow for it).
## 2. TECH STACK:
- **Frontend Framework:** Next.js (App Router)
- **UI Library:** shadcn/ui (for accessible, reusable components)
- **Styling:** Tailwind CSS (with PostCSS and Autoprefixer)
- **State Management:** React Context API (for global state) and component-level state management. Zustand or Jotai can be considered for more complex state if needed.
- **Data Fetching:** Server Components, Client Components, Route Handlers (API routes)
- **ORM:** Drizzle ORM (for type-safe database interactions)
- **Database:** PostgreSQL (or SQLite for local development/simpler deployments)
- **Authentication:** NextAuth.js (for seamless user authentication - GitHub, Google, Email/Password)
- **Mapping Library:** Leaflet.js (or Mapbox GL JS if more advanced features are required later, but start with Leaflet for simplicity with custom tiles)
- **Charting Library:** Recharts or Chart.js (for timeline visualization)
- **Form Handling:** React Hook Form with Zod for validation
- **Utilities:** date-fns or moment.js for date manipulation, clsx for conditional class names.
## 3. DATABASE SCHEMA:
We will use Drizzle ORM for PostgreSQL.
**Tables:**
1. **`users`**
* `id` (UUID, primary key, default generated)
* `name` (VARCHAR(255))
* `email` (VARCHAR(255), unique, not null)
* `emailVerified` (TIMESTAMP with time zone)
* `image` (VARCHAR(255))
* `createdAt` (TIMESTAMP with time zone, default now())
* `updatedAt` (TIMESTAMP with time zone, default now())
2. **`accounts`** (For NextAuth.js)
* `id` (UUID, primary key, default generated)
* `userId` (UUID, foreign key to `users.id`, not null)
* `type` (VARCHAR(255), not null)
* `provider` (VARCHAR(255), not null)
* `providerAccountId` (VARCHAR(255), not null)
* `refresh_token` (TEXT)
* `access_token` (TEXT)
* `expires_at` (BIGINT)
* `token_type` (VARCHAR(255))
* `scope` (TEXT)
* `id_token` (TEXT)
* `session_state` (TEXT)
3. **`sessions`** (For NextAuth.js)
* `id` (UUID, primary key, default generated)
* `sessionToken` (VARCHAR(255), unique, not null)
* `userId` (UUID, foreign key to `users.id`, not null)
* `expires` (TIMESTAMP with time zone, not null)
4. **`verificationTokens`** (For NextAuth.js)
* `identifier` (VARCHAR(255), not null)
* `token` (VARCHAR(255), unique, not null)
* `expires` (TIMESTAMP with time zone, not null)
5. **`map_layers`**
* `id` (UUID, primary key, default generated)
* `userId` (UUID, foreign key to `users.id`, nullable for public layers)
* `name` (VARCHAR(255), not null)
* `description` (TEXT)
* `isPublic` (BOOLEAN, default false)
* `createdAt` (TIMESTAMP with time zone, default now())
* `updatedAt` (TIMESTAMP with time zone, default now())
6. **`map_markers`**
* `id` (UUID, primary key, default generated)
* `layerId` (UUID, foreign key to `map_layers.id`, not null)
* `title` (VARCHAR(255), not null)
* `description` (TEXT)
* `lat` (DECIMAL(10, 8), not null) -- Latitude
* `lng` (DECIMAL(11, 8), not null) -- Longitude
* `icon` (VARCHAR(255), optional, e.g., path to custom icon)
* `category` (VARCHAR(100), optional, e.g., 'Event', 'Location', 'Character Starting Point')
* `eventTimestamp` (TIMESTAMP with time zone, optional, for chronological sorting)
* `createdAt` (TIMESTAMP with time zone, default now())
* `updatedAt` (TIMESTAMP with time zone, default now())
7. **`character_journeys`**
* `id` (UUID, primary key, default generated)
* `userId` (UUID, foreign key to `users.id`, nullable for public journeys)
* `name` (VARCHAR(255), not null) -- e.g., "Frodo's Journey"
* `description` (TEXT)
* `isPublic` (BOOLEAN, default false)
* `createdAt` (TIMESTAMP with time zone, default now())
* `updatedAt` (TIMESTAMP with time zone, default now())
8. **`journey_points`**
* `id` (UUID, primary key, default generated)
* `journeyId` (UUID, foreign key to `character_journeys.id`, not null)
* `lat` (DECIMAL(10, 8), not null)
* `lng` (DECIMAL(11, 8), not null)
* `order` (INTEGER, not null) -- Sequence in the journey
* `markerId` (UUID, foreign key to `map_markers.id`, optional, link to an event marker)
* `description` (TEXT, optional, description for this leg of the journey)
* `timestamp` (TIMESTAMP with time zone, optional)
**Relationships:**
- `users` 1-to-many `accounts`, `sessions`, `map_layers`, `character_journeys`
- `map_layers` 1-to-many `map_markers`
- `character_journeys` 1-to-many `journey_points`
## 4. CORE FEATURES & USER FLOW:
**a) User Authentication:**
- **Flow:** User lands on the homepage. Clicks 'Sign In/Sign Up'. Redirected to NextAuth.js pages (or modal). Options: GitHub, Google, Email/Password.
- **After Auth:** Redirect to the dashboard or map page. User session is maintained via cookies.
- **Edge Case:** Handle authentication errors gracefully.
**b) Interactive Map Display:**
- **Flow:** Homepage/Map page loads. Displays the Middle-earth map using Leaflet with custom tiles (initially a static high-def image tiled). Map controls (zoom, pan) are enabled.
- **Features:**
- **Marker Loading:** Fetch public `map_markers` from the DB via API route. Render markers with appropriate icons and popups on the map.
- **Layer Control:** A UI panel allows users to toggle visibility of different `map_layers` (initially a few pre-defined layers like 'Major Events', 'Hobbit Locations', 'LOTR Locations'). Authenticated users can see their own layers.
- **Edge Case:** Empty state (no markers loaded), network errors during fetching.
**c) Event Plotting & Timeline:**
- **Flow:** Users can click a button 'Add Event'. A modal/form appears.
- **Form Fields:** Title, Description, Latitude, Longitude, Timestamp (optional), Category (dropdown), Icon (optional).
- **Saving:** If authenticated, the marker is saved to the `map_markers` table associated with a default or selected layer. If not authenticated, prompt to sign in or save temporarily locally.
- **Timeline View:** A separate 'Timeline' page or a collapsible panel displays events sorted by `eventTimestamp`. Each event in the timeline is clickable, centering the map on its location.
- **Edge Case:** Invalid date inputs, missing required fields.
**d) Character Journey Visualization:**
- **Flow:** Users select a pre-defined journey (e.g., 'Frodo's Journey to Mordor') from a list or create a new one.
- **Creation:** Similar to event plotting, but defines a sequence of points (`journey_points`) possibly linked to existing `map_markers`. A UI allows reordering points.
- **Display:** When a journey is selected, a polyline is drawn on the map connecting the `journey_points` in order. Each segment can show a description and/or link to a marker.
- **Edge Case:** Incomplete journey data, disconnected points.
**e) Distance Measurement Tool:**
- **Flow:** User clicks a 'Measure Distance' tool button. Map interaction changes. First click sets a starting point, subsequent clicks set ending points. A line is drawn, and the distance (in leagues or km) is displayed on the map or in a UI panel.
- **Calculation:** Use spherical law of cosines or Haversine formula for accurate distance calculation on a sphere.
- **Edge Case:** User clicks only once, cancels measurement.
**f) User-Specific Layers/Markers (Authenticated Users):**
- **Flow:** Authenticated users have a 'My Map' or 'Dashboard' section.
- **Features:** List their created layers and markers. Ability to edit, delete, or mark layers as public/private.
- **Creation:** Button to 'Create New Layer'. Form for Layer Name, Description.
- **Edge Case:** User tries to edit/delete others' private data.
## 5. API & DATA FETCHING:
- **Next.js App Router:** Utilize Server Components for initial data fetching where possible (e.g., loading public map data on the main map page) and Client Components for interactive elements.
- **Route Handlers (API Routes):**
- `GET /api/markers`: Fetch markers (with optional filters for layerId, public status).
- Response: `[{ id, title, description, lat, lng, icon, category, eventTimestamp, layerId }, ...]`
- `POST /api/markers`: Create a new marker (requires authentication).
- Request Body: `{ title, description, lat, lng, layerId, category, eventTimestamp, icon }`
- Response: ` { success: true, markerId: '...' }`
- `PUT /api/markers/:id`: Update a marker (requires auth).
- `DELETE /api/markers/:id`: Delete a marker (requires auth).
- Similar routes for `layers`, `journeys`, `journey_points`.
- **Data Flow:** Client Components will use libraries like `react-query` or SWR for client-side caching and revalidation of fetched data, or direct `fetch` calls to Route Handlers.
- **Server Actions:** Consider using Server Actions for mutations (POST, PUT, DELETE) directly from forms in Server Components or Client Components for a more streamlined flow.
## 6. COMPONENT BREAKDOWN:
- **`app/page.tsx` (Homepage):** Landing page with app intro, call to action (View Map/Sign Up).
- **`app/map/page.tsx`:** The core interactive map component. Uses Leaflet.js. Renders markers, polylines. Includes controls.
- `components/MapContainer.tsx` (Client Component): Initializes Leaflet map, manages map state.
- `components/Marker.tsx`: Renders individual markers with popups.
- `components/Polyline.tsx`: Renders character journey lines.
- `components/DistanceTool.tsx`: UI for distance measurement.
- `components/LayerSwitcher.tsx`: Toggles layer visibility.
- **`app/auth/signin/page.tsx`:** Sign-in page using NextAuth.js components/providers.
- **`app/dashboard/page.tsx` (Authenticated Users):** User's personal space.
- `components/MyLayersList.tsx`
- `components/MyMarkersList.tsx`
- `components/MyJourneysList.tsx`
- `components/CreateLayerForm.tsx`
- **`app/timeline/page.tsx`:** Displays the chronological events, potentially with a chart component.
- `components/TimelineEvent.tsx`: Individual event item in the list.
- `components/EventChart.tsx`: Visual representation of events over time.
- **`app/layout.tsx`:** Root layout with Navbar, Footer, global providers.
- **`components/ui/...`:** Components from shadcn/ui (Button, Card, Input, Dialog, DropdownMenu, etc.).
- **`components/Navbar.tsx`:** Navigation bar with logo, links, auth status.
- **`components/Footer.tsx`:** Standard footer.
- **`components/EventForm.tsx`:** Modal/form for adding/editing map markers.
- **`components/JourneyForm.tsx`:** Form for creating/editing character journeys.
**State Management:**
- Global state (user auth, map settings) via Context API.
- Local component state for form inputs, UI toggles.
- Map state (center, zoom, loaded markers) managed within `MapContainer.tsx`.
## 7. UI/UX DESIGN & VISUAL IDENTITY:
- **Style:** "Mystical Parchment". A blend of historical, fantasy, and clean UI elements. Evokes a sense of ancient maps and lore.
- **Color Palette:**
- Primary: `#5D4037` (Deep Brown - Earthy, grounded)
- Secondary: `#BCAAA4` (Light Brown/Tan - Parchment)
- Accent: `#795548` (Medium Brown - Depth)
- Highlight: `#FFEB3B` (Golden Yellow - Important markers, links)
- Text: `#3E2723` (Dark Brown), `#757575` (Gray for secondary text)
- Background: `#F5F5DC` (Beige - subtle, not pure white)
- **Typography:**
- Headings: A slightly stylized serif font like 'Merriweather' or 'Playfair Display'.
- Body Text: A clean, readable sans-serif like 'Lato' or 'Open Sans'.
- **Layout:**
- Main map area takes up the largest portion of the screen.
- Sidebar/Panel for Layer Control, Timeline access, Search.
- Clean cards and modals for forms and information popups.
- **Map Tiles:** Use high-resolution fantasy map tiles that fit the theme. Consider Project Hy Borges's work or similar artistic styles.
- **Icons:** Custom icons for markers that are thematic (e.g., a sword for a battle, a ring for a significant event, a hobbit hole for Shire locations).
- **Responsiveness:** Mobile-first approach. Map is usable on smaller screens, potentially with a more streamlined UI. Sidebar might collapse into a menu. Ensure touch targets are large enough.
## 8. SAMPLE/MOCK DATA:
**`map_markers`:**
1. `{ title: "Shire established", description: "The beginning of the Shire.", lat: 55.9, lng: -3.2, category: "Event", eventTimestamp: "T-1600", icon: "hobbit_hole.svg" }`
2. `{ title: "Council of Elrond", description: "Decision to destroy the One Ring made.", lat: 37.2, lng: -80.1, category: "Event", eventTimestamp: "TA 3018-10-25", icon: "council.svg" }`
3. `{ title: "Rivendell", description: "Last Homely House East of the Sea.", lat: 37.1, lng: -80.2, category: "Location", icon: "rivendell.png" }`
4. `{ title: "Mount Doom", description: "The Cracks of Doom, where the Ring was forged and destroyed.", lat: -15.8, lng: 168.1, category: "Location", icon: "volcano.svg" }`
5. `{ title: "Bag End", description: "Frodo Baggins' home.", lat: 55.95, lng: -3.18, category: "Location", icon: "bag_end.svg" }`
**`character_journeys`:**
1. `{ name: "Frodo's Journey to Mordor", description: "From Bag End to Mount Doom.", isPublic: true }`
**`journey_points` (for Frodo):**
1. `{ journeyId: '...', lat: 55.95, lng: -3.18, order: 1, markerId: 'bag_end_id', description: "Leaving the Shire" }`
2. `{ journeyId: '...', lat: 37.1, lng: -80.2, order: 2, markerId: 'rivendell_id', description: "Council of Elrond" }`
3. `{ journeyId: '...', lat: -15.8, lng: 168.1, order: 3, markerId: 'mount_doom_id', description: "Destruction of the Ring" }`
## 9. TURKISH TRANSLATIONS:
- **App Title:** Lore Mapper (MappaLore)
- **Sign In:** Giriş Yap
- **Sign Up:** Kayıt Ol
- **Map:** Harita
- **Timeline:** Zaman Çizelgesi
- **Layers:** Katmanlar
- **My Map:** Benim Haritam
- **Add Event:** Olay Ekle
- **Add Marker:** İşaretçi Ekle
- **Search:** Ara
- **Name:** Ad
- **Description:** Açıklama
- **Latitude:** Enlem
- **Longitude:** Boylam
- **Save:** Kaydet
- **Cancel:** İptal
- **Measure Distance:** Mesafe Ölç
- **Loading...:** Yükleniyor...
- **No data available:** Veri bulunamadı.
- **Create New Layer:** Yeni Katman Oluştur
- **Journey:** Yolculuk
- **Event:** Olay
- **Location:** Konum
- **Character:** Karakter
- **Distance:** Mesafe
- **User Profile:** Kullanıcı Profili
## 10. ANIMATIONS:
- **Page Transitions:** Subtle fade-in/fade-out transitions between pages using Next.js's `useRouter` and Framer Motion (or CSS transitions).
- **Marker Popups:** Smooth expand/collapse animation when clicking markers.
- **Button Hovers:** Slight scale-up or color change on button hover states.
- **Loading States:** Use shimmering placeholders (skeleton loaders) or spinners (`react-spinners`) for data fetching.
- **Map Interactions:** Smooth zoom and pan provided by Leaflet.js.
- **Timeline Entries:** Fade-in effect as new events load or when scrolling.
## 11. EDGE CASES & VALIDATIONS:
- **Authentication:** Ensure all mutation endpoints (`POST`, `PUT`, `DELETE`) are protected and require authentication. Handle unauthenticated access attempts with redirects or error messages.
- **Data Validation:** Use Zod with React Hook Form for robust validation on all user input forms (marker details, layer creation, etc.). Ensure lat/lng are within valid ranges. Timestamps should be parseable.
- **Empty States:** Design informative empty states for the map (e.g., "No markers added yet. Click 'Add Event' to start."), timeline, and user dashboard lists.
- **Error Handling:** Implement try-catch blocks in API routes and Server Actions. Display user-friendly error messages using toasts (e.g., using `react-hot-toast` or shadcn/ui's toast component).
- **Map Bounds:** Ensure the initial map view is set to Middle-earth's approximate bounds. Prevent users from panning too far outside the map area if using static tiles.
- **Large Data Sets:** For performance, implement pagination or lazy loading for markers and timeline events if the number grows significantly.
- **Concurrency:** Consider potential race conditions if multiple users edit the same public layer simultaneously (though less likely in MVP). Add basic checks or optimistic UI updates.
- **Responsive Design:** Ensure usability across various devices and screen sizes. Test thoroughly on mobile, tablet, and desktop.