Welcome to Traveler’s Tea, an intuitive and personalized travel planning web app that turns your travel dreams into detailed itineraries.
Built around user preferences, the app delivers curated plans comprising places to visit, descriptions, and more, all at your fingertips.
Alongside its planning capabilities, TravelersTea thrives on the collective wisdom of its user community, featuring plan sharing with others, and shaping a dynamic and interactive travel planning experience.
- Project Requirements
- Usage of Units
- Above and Beyond Functionality
- Descriptions of Next Steps
- Team Contributions
- Limitations
- Prototypes
- Instructions
- Users should be able to input a set of preferences (Destination, Number of Days, Budget, Places per day), to generate personalized travel plans.
- Users can see destination markers on a map.
- Users can see a description of each destination.
- Users can create, read, update, and delete plan metadata.
- Autogenerated Pin Icons
- Users can manually update an individual destination within a plan.
- Display ratings of suggested places.
- Login system.
- Colloquial Prompt
- Users' Preferences: Compact Mode, Light Mode
- Users can generate plans based on extra notes (e.g. dietary restrictions, travel preferences)
- Entire application should be mobile-friendly
- Share itinerary as a link
Unit 1: HTML CSS JS: Our frontend consists of appropriately sized components, where each one involved writing JSX using Tailwind CSS. Since these JS language extensions are based on HTML and CSS, we utilized knowledge from all three languages to build our app.
Unit 2: React and Redux: Our front end was built using React and Redux. We followed best practices by using thunks to handle asynchronous events, segregated the API calls into their own service.js files, and used state hooks to manage frontend states.
Unit 3: Node/Express: Our backend uses Node and Express. We followed design patterns such as the Model Route Controller pattern in order to separate the responsibilities of handling the business logic, route exposure, and database models. Express also allowed us to build middlewares for error handling, error logging, general logging, authentication, and IP based rate limiting.
Unit 4: MongoDB: Our data is stored in collections inside an Atlas Cluster. We followed model schema design best practices such as choosing to not go with the common embedded document pattern by considering how frequently documents may be accessed and changed.
Unit 5: GitHub Action to format the code before any pushes to main. Two-stage Docker, one to build all dependencies for the server and client, then the second to copy over only necessary built-artifacts and run the server that serves the client. Deployed using Render with docker.
- Free form trip generation. This is generally difficult to do in other applications because of the precise requirements
needed as inputs to a natural language model like ChatGPT. We solved this by having 2 separate GPT calls
- First Call: take the free form request and turn it into trip parameters
- Second Call: use those trip parameters to generate our stages (destinations)
- Averaging set of coordinates for map markers such that all are visible on zoom:
- Simple averaging would not work because it would assume Earth is flat.
- Resolved by translating to Cartesian coordinates, finding the average, then convert back.
- Implementation assumes Earth is a sphere, which is a very good assumption, but not entirely true.
- Light and Dark mode
- Preferences are initialized by fetching the user's OS's preferences, and persisted in localStorage.
- To switch the map's theme via a toggle, we tried simply plugging in a new style parameter.
- However, we got intermittent mapbox rendering issues that kept slipping through our try/catch blocks, due to mapbox's internal chain of async calls. Therefore, we crafted a more elegant solution using react hooks.
- Seamless integration of multiple API services
- Google Places API
- OpenAI API
- MapBox API
We would like to add improved budget considerations when generating trips and implement Global Share Board and Voting System between friends and families for itineraries. We would also like to improve popups for markers on the map to have more details about the place, such as opening hours and images, and retry Logic for failed stages and trips
Andy My responsibilities were mainly centered around the backend as I implemented the user system, auth middleware, error handling and logging middlewares, share itinerary backend, postman regression tests. I was also responsible for the initial implementation and investigation for mapbox-gl, which is the map in our app.
Noreen: Most of my tasks were creating UI views in the frontend (React / Redux / Tailwind CSS). To chronologically name a few large features, I created the wireframe draft of the app, the regular trip view which includes teacups and the side panel, the “see more” drawer, the day view, the compact view, and finally light mode. I also styled and placed markers on the map.
Lymeng: I set up the mono-repo structure and redux with thunks. Create frontend components such as modals, loaders, forms, etc. Engineer the connection between the client and server. Containerized using Docker to ensure the environment is the same for the mono-repo and deployed with Render.
Vaishnavi: mainly responsible for the integration of Google Places API to fetch coordinates and ratings based on the names of the places generated by OpenAI’s returned trip plan response. Helped create UI for sign in page and added routing. Helped add the spinning feature on Mapbox globe and add FE and BE logic for tea cup ratings for each place on the plan. Also improved UI for map marker popups.
Rithin: I worked on the complete end to end implementation of the edit stage feature and also worked with Andy to deliver the share itinerary feature. I was also responsible for driving team discussions and was involved in code reviews. As I had the most experience with GPT, I was also responsible for developing the interfacing logic for GPT API.
- Some locations don't necessarily have corresponding coordinates, this will cause an error
- Especially more prominent for more obscure Destinations
- Takes time for trips to generate (this should get better with time)
- Can be expensive to deploy at scale
User input
With sidebar closed
With sidebar open: Specific details about a day in the plan
This is a MERN stack project using JavaScript, with auto-linting and formatting set up using ESLint and Prettier. We use Yarn Workspaces to simplify installation and running scripts.
- Clone the repository:
git clone https://github.com/cpsc455-bugstorm/TravelersTea.git
- Install the dependencies:
yarn install
Now, you will need .env
files, one in server and one in client.
- Create a new file
.env
in theserver
folder:
touch server/.env
- Find the correct
<value>
for the following in discord's secret channel.
The content of server/.env
file should look like this (with the <value>
replaced with the correct constant) :
server/.env.example
provides a template for this file.
ENV=<value>
MONGO_USERNAME=<value>
MONGO_PASSWORD=<value>
JWT_SECRET=<value>
OPEN_AI_ORG_ID=<value>
OPEN_AI_API_KEY=<value>
GPT_MODEL=<value>
DB_USER_FLAG=<value>
GOOGLE_PLACES_API_KEY=<value>
CLIENT_URL=<value>
- Create a new file
.env
in theclient
folder:
touch client/.env
- Find the correct
<value>
for the following in discord's secret channel.
The content of client/.env
file should look like this (with the <value>
replaced with the correct constant) :
client/.env.example
provides a template for this file.
REACT_APP_MAPBOX_TOKEN=<value>
REACT_APP_API_URL=<value>
- Start both the server and client using concurrently
yarn start
Alternatively, you can start either server or client using the commands below:
# starting only server
yarn start:server
# starting only client
yarn start:client
follow the client
link here: http://localhost:3000
follow the server
link here: http://localhost:5001/api/user
# run linter
yarn lint:fix
# check for linting errors
yarn lint
# run formatter
yarn format
# check for formatting errors
yarn format:check
We use Husky to run pre-commit hooks
with lint-staged to run linters on git staged files. This ensures that our code
is formatted correctly when we commit our codes and when we open a pull-request on main
branch.
- Restart your IDE to fix tailwind autocomplete.
- Delete all node_modules and do
yarn install
in the root directory.
components
: where react elements go.common
: reusable components, such asButton
,Dropdown
,Alert
etc.
reducers
: put redux reducers here.App.js
: the top-level React app.index.css
: imports tailwind. Try not to modify this.store.js
: configures redux; link any new reducers here.
This is where assets (e.g. images) go, as well as the index.html
.
Configure tailwind and add custom tailwind keywords.
To see some particular database, whether it is the shared one, of your own, follow the steps below.
-
Log in to Mongo Atlas (press Sign In on the top right)
-
Here is our database! Our collections (think of SQL Tables), along with other helpful buttons, can be found here:
To use your own database. Navigate to config.js
in the server
folder.