RouteScout is an AI-powered travel assistant built with Spring Boot that combines Google's Gemini AI and Google Maps API to provide intelligent location suggestions, discover points of interest along your route, generate turn-by-turn driving directions, and find nearby amenities. Simply describe what you're looking for in natural language, and RouteScout will help you plan your journey with personalized recommendations.
RouteScout is a full-stack application consisting of:
-
Backend: Spring Boot REST API (port 5001)
- AI-powered location suggestions using Google Gemini
- Route generation with Google Maps API
- Nearby places search functionality
-
Frontend: React UI (port 3000)
- User interface for interacting with the RouteScout API
- Located in
ui/saasquatch-ui/ - See UI README for detailed frontend setup
Before setting up RouteScout, ensure you have the following installed:
-
Java JDK 17+: RouteScout requires Java Development Kit 17 or higher
- Mac: Install using Homebrew
brew install --cask corretto@17
- Windows: Download the
.msiinstaller from AWS Corretto and run it - Verify installation:
java -version
- Mac: Install using Homebrew
-
Maven: Included via Maven Wrapper (
mvnw), no separate installation needed -
PostgreSQL Database: Required for data persistence
- Install PostgreSQL 12 or higher
- Create a database for the application
-
Google API Key: Required for Gemini AI integration
- Obtain an API key from Google AI Studio
- Node.js 14+: Required for running the React UI
- Mac: Install using Homebrew
brew install node
- Windows: Download the installer from nodejs.org
- Verify installation:
node -v npm -v
- Mac: Install using Homebrew
RouteScout requires API keys for Google Gemini and Google Maps services. These should be configured directly in the application configuration files.
| Key | Description | How to Obtain | Required APIs |
|---|---|---|---|
| Google API Key | Google Gemini API key for AI-powered location suggestions | Google AI Studio | Gemini API |
| Google Maps API Key | Google Maps API key for route generation, directions, and map visualization | Google Cloud Console | Directions API, Places API (New), Maps JavaScript API |
Configure your API keys in the YAML configuration files:
For Production/Development:
Edit src/main/resources/application.yaml:
google:
api:
key: your_google_api_key_here
maps:
key: your_google_maps_api_key_hereFor Testing:
Edit src/main/resources/application-test.yaml:
google:
api:
key: your_google_api_key_here
maps:
key: your_google_maps_api_key_hereFor Frontend (React UI):
Create or edit ui/saasquatch-ui/.env:
REACT_APP_BASE_URL=http://localhost:5001
REACT_APP_GOOGLE_MAPS_API_KEY=your_google_maps_api_key_hereImportant Notes:
- The frontend
REACT_APP_GOOGLE_MAPS_API_KEYshould use the same Google Maps API key as the backend - Ensure Maps JavaScript API is enabled in your Google Cloud Console for map visualization to work
- The frontend API key is used for client-side map rendering with the
@react-google-maps/apilibrary
Security Note: Never commit API keys to version control. Add these configuration files to .gitignore or use environment-specific configurations.
git clone <repository-url>
cd saasquatchConfigure your Google API keys in the configuration files as described in the API Configuration section above.
Note: On Windows, replace
./mvnwwith.\mvnw
./mvnw clean installYou should see a BUILD SUCCESS message if everything is set up correctly.
./mvnw spring-boot:runThe application will start on port 5001.
Once the application is running, you can access:
- Swagger UI: http://localhost:5001/swagger-ui/index.html
- Interactive API documentation where you can test endpoints directly
You should now have RouteScout running locally!
The RouteScout React UI provides a user-friendly interface for interacting with the backend API, including Google Maps visualization for routes.
cd ui/saasquatch-uinpm installThis will install all required packages including:
- React and core dependencies
@react-google-maps/apifor Google Maps integration- Axios for API calls
- SASS for styling
Create a .env file in the ui/saasquatch-ui/ directory with your API keys:
REACT_APP_BASE_URL=http://localhost:5001
REACT_APP_GOOGLE_MAPS_API_KEY=your_google_maps_api_key_hereSee the API Configuration section for details on obtaining API keys.
npm startThe UI will start on port 3000 and automatically open in your browser at http://localhost:3000.
Ensure the backend is running on port 5001 before using the UI. The frontend will make API calls to http://localhost:5001.
For more detailed information about the UI, including available scripts and configuration options, see the UI README.
RouteScout provides AI-powered location suggestions through the /suggest endpoint.
Description: Health check endpoint to verify the service is available.
URL: http://localhost:5001/suggest
Method: GET
Response:
{
"status": "Service available"
}Postman Setup:
- Create a new GET request
- Enter URL:
http://localhost:5001/suggest - Click Send
Description: Get AI-powered location suggestions based on natural language queries.
URL: http://localhost:5001/suggest
Method: POST
Headers:
Content-Type:application/json
Request Body:
{
"message": "Find me a quiet coffee shop to study"
}Response (Success - 200 OK):
{
"suggestions": [
{
"name": "The Study Cafe",
"type": "Cafe",
"address": "123 Main Street, Charleston, SC",
"reason": "Quiet atmosphere with comfortable seating, free WiFi, and outlets at every table."
},
{
"name": "Bookworm Coffee House",
"type": "Cafe",
"address": "456 King Street, Charleston, SC",
"reason": "Library-inspired decor with private study nooks and a strict quiet policy after 2pm."
}
]
}Response (Error - 400 Bad Request):
{
"error": "Message is required."
}Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/suggest - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "message": "Find me a coffee shop on a route between Daniel Island, SC and James Island, SC" } - Click Send
Example Queries:
- "Find me a coffee shop with WiFi"
- "I need a quiet place to study"
- "Suggest parks for a family picnic"
- "Looking for restaurants with outdoor seating"
Description: Get AI-powered points of interest (POIs) along a route between two locations. This endpoint can find real places along your route, optionally filtered by a natural language query describing what you're looking for.
URL: http://localhost:5001/suggest/POIs
Method: POST
Headers:
Content-Type:application/json
Request Body:
{
"origin": "Charleston, SC",
"destination": "Columbia, SC",
"query": "coffee shops"
}Request Parameters:
origin(required): Starting location (address, city, or landmark)destination(required): Ending location (address, city, or landmark)query(optional): Natural language description of what type of POI you're looking for
Response (Success - 200 OK):
{
"suggestions": [
{
"name": "Starbucks Coffee",
"type": "cafe",
"address": "1234 Highway 26, Summerville, SC 29485",
"reason": "Popular coffee shop chain with comfortable seating and WiFi"
},
{
"name": "The Daily Grind",
"type": "cafe",
"address": "5678 Main St, Orangeburg, SC 29115",
"reason": "Local coffee shop known for artisan drinks and cozy atmosphere"
}
]
}Response (Error - 400 Bad Request):
{
"error": "Origin and Destination are required."
}Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/suggest/POIs - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "origin": "Daniel Island, SC", "destination": "James Island, SC", "query": "gas stations" } - Click Send
cURL Example:
curl -X POST http://localhost:5001/suggest/POIs \
-H "Content-Type: application/json" \
-d '{
"origin": "Charleston, SC",
"destination": "Columbia, SC",
"query": "restaurants"
}'Example Queries:
- "coffee shops" - Find coffee shops along your route
- "gas stations" - Locate gas stations for refueling
- "restaurants with outdoor seating" - Find dining options
- "parks" - Discover parks and rest areas
- Leave
queryempty for general AI-suggested POIs
How It Works:
- With query: The AI parses your natural language query into place types, then searches for real POIs along your route using Google Maps API
- Without query: Returns AI-generated POI suggestions based on the route
Requirements:
- Both
GOOGLE_API_KEY(for AI parsing) andGOOGLE_MAPS_API_KEY(for POI search) must be configured inapplication.yamlorapplication-test.yaml - Origin and destination should be valid location strings
RouteScout provides route generation and turn-by-turn directions using Google Maps API.
Description: Generate a driving route with step-by-step directions between two locations.
URL: http://localhost:5001/route/generateRoute
Method: POST
Headers:
Content-Type:application/json
Request Body:
{
"origin": "Charleston, SC",
"destination": "Columbia, SC"
}Response (Success - 200 OK):
{
"origin": "Charleston, SC",
"destination": "Columbia, SC",
"distance": "114 mi",
"duration": "1 hour 53 mins",
"instructions": [
"Head northwest on Meeting St toward Cumberland St.",
"Turn right onto Spring St.",
"Turn left onto US-52 N/Morrison Dr.",
"..."
]
}Response (Error - 500 Internal Server Error):
"Error message describing what went wrong"Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/route/generateRoute - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "origin": "Daniel Island, SC", "destination": "James Island, SC" } - Click Send
cURL Example:
curl -X POST http://localhost:5001/route/generateRoute \
-H "Content-Type: application/json" \
-d '{
"origin": "Charleston, SC",
"destination": "Columbia, SC"
}'Requirements:
- The
GOOGLE_MAPS_API_KEYmust be set inapplication.yamlorapplication-test.yaml - Both
originanddestinationshould be valid location strings (addresses, cities, or landmarks) - The endpoint uses Google Maps Directions API for driving routes
RouteScout can generate a random destination near your location and provide driving directions to get there.
Description: Generate a random destination within a specified radius from your starting point and receive turn-by-turn directions to get there. The endpoint randomly selects from various destination types including restaurants, cafes, bakeries, amusement centers, cultural centers, movie theaters, parks, and cultural landmarks.
URL: http://localhost:5001/destination/generateDestination
Method: POST
Headers:
Content-Type:application/json
Request Body:
{
"origin": "Charleston, SC",
"radius": 5000
}Request Parameters:
origin(required): Starting location (address, city, or landmark)radius(required): Search radius in meters (0.0 to 50000.0)
Response (Success - 200 OK):
{
"destinationType": "cafe",
"routeDetails": {
"origin": "Charleston, SC",
"destination": "Kudu Coffee & Craft Beer",
"distance": "2.3 mi",
"duration": "8 mins",
"instructions": [
"Head north on Meeting St toward George St.",
"Turn left onto Spring St.",
"Turn right onto King St.",
"Destination will be on the left."
]
}
}Response (Error - 400 Bad Request):
"Invalid origin location."Response (Error - 404 Not Found):
"No destination found for type cafe within the specified radius."Response (Error - 500 Internal Server Error):
"Error message describing what went wrong"Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/destination/generateDestination - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "origin": "Harbor Walk East - College of Charleston", "radius": 10000 } - Click Send
cURL Example:
curl -X POST http://localhost:5001/destination/generateDestination \
-H "Content-Type: application/json" \
-d '{
"origin": "Charleston, SC",
"radius": 5000
}'How It Works:
- Converts your origin location to coordinates using Google Geocoding API
- Randomly selects a destination type from:
restaurant- Dining establishmentscafe- Coffee shops and cafesbakery- Bakeries and pastry shopsamusement_center- Entertainment venuescultural_center- Cultural institutionsmovie_theater- Cinema and theaterspark- Parks and outdoor spacescultural_landmark- Historical and cultural landmarks
- Searches for a place of that type within your specified radius using Google Places API
- Generates turn-by-turn driving directions from your origin to the destination
- Returns both the destination type and complete route details
Use Cases:
- Discover new places when you're feeling adventurous
- Find something to do nearby without having to decide what
- Generate spontaneous date ideas or outing destinations
- Break out of routine by visiting random local spots
Requirements:
- The
GOOGLE_MAPS_API_KEYmust be configured inapplication.yamlorapplication-test.yaml - Origin should be a valid location string that can be geocoded
- Radius must be between 0.0 and 50000.0 meters
- The endpoint uses Google Geocoding API, Google Places API (New), and Google Maps Directions API
RouteScout provides nearby places search functionality using Google's Places API (New). These endpoints allow you to find amenities like restaurants, gas stations, parks, and other points of interest near a specific location.
Description: Find amenities near a given location. Returns detailed information about places including ratings, contact information, accessibility options, and restaurant-specific details.
URL: http://localhost:5001/nearest/amenity
Method: POST
Headers:
Content-Type:application/json
Request Body:
{
"latitude": 32.7767,
"longitude": -79.9309,
"radius": 1500,
"type": "restaurant"
}Request Parameters:
latitude(required): Latitude coordinate of the search centerlongitude(required): Longitude coordinate of the search centerradius(optional): Search radius in meters (default: 1000, max: 50000)type(optional): Type of amenity to search for (e.g., "restaurant", "gas_station", "park", "cafe")
Response (Success - 200 OK):
{
"amenities": [
{
"placeId": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"name": "The Ordinary",
"vicinity": "544 King Street, Charleston, SC 29403",
"rating": 4.6,
"userRatingsTotal": 1234,
"latitude": 32.7876,
"longitude": -79.9402,
"types": ["restaurant", "seafood_restaurant", "bar"],
"website": "https://www.theordinary.com",
"phoneNumber": "(843) 414-7060",
"openNow": true,
"wheelchairAccessibleEntrance": true,
"priceLevelString": "PRICE_LEVEL_EXPENSIVE",
"hasRestroom": true,
"dineIn": true,
"takeout": false,
"delivery": false,
"servesBreakfast": false,
"servesLunch": true,
"servesDinner": true,
"vegetarianFood": true,
"reservable": true,
"music": false
}
],
"error": null
}Response (Error - 500 Internal Server Error):
{
"error": "Error fetching amenities: API request failed with response code: 403"
}Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/nearest/amenity - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "latitude": 32.7767, "longitude": -79.9309, "radius": 2000, "type": "cafe" } - Click Send
cURL Example:
curl -X POST http://localhost:5001/nearest/amenity \
-H "Content-Type: application/json" \
-d '{
"latitude": 32.7767,
"longitude": -79.9309,
"radius": 1500,
"type": "restaurant"
}'Common Place Types:
restaurant- Restaurantscafe- Coffee shops and cafesgas_station- Gas stationsparking- Parking facilitiespark- Parks and recreational areashospital- Hospitals and medical facilitiespharmacy- Pharmaciesgrocery_or_supermarket- Grocery storesatm- ATMs and bankslodging- Hotels and accommodations
For a complete list of supported types, see Google Places API Types.
Description: Search for multiple types of amenities near a location in a single request. This endpoint performs separate searches for each type and combines the results.
URL: http://localhost:5001/nearest/amenity/types
Method: POST
Headers:
Content-Type:application/json
Request Body:
{
"latitude": 32.7767,
"longitude": -79.9309,
"radius": 1500,
"types": ["restaurant", "cafe", "gas_station"]
}Request Parameters:
latitude(required): Latitude coordinate of the search centerlongitude(required): Longitude coordinate of the search centerradius(optional): Search radius in meters (default: 1000)types(required): Array of place types to search for
Response (Success - 200 OK):
{
"amenities": [
{
"placeId": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"name": "The Ordinary",
"vicinity": "544 King Street, Charleston, SC 29403",
"rating": 4.6,
"types": ["restaurant", "seafood_restaurant", "bar"],
...
},
{
"placeId": "ChIJA2B3kTeuEmsRSomeOtherId",
"name": "Kudu Coffee",
"vicinity": "4 Vanderhorst Street, Charleston, SC 29403",
"rating": 4.8,
"types": ["cafe", "coffee_shop"],
...
},
{
"placeId": "ChIJB3C4lTeuEmsRAnotherPlaceId",
"name": "Shell Gas Station",
"vicinity": "400 King Street, Charleston, SC 29403",
"rating": 3.9,
"types": ["gas_station", "convenience_store"],
...
}
],
"error": null
}Response (Error - 500 Internal Server Error):
{
"error": "Error fetching amenities by types: API request failed with response code: 400"
}Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/nearest/amenity/types - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "latitude": 32.7767, "longitude": -79.9309, "radius": 2000, "types": ["restaurant", "cafe", "park"] } - Click Send
cURL Example:
curl -X POST http://localhost:5001/nearest/amenity/types \
-H "Content-Type: application/json" \
-d '{
"latitude": 32.7767,
"longitude": -79.9309,
"radius": 1500,
"types": ["restaurant", "cafe", "gas_station"]
}'Use Cases:
- Find all essential amenities (restaurants, gas stations, ATMs) near a rest stop
- Locate dining and entertainment options in a tourist area
- Search for multiple healthcare facilities (hospitals, pharmacies, clinics)
Requirements:
- The
GOOGLE_MAPS_API_KEYmust be configured inapplication.yamlorapplication-test.yaml - Valid latitude and longitude coordinates
- The endpoint uses Google Places API (New) with the
searchNearbymethod - Maximum of 20 results per type (combined results may contain up to 20 × number of types)
Description: Find amenities near your approximate location. Returns detailed information about places including ratings, contact information, accessibility options, and restaurant-specific details.
URL: http://localhost:5001/nearest/amenity/current-geolocation
Method: POST
Headers:
Content-Type:application/jsonRequest Body:
{
"radius": 1500,
"type": "restaurant"
}Request Parameters:
radius(required): Search radius in meters (default: 1000, max: 50000)type(required): Type of amenity to search for (e.g., "restaurant", "gas_station", "park", "cafe")
Response (Success - 200 OK):
{
"amenities": [
{
"placeId": "ChIJyz5Va1SeVogR8h36vS53-Po",
"name": "Chick-fil-A",
"vicinity": "1540 E Woodlawn Rd, Charlotte, NC 28209, USA",
"rating": 4.5,
"userRatingsTotal": 1779,
"latitude": 35.171641199999996,
"longitude": -80.8498977,
"types": ["fast_food_restaurant", "breakfast_restaurant", "catering_service", "food_delivery", "restaurant", "food", "point_of_interest", "establishment"],
"website": "https://www.chick-fil-a.com/locations/nc/east-woodlawn-road?utm_source=yext&utm_medium=link",
"phoneNumber": "(704) 601-6031",
"openNow": true,
"wheelchairAccessibleEntrance": true,
"priceLevelString": "PRICE_LEVEL_INEXPENSIVE",
"hasRestroom": true,
"dineIn": false,
"takeout": true,
"delivery": true,
"servesBreakfast": true,
"servesLunch": true,
"servesDinner": true,
"vegetarianFood": false,
"music": false,
"reservable": false
}
],
"error": null
}Response (Error - 500 Internal Server Error):
{
"error": "Error fetching amenities: API request failed with response code: 400"
}Postman Setup:
- Create a new POST request
- Enter URL:
http://localhost:5001/nearest/amenity/current-geolocation - Select the Body tab
- Choose raw and select JSON from the dropdown
- Enter the JSON request body:
{ "radius": 2000, "type": "cafe" } - Click Send
cURL Example:
curl -X POST http://localhost:5001/nearest/amenity/current-geolocation \
-H "Content-Type: application/json" \
-d '{
"radius": 1500,
"type": "restaurant"
}'Common Place Types:
restaurant- Restaurantscafe- Coffee shops and cafesgas_station- Gas stationsparking- Parking facilitiespark- Parks and recreational areashospital- Hospitals and medical facilitiespharmacy- Pharmaciesgrocery_or_supermarket- Grocery storesatm- ATMs and bankslodging- Hotels and accommodations
For a complete list of supported types, see Google Places API Types.
Description: Get your approximate current location in latitude and longitude.
URL: http://localhost:5001/current/geolocation/auto
Method: GET
Response:
{
"longitude": -80.8488498,
"accessPointsUsed": [],
"latitude": 35.1811188
}Postman Setup:
- Create a new GET request
- Enter URL:
http://localhost:5001/current/geolocation/auto - Click Send
RouteScout provides multiple health check endpoints to monitor application status and performance.
Description: Enhanced health check endpoint that provides detailed application health status along with system metrics including CPU usage, memory consumption, and HTTP request statistics.
URL: http://localhost:5001/status/health
Method: GET
Response (Success - 200 OK):
{
"health": {
"status": "UP"
},
"metrics": {
"system.cpu.usage": {
"name": "system.cpu.usage",
"description": "The recent CPU usage of the system",
"baseUnit": "percent",
"measurements": [
{
"statistic": "VALUE",
"value": 0.125
}
]
},
"process.cpu.usage": {
"name": "process.cpu.usage",
"description": "The recent CPU usage of the JVM process",
"baseUnit": "percent",
"measurements": [
{
"statistic": "VALUE",
"value": 0.0523
}
]
},
"jvm.memory.used": {
"name": "jvm.memory.used",
"description": "The amount of used memory",
"baseUnit": "bytes",
"measurements": [
{
"statistic": "VALUE",
"value": 123456789
}
]
},
"http.server.requests": {
"name": "http.server.requests",
"description": "HTTP server request metrics",
"baseUnit": "seconds",
"measurements": [
{
"statistic": "COUNT",
"value": 42
},
{
"statistic": "TOTAL_TIME",
"value": 1.234
}
]
}
}
}Postman Setup:
- Create a new GET request
- Enter URL:
http://localhost:5001/status/health - Click Send
cURL Example:
curl http://localhost:5001/status/healthUse Cases:
- Monitor application health and performance in real-time
- Track CPU and memory usage for capacity planning
- Monitor HTTP request metrics for load analysis
- Integration with monitoring tools and dashboards
Description: Standard Spring Boot Actuator health check endpoint to verify the application is running.
URL: http://localhost:5001/actuator/health
Method: GET
Response (Success - 200 OK):
{
"status": "UP"
}Postman Setup:
- Create a new GET request
- Enter URL:
http://localhost:5001/actuator/health - Click Send
cURL Example:
curl http://localhost:5001/actuator/healthNote: This is the standard Spring Boot Actuator health endpoint, enabled in application.yaml under the management.endpoint.health.enabled configuration. For detailed metrics, use the /status/health endpoint instead.
To run all tests in the project:
./mvnw testNote: On Windows, replace
./mvnwwith.\mvnw
To run only the RouteScoutAgent test suite:
./mvnw test -Dtest=RouteScoutAgentTestThis will execute all unit tests for the RouteScoutAgent class, including:
- Constructor initialization tests
- Input validation tests
- Error handling tests
- Prompt format validation tests
To run a specific test method:
./mvnw test -Dtest=RouteScoutAgentTest#testGetSuggestions_WithValidMessageAfter running tests, you can view:
- Console output: Test results displayed in the terminal
- HTML Report: Generated at
target/surefire-reports/index.html - XML Reports: Available in
target/surefire-reports/directory
Setting up the datasource within IntelliJ should be straightforward with username and password. If you're using a Heroku datasource then you will need to set the following settings on the Advanced tab
Github project link: https://github.com/users/bmeudy11/projects/1 Github repository: https://github.com/bmeudy11/saasquatch.git
For further references with Spring Boot:
For further references with Maven's dependency management framework:
