A comprehensive full-stack web application that helps users discover, generate, and customize running, cycling, and walking routes based on their preferences. The app features interactive maps, route analytics, and personalized recommendations using Google Maps API.
- User Authentication: Secure signup/login with Firebase Authentication
- User Profiles: Customizable profiles with route preferences
- Route Discovery: Search and filter routes by distance, terrain, and type
- Route Generation: Generate custom routes using Google Maps Directions API
- Interactive Maps: Visualize routes on Google Maps with elevation data
- Route Management: Create, read, update, and delete routes (CRUD)
- Favorites: Save favorite routes for quick access
- Route Analytics: View distance, elevation gain, estimated time, and difficulty
- RESTful API with Express.js backend
- PostgreSQL database with Supabase
- Vue.js frontend with Vite
- Tailwind CSS for styling
- Google Maps API integration
- Firebase-based authentication
- Unit tests for frontend and backend
- Vue 3 with Vite
- Vue Router for navigation
- Pinia for state management
- Tailwind CSS for styling
- @googlemaps/js-api-loader for map integration
- Recharts for elevation profile visualization
- Firebase for authentication
- Axios for API calls
- Node.js with Express.js
- PostgreSQL database (via Supabase)
- Firebase Admin SDK for authentication
- express-validator for input validation
- Axios for external API calls
- Jest for unit testing
- Supertest for API testing
- Vitest for frontend testing
Before you begin, ensure you have the following installed:
- Node.js (v18 or higher)
- npm or yarn
- PostgreSQL (or use Supabase free tier)
- Google Maps API key
git clone <your-repo-url>
cd RunRoutescd backend
npm installOption A: Using Supabase (Recommended for free tier)
- Create a free account at Supabase
- Create a new project
- Go to SQL Editor and run the schema from
backend/database/schema.sql - Copy your database connection string from Project Settings → Database
Option B: Local PostgreSQL
- Install PostgreSQL locally
- Create a database:
CREATE DATABASE runroutes;- Run the schema:
psql -U postgres -d runroutes -f backend/database/schema.sqlCreate a .env file in the backend directory:
NODE_ENV=development
PORT=5000
DATABASE_URL=postgresql://user:password@host:port/database
FIREBASE_SERVICE_ACCOUNT={"type":"service_account","project_id":"..."}
# OR use FIREBASE_PROJECT_ID for default credentials
FIREBASE_PROJECT_ID=your-firebase-project-id
GOOGLE_MAPS_API_KEY=your-google-maps-api-keynpm run devThe backend will run on http://localhost:5000
cd frontend
npm installCreate a .env file in the frontend directory:
VITE_API_URL=http://localhost:5000/api
VITE_GOOGLE_MAPS_API_KEY=your-google-maps-api-key
VITE_FIREBASE_API_KEY=your-firebase-api-key
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-firebase-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
VITE_FIREBASE_APP_ID=your-app-idnpm run devThe frontend will run on http://localhost:3000
- Go to Firebase Console
- Create a new project or select an existing one
- Enable Authentication → Email/Password sign-in method
- Go to Project Settings → Service Accounts
- Generate a new private key (download JSON file)
- Copy the JSON content to
FIREBASE_SERVICE_ACCOUNTin backend.env(as a JSON string) - Get your Firebase config from Project Settings → General → Your apps
- Add Firebase config to frontend
.envfile
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the following APIs:
- Maps JavaScript API
- Directions API
- Elevation API
- Create credentials (API Key)
- Add the API key to your
.envfiles
The application will be available at:
- Frontend:
http://localhost:3000 - Backend:
http://localhost:5000 - Database:
localhost:5432
cd backend
npm testcd frontend
npm testPOST /api/auth/register- Create user profile (after Firebase registration)
GET /api/users/profile- Get user profile (Protected)PUT /api/users/profile- Update user profile (Protected)
GET /api/routes- Get all routes (with filters)GET /api/routes/:id- Get a single routePOST /api/routes- Create a new route (Protected)POST /api/routes/generate- Generate a route using Google Maps (Protected)PUT /api/routes/:id- Update a route (Protected, owner only)DELETE /api/routes/:id- Delete a route (Protected, owner only)
GET /api/favorites- Get user's favorite routes (Protected)POST /api/favorites/:routeId- Add route to favorites (Protected)DELETE /api/favorites/:routeId- Remove route from favorites (Protected)
id(SERIAL PRIMARY KEY)uid(VARCHAR, UNIQUE) - Firebase UIDemail(VARCHAR, UNIQUE)name(VARCHAR)location(VARCHAR)preferences(JSONB)profile_picture_url(VARCHAR)created_at(TIMESTAMP)updated_at(TIMESTAMP)
id(SERIAL PRIMARY KEY)user_id(INTEGER, FK → Users)route_name(VARCHAR)distance(DECIMAL)estimated_time(INTEGER)terrain_type(VARCHAR)elevation_gain(DECIMAL)waypoints(JSONB)visibility(VARCHAR)created_at(TIMESTAMP)updated_at(TIMESTAMP)
id(SERIAL PRIMARY KEY)user_id(INTEGER, FK → Users)route_id(INTEGER, FK → Routes)created_at(TIMESTAMP)
RunRoutes/
├── backend/
│ ├── config/
│ │ ├── database.js
│ │ └── firebase.js
│ ├── database/
│ │ └── schema.sql
│ ├── middleware/
│ │ └── auth.js (Firebase token verification)
│ ├── routes/
│ │ ├── auth.js
│ │ ├── routes.js
│ │ ├── users.js
│ │ └── favorites.js
│ ├── services/
│ │ └── mapsService.js
│ ├── tests/
│ │ ├── auth.test.js
│ │ └── routes.test.js
│ ├── utils/
│ │ ├── validation.js
│ │ └── userHelper.js
│ ├── server.js
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ └── Navbar.vue
│ │ ├── stores/
│ │ │ └── auth.js (Pinia store)
│ │ ├── pages/
│ │ │ ├── Home.vue
│ │ │ ├── Login.vue
│ │ │ ├── Register.vue
│ │ │ ├── Dashboard.vue
│ │ │ ├── RouteSearch.vue
│ │ │ ├── RouteDetails.vue
│ │ │ └── Profile.vue
│ │ ├── router/
│ │ │ └── index.js
│ │ ├── services/
│ │ │ └── api.js
│ │ ├── config/
│ │ │ └── firebase.js
│ │ ├── App.vue
│ │ ├── main.js
│ │ └── index.css
│ ├── package.json
│ └── vite.config.js
├── .gitignore
└── README.md
- Authentication handled by Firebase (secure password hashing)
- Firebase ID tokens for API authentication
- Protected routes require authentication
- Input validation on all endpoints
- SQL injection prevention using parameterized queries
- CORS configured for frontend domain
- Firebase Admin SDK verifies tokens server-side
- OAuth integration (Google/GitHub)
- Weather API integration
- Route sharing via link
- Comments and ratings on routes
- Leaderboard for popular routes
- Offline map caching
- Strava API integration
- Real-time route tracking
- Mobile app (React Native)
- QUICKSTART.md - Fast setup guide
- API.md - Basic API reference
- API Documentation - Full API reference with examples
- Architecture - System design and technical details
- Route Generation Logic - Deep dive into route generation algorithm
- Troubleshooting - Common issues and solutions
Built with Vue.js, Node.js, Firebase, and Google Maps API