A full-stack web application for planning day trips in Singapore. Discover tourist attractions, get AI-powered recommendations, build itineraries, find optimal routes, and check real-time weather — all in one place.
User Authentication — Secure signup/login with bcrypt password hashing and JWT tokens stored in HTTP-only cookies
Interactive Map — Explore Singapore with a Leaflet-powered map showing tourist attractions, your live location, and nearby points of interest
AI Chat Assistant — Get personalized Singapore tour recommendations via a Groq-powered AI chatbot that understands attractions, food, culture, and nightlife
Itinerary Builder — Add places from the map or chat to a per-day itinerary, saved locally for quick access
Route Optimization — Calculate the optimal driving route between your itinerary stops using OpenRouteService with waypoint optimization
Real-Time Weather — View current temperature, wind speed, and conditions for any location on the map via Open-Meteo
Nearest Bus Stop Finder — Find the closest bus stop to any map click using Singapore's LTA DataMall API
Tourist Attractions Data — Fetch live Singapore attraction data from Singapore's official data.gov.sg open data API
Responsive UI — Clean, mobile-friendly interface built with Tailwind CSS and smooth Framer Motion animations
Protected Routes — Dashboard, chat, itinerary, and account pages are guarded behind authentication
Technology
Purpose
React 19
UI framework
TypeScript 5.8
Type safety
Vite 7
Build tool & dev server
Tailwind CSS 4
Utility-first styling
React Router 6
Client-side routing
Leaflet / React-Leaflet
Interactive maps
Framer Motion
Animations
React Markdown
Rendering chat responses
Axios
HTTP client (available)
Technology
Purpose
Node.js 20
Runtime
Express 5
HTTP server & routing
MySQL 2
Database driver (connection pool)
Supabase
Alternative cloud database
bcrypt
Password hashing
JSON Web Tokens
Authentication
Groq SDK
AI chat completions
dotenv
Environment configuration
┌─────────────────────┐ ┌─────────────────────────┐
│ │ REST │ │
│ React Frontend │◄───────►│ Express Backend │
│ (Vite Dev :5173) │ /api/* │ (:5005) │
│ │ │ │
└─────────────────────┘ └──────────┬──────────────┘
│
┌──────────────────────┬┼──────────────────────┐
│ │ │
┌─────▼─────┐ ┌───────▼──────┐ ┌───────▼──────┐
│ MySQL / │ │ External │ │ External │
│ Supabase │ │ APIs │ │ APIs │
│ (Users) │ │ (Groq, ORS) │ │ (LTA, Gov) │
└────────────┘ └──────────────┘ └──────────────┘
day-planner-sg/
├── .gitignore
├── README.md
│
├── backend/
│ ├── package.json
│ ├── server.js # Entry point — starts Express on PORT
│ ├── app.js # Express app config, CORS, middleware, routes
│ ├── .env.example # Template for required environment variables
│ ├── controllers/
│ │ ├── authController.js # Signup, login, logout, JWT verification
│ │ ├── userController.js # User profile endpoints
│ │ ├── attractionController.js # Fetches attractions from data.gov.sg
│ │ ├── chatController.js # Proxies messages to Groq AI
│ │ ├── tripController.js # Bus stops (LTA) & weather (Open-Meteo)
│ │ └── orsController.js # Route optimization via OpenRouteService
│ ├── routes/
│ │ ├── authRoutes.js
│ │ ├── userRoutes.js
│ │ ├── placesRoutes.js
│ │ ├── tripRoutes.js
│ │ ├── chatRouter.js
│ │ └── orsRouter.js
│ ├── Services/
│ │ ├── userService.js # User CRUD (MySQL / Supabase)
│ │ ├── chatService.js # Groq API integration
│ │ ├── tripService.js # LTA DataMall integration
│ │ └── orsService.js # OpenRouteService integration
│ ├── utils/
│ │ ├── db.js # Serverless-friendly MySQL pool singleton
│ │ └── supabase.js # Supabase client initialization
│ └── sql/
│ └── schema.sql # Database schema (users table)
│
└── frontend/
├── package.json
├── vite.config.ts
├── tsconfig.json
├── tailwind.config.js
├── index.html
├── public/ # Static assets (images)
└── src/
├── main.tsx # React entry point
├── App.tsx # Route definitions
├── index.css # Global styles
├── utils/
│ ├── api.ts # Centralized fetch wrapper (VITE_API_BASE_URL)
│ └── Protectedroutes.tsx # Auth guard for private routes
├── Component/
│ ├── Map.tsx # Leaflet map with markers, routes, geolocation
│ ├── Navbar.tsx # Navigation bar
│ ├── NavbarLayout.tsx # Layout wrapper with navbar
│ └── weather.tsx # Weather display widget
├── context/
│ ├── ChatContext.tsx # Chat state management
│ └── ItineraryContext.tsx # Itinerary state management
├── data/
│ └── TouristAttractions.geojson
└── pages/
├── Landing.tsx # Public landing page
├── Login.tsx # Login form
├── Signup.tsx # Registration form
├── Dashboard.tsx # Main dashboard with map & weather
├── chat.tsx # AI chat interface
├── Itinerary.tsx # Itinerary builder with route map
└── Account.tsx # User account settings
Node.js 20.x or higher
npm 9+ (bundled with Node.js)
MySQL 8.0+ (or a Supabase project)
API keys for the external services (see Environment Variables )
git clone https://github.com/< your-username> /day-planner-sg.git
cd day-planner-sg
Run the schema script to create the database and tables:
mysql -u root -p < backend/sql/schema.sql
Or if using Supabase, create a users table matching the schema in backend/sql/schema.sql.
3. Configure environment variables
Backend — copy the example and fill in your values:
cp backend/.env.example backend/.env
Frontend — create the dev environment file:
echo " VITE_API_BASE_URL=http://localhost:5005" > frontend/.env.development
See Environment Variables for a full list of required keys.
4. Install dependencies & start
# Terminal 1 — Backend
cd backend
npm install
npm run dev # Starts on http://localhost:5005
# Terminal 2 — Frontend
cd frontend
npm install
npm run dev # Starts on http://localhost:5173
Open http://localhost:5173 in your browser.
Variable
Description
Example
PORT
Server port
5005
NODE_ENV
Environment mode
development
DB_HOST
MySQL host
localhost
DB_USER
MySQL username
root
DB_PASSWORD
MySQL password
yourpassword
DB_NAME
MySQL database name
day_planner
DB_CONN_LIMIT
Connection pool limit
10
JWT_SECRET
Secret key for signing JWTs
a-long-random-string
COOKIE_NAME
Auth cookie name
auth_token
JWT_EXPIRES_IN
Token expiry duration
7d
CORS_ORIGINS
Allowed frontend origins (comma-separated)
http://localhost:5173
GROQ_API_KEY
Groq API key for AI chat
gsk_...
ORS_API_KEY
OpenRouteService API key
5b3ce3597851110001...
LTA_API_KEY
Singapore LTA DataMall API key
your-lta-key
SUPABASE_URL
Supabase project URL (optional)
https://xxx.supabase.co
SUPABASE_KEY
Supabase service role key (optional)
eyJ...
Frontend (frontend/.env.development)
Variable
Description
Example
VITE_API_BASE_URL
Backend API base URL
http://localhost:5005
Note: In production, leave VITE_API_BASE_URL empty so requests go to relative /api/* paths (useful for reverse-proxy setups).
Method
Endpoint
Description
POST
/api/auth/signup
Register a new user
POST
/api/auth/login
Log in and receive auth cookie
POST
/api/auth/logout
Clear auth cookie
Method
Endpoint
Description
GET
/api/users/about
Get current user profile (protected)
Method
Endpoint
Description
GET
/api/attractions/places
Fetch Singapore tourist attractions
Method
Endpoint
Description
GET
/api/trips/busstop
Get all Singapore bus stops
GET
/api/trips/weather?lat=&lng=
Get current weather for coordinates
Method
Endpoint
Description
POST
/api/chat
Send a message to the AI assistant
Method
Endpoint
Description
POST
/api/ors
Calculate optimized driving route
Method
Endpoint
Description
GET
/api/health
Server health check
API
Purpose
Sign Up
Groq
AI chat completions (LLM)
Free tier available
OpenRouteService
Driving route optimization
Free tier (2,000 req/day)
LTA DataMall
Singapore bus stops data
Free with registration
data.gov.sg
Singapore tourist attractions dataset
No key required
Open-Meteo
Weather forecasts
Free, no key required
Command
Description
npm run dev
Start Vite dev server with HMR
npm run build
Type-check and build for production
npm run preview
Preview production build locally
npm run lint
Run ESLint
Command
Description
npm run dev
Start with nodemon (auto-restart)
npm start
Start with Node.js directly
Fork the repository
Create a feature branch (git checkout -b feature/my-feature)
Commit your changes (git commit -m "Add my feature")
Push to the branch (git push origin feature/my-feature)
Open a Pull Request
Please use descriptive commit messages and keep PRs focused on a single concern.
This project is open source and available under the MIT License .