# balakamatchi/ai_travel_planner architecture

> Architecture diagram of the GitHub repository balakamatchi/ai_travel_planner, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/balakamatchi/ai_travel_planner
- Repository: https://github.com/balakamatchi/ai_travel_planner

## Overview

#### Purpose and entry points
AI Travel Planner is a MERN application for authenticated trip planning, AI itinerary generation, budgeting, maps, and photo journals. The React/Vite client starts at `client/src/main.jsx` and composes routes/UI in `client/src/App.jsx`. The Express API starts at `server/server.js`, connects MongoDB through `server/config/db.js`, and mounts resource routes.

#### Client application shell and session boundary
`client/src/context/AuthContext.jsx` restores the session through `/api/auth/me`, owns login/logout state, and supplies credentials to protected UI. `client/src/services/api.js` is the Axios boundary: it attaches the locally stored JWT and handles global 401 logout behavior. `client/src/components/ProtectedRoute.jsx` guards private routes; `client/src/components/DashboardLayout.jsx` provides the authenticated navigation shell. Theme state is independently managed and persisted by `client/src/context/ThemeContext.jsx`.

#### API security and request pipeline
`server/server.js` configures Express, CORS scoped to `CLIENT_URL`, cookie parsing, JSON handling, and centralized errors. Protected resource routes pass through JWT authentication in `server/middleware/auth.js`, accepting bearer token or cookie and attaching the owning user to `req.user`. Validation, multipart handling, and normalized API failures form key boundaries in `server/middleware/validate.js`, `server/middleware/upload.js`, and `server/middleware/errorHandler.js`.

#### Domain persistence and ownership model
MongoDB/Mongoose persists four user-owned collections: `server/models/User.js`, `server/models/Trip.js`, `server/models/Expense.js`, and `server/models/Journal.js`. Trips are the aggregate center: expenses and journal records reference both trip and user. Controllers scope reads and mutations to `req.user._id`; permanent trip deletion cascades related expenses and journals. Non-cancelled trip state is computed from travel dates via `server/utils/getTripStatus.js`, rather than persisted.

#### Trip planning and AI generation flow
The planner UI invokes `client/src/services/aiService.js` from `client/src/pages/AITripPlannerPage.jsx`. API endpoints in `server/routes/aiRoutes.js` route to `server/controllers/aiController.js`, which either returns a preview or persists an AI-generated Trip. `server/utils/aiService.js` calls Google Gemini for structured itinerary JSON, sanitizes model-derived values, and falls back to deterministic mock plans when unavailable or invalid. It separately queries Unsplash for destination cover images. AI endpoints are rate-limited to bound cost and abuse.

#### Trip lifecycle, budgets, and visualization
Trip CRUD flows through `client/src/services/tripService.js` and `server/controllers/tripController.js`; UI pages include trip list/details and dashboard views. Expense CRUD flows through `client/src/services/expenseService.js` and `server/controllers/expenseController.js`, producing per-trip totals/category breakdowns for the budget tracker. A Trip’s AI-produced `places` data crosses into `client/src/pages/MapViewPage.jsx`, where React Leaflet renders valid coordinates on OpenStreetMap tiles with type filtering.

#### Media and journal subsystem
Journal UI/service calls (`client/src/pages/TravelJournalPage.jsx`, `client/src/services/journalService.js`) reach `server/controllers/journalController.js`. Multer streams avatar and journal images using Cloudinary storage configured in `server/config/cloudinary.js`; journal deletion also removes Cloudinary assets. Profile operations are handled by `server/controllers/userController.js`, including avatar replacement and dashboard aggregation.

#### Runtime and external dependencies
The frontend is React 18/Vite with React Router, Tailwind, Leaflet, Recharts, and Framer Motion. The backend is Node.js 18+ and Express with MongoDB/Mongoose. Required infrastructure is MongoDB and Cloudinary; Gemini and Unsplash are optional due to graceful AI/mock and cover-image fallbacks. The root project runs client and server concurrently; client production output is independently deployable.

Main entry points: [`client/src/services/api.js`](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/services/api.js) (API client), [`server/middleware/auth.js`](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/middleware/auth.js) (JWT authentication), [`server/controllers/journalController.js`](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/journalController.js) (Journal and profile APIs), [`server/controllers/aiController.js`](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/aiController.js) (AI generation API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["React client"]
  node_client_shell["App routes and UI<br/>React/Vite app<br/>[App.jsx]"]
  node_auth_context["Session state<br/>React context<br/>[AuthContext.jsx]"]
  node_api_client["API client<br/>Axios boundary<br/>[api.js]"]
  node_protected_ui["Protected app shell<br/>route guard/layout<br/>[ProtectedRoute.jsx]"]
  node_ai_planner["AI trip planner<br/>planner page/service"]
  node_trip_budget_ui["Trips and budgets<br/>pages/services<br/>[tripService.js]"]
  node_map_ui["Map view<br/>Leaflet page<br/>[MapViewPage.jsx]"]
  node_journal_ui["Travel journal<br/>page/service"]
end

subgraph group_api["Express API"]
  node_server["Express server<br/>API entry point<br/>[server.js]"]
  node_auth_middleware["JWT authentication<br/>Express middleware<br/>[auth.js]"]
  node_resource_controllers["Trip and expense APIs<br/>controllers<br/>[tripController.js]"]
  node_ai_controller["AI generation API<br/>controller/routes<br/>[aiController.js]"]
  node_ai_service["Itinerary generation<br/>AI integration<br/>[aiService.js]"]
  node_journal_controller["Journal and profile APIs<br/>controllers"]
  node_upload["Media upload pipeline<br/>Multer middleware<br/>[upload.js]"]
end

subgraph group_data["Persistence"]
  node_mongo[("MongoDB<br/>Mongoose database<br/>[db.js]")]
  node_trip_model["Trip aggregate<br/>Mongoose model<br/>[Trip.js]"]
end

subgraph group_external["External services"]
  node_cloudinary[("Cloudinary<br/>media storage<br/>[cloudinary.js]")]
  node_gemini["Google Gemini<br/>AI provider"]
  node_unsplash["Unsplash<br/>image provider"]
end

node_client_shell -->|"uses"| node_auth_context
node_auth_context -->|"restores /api/auth/me"| node_api_client
node_client_shell -->|"private routes"| node_protected_ui
node_ai_planner -->|"generation requests"| node_api_client
node_trip_budget_ui -->|"trip and expense CRUD"| node_api_client
node_journal_ui -->|"journal requests"| node_api_client
node_map_ui -->|"uses trip places"| node_trip_budget_ui
node_api_client -->|"REST API"| node_server
node_server -->|"protects resources"| node_auth_middleware
node_auth_middleware -->|"req.user"| node_resource_controllers
node_auth_middleware -->|"req.user"| node_ai_controller
node_auth_middleware -->|"req.user"| node_journal_controller
node_resource_controllers -->|"CRUD and cascade deletion"| node_trip_model
node_trip_model -->|"persists"| node_mongo
node_ai_controller -->|"generate plan"| node_ai_service
node_ai_controller -->|"persist generated trip"| node_trip_model
node_ai_service -->|"structured itinerary"| node_gemini
node_ai_service -->|"cover image"| node_unsplash
node_journal_controller -->|"multipart media"| node_upload
node_upload -->|"stream uploads"| node_cloudinary
node_journal_controller -->|"journals and users"| node_mongo
node_journal_controller -->|"remove deleted assets"| node_cloudinary

click node_client_shell "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/App.jsx"
click node_auth_context "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/context/AuthContext.jsx"
click node_api_client "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/services/api.js"
click node_protected_ui "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/components/ProtectedRoute.jsx"
click node_ai_planner "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/pages/AITripPlannerPage.jsx"
click node_trip_budget_ui "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/services/tripService.js"
click node_map_ui "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/pages/MapViewPage.jsx"
click node_journal_ui "https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/pages/TravelJournalPage.jsx"
click node_server "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/server.js"
click node_auth_middleware "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/middleware/auth.js"
click node_resource_controllers "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/tripController.js"
click node_ai_controller "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/aiController.js"
click node_ai_service "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/utils/aiService.js"
click node_journal_controller "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/journalController.js"
click node_upload "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/middleware/upload.js"
click node_mongo "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/config/db.js"
click node_trip_model "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/models/Trip.js"
click node_cloudinary "https://github.com/balakamatchi/ai_travel_planner/blob/main/server/config/cloudinary.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_client_shell,node_auth_context,node_api_client,node_protected_ui,node_ai_planner,node_trip_budget_ui,node_map_ui,node_journal_ui toneBlue
class node_server,node_auth_middleware,node_resource_controllers,node_ai_controller,node_ai_service,node_journal_controller,node_upload toneAmber
class node_mongo,node_trip_model toneMint
class node_cloudinary,node_gemini,node_unsplash toneRose
```

## Components

### React client

- [App routes and UI](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/App.jsx): React/Vite app · `client/src/App.jsx`
- [Session state](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/context/AuthContext.jsx): React context · Restores the authenticated user and owns login/logout state. · `client/src/context/AuthContext.jsx`
- [API client](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/services/api.js): Axios boundary · Attaches JWTs and triggers global logout on 401 responses. · `client/src/services/api.js`
- [Protected app shell](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/components/ProtectedRoute.jsx): route guard/layout · `client/src/components/ProtectedRoute.jsx`
- [AI trip planner](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/pages/AITripPlannerPage.jsx): planner page/service · `client/src/pages/AITripPlannerPage.jsx`
- [Trips and budgets](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/services/tripService.js): pages/services · Trip and expense UI presents trip details, totals, and category breakdowns. · `client/src/services/tripService.js`
- [Map view](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/pages/MapViewPage.jsx): Leaflet page · Renders valid AI trip places on OpenStreetMap tiles. · `client/src/pages/MapViewPage.jsx`
- [Travel journal](https://github.com/balakamatchi/ai_travel_planner/blob/main/client/src/pages/TravelJournalPage.jsx): page/service · `client/src/pages/TravelJournalPage.jsx`

### Express API

- [Express server](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/server.js): API entry point · Configures CORS, cookies, JSON parsing, routes, and centralized errors. · `server/server.js`
- [JWT authentication](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/middleware/auth.js): Express middleware · Accepts bearer tokens or cookies and attaches the owner to req.user. · `server/middleware/auth.js`
- [Trip and expense APIs](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/tripController.js): controllers · Scopes CRUD and budget aggregations to the authenticated user. · `server/controllers/tripController.js`
- [AI generation API](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/aiController.js): controller/routes · Returns previews or persists generated trips; endpoints are rate-limited. · `server/controllers/aiController.js`
- [Itinerary generation](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/utils/aiService.js): AI integration · Sanitizes Gemini output and falls back to deterministic mock plans. · `server/utils/aiService.js`
- [Journal and profile APIs](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/controllers/journalController.js): controllers · Manages journals, images, avatars, and dashboard aggregation. · `server/controllers/journalController.js`
- [Media upload pipeline](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/middleware/upload.js): Multer middleware · `server/middleware/upload.js`

### Persistence

- [MongoDB](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/config/db.js): Mongoose database · Stores user-owned users, trips, expenses, and journals. · `server/config/db.js`
- [Trip aggregate](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/models/Trip.js): Mongoose model · Expenses and journals reference this user-owned aggregate. · `server/models/Trip.js`

### External services

- [Cloudinary](https://github.com/balakamatchi/ai_travel_planner/blob/main/server/config/cloudinary.js): media storage · Stores avatars and journal images; deleted journal assets are removed. · `server/config/cloudinary.js`
- **Google Gemini**: AI provider
- **Unsplash**: image provider · Provides optional destination cover images.

## Connections

- App routes and UI → Session state: uses
- Session state → API client: restores /api/auth/me
- App routes and UI → Protected app shell: private routes
- AI trip planner → API client: generation requests
- Trips and budgets → API client: trip and expense CRUD
- Travel journal → API client: journal requests
- Map view → Trips and budgets: uses trip places
- API client → Express server: REST API
- Express server → JWT authentication: protects resources
- JWT authentication → Trip and expense APIs: req.user
- JWT authentication → AI generation API: req.user
- JWT authentication → Journal and profile APIs: req.user
- Trip and expense APIs → Trip aggregate: CRUD and cascade deletion
- Trip aggregate → MongoDB: persists
- AI generation API → Itinerary generation: generate plan
- AI generation API → Trip aggregate: persist generated trip
- Itinerary generation → Google Gemini: structured itinerary
- Itinerary generation → Unsplash: cover image
- Journal and profile APIs → Media upload pipeline: multipart media
- Media upload pipeline → Cloudinary: stream uploads
- Journal and profile APIs → MongoDB: journals and users
- Journal and profile APIs → Cloudinary: remove deleted assets
