# Project export: BucketList AI

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Imagine never missing out on the perfect flight for your dream trip. You can build bucketlists and receive automatic notifications about the most affordable flights to your desired destinations.
- Devpost: https://devpost.com/software/bucketlist-ai
- GitHub: https://github.com/johntrinhvu/BucketList-AI
- Team: 4 GitHub contributor(s) — johntrinhvu (32 commits), Abhay Singh (26 commits), andrewzho (24 commits), tyeon (16 commits)

## Devpost submission (written by the team)

### Inspiration

Our inspiration for this project came from OpenAI's recent release of Swarms, which introduced us to the concept of using multiple AI agents to collaboratively accomplish tasks. We wanted to explore how AI agents could be applied in a practical, user-friendly way, particularly for tasks that require coordination and planning. As college students, we often find ourselves excited about future plans, like traveling or exploring new places. However, with our busy schedules, these ideas often get pushed aside and forgotten. This is where Bucket List AI steps in. It’s designed to tackle this common problem by not only remembering the trips we want to take but actively helping us plan them. Using AI-driven recommendations and personalized itineraries, Bucket List AI simplifies the process of turning our aspirations into reality, ensuring we don't let those ideas wither away.

### What it does

Bucket List AI helps users turn their travel dreams into reality by intelligently planning trips based on their interests. First, it analyzes the items the user adds to their "bucket" list, such as destinations or activities. Then, it scans for flights from the user’s location and identifies options that are cheaper than usual. Once potential flights are found, our AI agents step in to evaluate the quality of the trip, considering factors like whether the user's bucket list items will be fulfilled. After this evaluation, the information is passed to another agent that generates a detailed itinerary, which is then sent back to the user. This seamless process ensures that users not only discover affordable travel opportunities but also receive well-planned itineraries tailored to their personal goals.

### How we built it

We built Bucket List AI using the FaRM stack, which stands for FastAPI, React, and MongoDB. Our backend was developed in Python with FastAPI, providing a fast and scalable framework for handling requests and managing user data. For data storage, we utilized MongoDB, allowing us to store and manage complex, unstructured data like bucket list items and trip plans efficiently. Our frontend was created with React for a dynamic and user-friendly interface, enabling users to easily interact with their bucket lists and receive travel recommendations. We styled the frontend using CSS to ensure a visually appealing and smooth user experience. Additionally, we integrated Fetch.ai's agents, which allowed us to harness the power of decentralized AI. These agents work collaboratively to scan for flights, evaluate trip quality, and generate personalized itineraries. By leveraging Fetch.ai’s agent framework, we enabled seamless, automated task completion, ensuring that users receive high-quality, curated trip plans.

### Challenges we ran into

One of the key challenges we faced was implementing a multi-agent system with Fetch.ai. We encountered difficulties in establishing clear communication between the agents, despite following the guidelines and studying the documentation. The process of getting the agents to effectively collaborate and share data proved to be more complex than anticipated, and we weren’t able to fully implement the agents as we originally intended.

### Accomplishments we're proud of

We’re proud of several accomplishments in building Bucket List AI. First, successfully integrating the FaRM stack—FastAPI, React, and MongoDB—allowed us to create a full-stack application that delivers a smooth user experience. Despite not being able to fully use the Agents through Fetch.ai, we learned a lot about how these agents work and how to implement them. The fact that we were able to generate trip recommendations based on user interests and flight prices is a major win as well as being able to use real time flight data to make trips.

### What we learned

Throughout the development of Bucket List AI, we gained valuable experience in working with AI agents and understanding the complexities of multi-agent systems. We deepened our knowledge of the FaRM stack, honing our skills in FastAPI, React, and MongoDB, while also improving our ability to handle database connectivity issues and optimize API performance. We learned the importance of collaborative problem-solving when overcoming technical hurdles and gained a better understanding of how AI-driven automation can enhance user experiences in real-world applications.

### What's next

Following CalHacks, our team is excited to continue collaborating and perfecting our project. We aim to address the challenges we faced with Fetch.ai, enhancing and adding to the product to make it refined, impactful, and ready for users around the world to enjoy.

## README (from the GitHub repository)

## Inspiration
Our inspiration for this project came from OpenAI's recent release of Swarms, which introduced us to the concept of using multiple AI agents to collaboratively accomplish tasks. We wanted to explore how AI agents could be applied in a practical, user-friendly way, particularly for tasks that require coordination and planning.

As college students, we often find ourselves excited about future plans, like traveling or exploring new places. However, with our busy schedules, these ideas often get pushed aside and forgotten. This is where Bucket List AI steps in. It’s designed to tackle this common problem by not only remembering the trips we want to take but actively helping us plan them. Using AI-driven recommendations and personalized itineraries, Bucket List AI simplifies the process of turning our aspirations into reality, ensuring we don't let those ideas wither away.

## What it does
Bucket List AI helps users turn their travel dreams into reality by intelligently planning trips based on their interests. First, it analyzes the items the user adds to their "bucket" list, such as destinations or activities. Then, it scans for flights from the user’s location and identifies options that are cheaper than usual.

Once potential flights are found, our AI agents step in to evaluate the quality of the trip, considering factors like whether the user's bucket list items will be fulfilled. After this evaluation, the information is passed to another agent that generates a detailed itinerary, which is then sent back to the user. This seamless process ensures that users not only discover affordable travel opportunities but also receive well-planned itineraries tailored to their personal goals.
## How we built it
We built Bucket List AI using the FaRM stack, which stands for FastAPI, React, and MongoDB. Our backend was developed in Python with FastAPI, providing a fast and scalable framework for handling requests and managing user data. For data storage, we utilized MongoDB, allowing us to store and manage complex, unstructured data like bucket list items and trip plans efficiently.

Our frontend was created with React for a dynamic and user-friendly interface, enabling users to easily interact with their bucket lists and receive travel recommendations. We styled the frontend using CSS to ensure a visually appealing and smooth user experience.

Additionally, we integrated Fetch.ai's agents, which allowed us to harness the power of decentralized AI. These agents work collaboratively to scan for flights, evaluate trip quality, and generate personalized itineraries. By leveraging Fetch.ai’s agent framework, we enabled seamless, automated task completion, ensuring that users receive high-quality, curated trip plans.

## Challenges we ran into
One of the key challenges we faced was implementing a multi-agent system with Fetch.ai. We encountered difficulties in establishing clear communication between the agents, despite following the guidelines and studying the documentation. The process of getting the agents to effectively collaborate and share data proved to be more complex than anticipated, and we weren’t able to fully implement the agents as we originally intended. We worked alongside the FetchAI software engineers but couldn't find a fix to the bug

## Accomplishments that we're proud of
We’re proud of several accomplishments in building Bucket List AI. First, successfully integrating the FaRM stack—FastAPI, React, and MongoDB—allowed us to create a full-stack application that delivers a smooth user experience. Despite not being able to fully use the Agents through Fetch.ai, we learned a lot about how these agents work and how to implement them.  The fact that we were able to generate trip recommendations based on user interests and flight prices is a major win as well as being able to use real time flight data to make trips.

## What we learned
Throughout the development of Bucket List AI, we gained valuable experience in working with AI agents and understanding the complexities of multi-agent systems. We deepened our knowledge of the FaRM stack, honing our skills in FastAPI, React, and MongoDB, while also improving our ability to handle database connectivity issues and optimize API performance. We learned the importance of collaborative problem-solving when overcoming technical hurdles and gained a better understanding of how AI-driven automation can enhance user experiences in real-world applications.

## What's next for BucketList AI
Following CalHacks, our team is excited to continue collaborating and perfecting our project. We aim to address the challenges we faced with Fetch.ai, enhancing and adding to the product to make it refined, impactful, and ready for users around the world to enjoy.

### Devpost Link ###
https://devpost.com/software/bucketlist-ai


## Detected evidence (automated analysis)

Indexed codebase: 27 recognized source files, 68 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- FastAPI (technology) — claimed on Devpost, not found in the code
- MongoDB (technology) — claimed on Devpost, not found in the code
- OpenAI (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (36 of 36)

```
.gitignore
backend/Dockerfile
backend/pyproject.toml
backend/requirements.txt
backend/src/api/amadeus.py
backend/src/api/itinerary_agent_user.py
backend/src/api/itinerary_agent.py
backend/src/api/openai_handler.py
backend/src/dal.py
backend/src/routers/agent.py
backend/src/server.py
flight-extension/background.js
flight-extension/manifest.json
flight-extension/popup.css
flight-extension/popup.html
flight-extension/popup.js
frontend/.gitignore
frontend/package.json
frontend/postcss.config.js
frontend/public/index.html
frontend/public/manifest.json
frontend/public/robots.txt
frontend/README.md
frontend/src/components/FlightCard/FlightCard.jsx
frontend/src/components/Navbar/Navbar.jsx
frontend/src/index.css
frontend/src/index.js
frontend/src/pages/About/About.css
frontend/src/pages/About/About.jsx
frontend/src/pages/App/App.jsx
frontend/src/pages/Dashboard/Dashboard.jsx
frontend/src/pages/Home/Home.jsx
frontend/src/pages/Login/Login.css
frontend/src/pages/Login/Login.jsx
frontend/tailwind.config.js
README.md
```

### Dependencies

- frontend/package.json: @fortawesome/fontawesome-svg-core@^6.6.0, @fortawesome/free-solid-svg-icons@^6.6.0, @fortawesome/react-fontawesome@^0.2.2, @testing-library/jest-dom@^5.17.0, @testing-library/react@^13.4.0, @testing-library/user-event@^13.5.0, autoprefixer@^10.4.20, axios@^1.7.7, framer-motion@^11.11.9, postcss@^8.4.47, react@^18.3.1, react-dom@^18.3.1, react-icons@^5.3.0, react-router-dom@^6.27.0, react-scripts@5.0.1, tailwindcss@^3.4.14, web-vitals@^2.1.4

### Recent commits (newest first)

- Updated README.md
- Create README.md
- push back
- added pfp and fixed description
- my about
- add pic of self
- create changes
- added About
- hardcode some data
- fix style of flights
- Merge branch 'main' of https://github.com/johntrinhvu/BucketList-AI
- working fetchai?
- getting flights
- fix
- fix the access token
- Merge branch 'main' of https://github.com/johntrinhvu/BucketList-AI
- flight data upload
- fix?
- getting flight data
- Merge branch 'main' of https://github.com/johntrinhvu/BucketList-AI

## Key source files (fetched from GitHub, selected and truncated for size)

### backend/pyproject.toml

```
[tool.pytest.ini_options]
pythonpath = "src"

```

### backend/Dockerfile

```
FROM python:3

WORKDIR /usr/src/app
COPY requirements.txt ./

RUN pip install --no-cache-dir --upgrade -r ./requirements.txt

EXPOSE 3001

CMD [ "python", "./src/server.py" ]

```

### backend/requirements.txt

```
��u a g e n t s = = 0 . 1 5 . 2  
 f a s t a p i = = 0 . 1 1 5 . 2  
 u v i c o r n = = 0 . 3 0 . 6  
 u a g e n t s - a i - e n g i n e = = 0 . 5 . 0  
 p y d a n t i c = = 2 . 8 . 2  
 h t t p x = = 0 . 2 7 . 2  
 m o t o r = = 3 . 6 . 0  
 p y m o n g o = = 4 . 9 . 2  
 p y t h o n - d o t e n v = = 1 . 0 . 1  
 p a s s l i b [ b c r y p t ] = = 1 . 7 . 4  
 o p e n a i = = 1 . 5 2 . 0  
 p y t h o n - d o t e n v = = 1 . 0 . 1 
```

### frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^6.6.0",
    "@fortawesome/free-solid-svg-icons": "^6.6.0",
    "@fortawesome/react-fontawesome": "^0.2.2",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.7.7",
    "framer-motion": "^11.11.9",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-icons": "^5.3.0",
    "react-router-dom": "^6.27.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "autoprefixer": "^10.4.20",
    "postcss": "^8.4.47",
    "tailwindcss": "^3.4.14"
  }
}

```

### frontend/src/index.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './pages/App/App';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    
    <App />
  </React.StrictMode>
);
```

### backend/src/server.py

```python
from fastapi import FastAPI, HTTPException, status, Depends, Request, Response, Query
from pydantic import BaseModel
from api.openai_handler import router as openai_router
from motor.motor_asyncio import AsyncIOMotorClient
from fastapi.middleware.cors import CORSMiddleware
from api.amadeus import get_access_token, search_cheapest_flights
from contextlib import asynccontextmanager
from datetime import datetime, timedelta
from typing import List
import os
import sys
import uvicorn
import uuid
from dotenv import load_dotenv
load_dotenv()

from dal import UserDAL, BucketList, BucketListItem

# Configuration
MONGODB_URI = os.environ["MONGODB_URI"]
DATABASE_NAME = "bucketlist_db"
USER_COLLECTION = "users"
BUCKET_COLLECTION = "buckets"
FLIGHT_COLLECTION = "flights"
SESSION_COOKIE_NAME = "session_id"
DEBUG = os.environ.get("DEBUG", "").strip().lower() in {"1", "true", "on", "yes"}

# In-memory session store
sessions = {}

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    client = AsyncIOMotorClient(MONGODB_URI)
    database = client.get_database(DATABASE_NAME)

    # Ensure the database is available
    pong = await database.command("ping")
    if int(pong["ok"]) != 1:
        raise Exception("Cluster connection is not okay!")

    user_collection = database.get_collection(USER_COLLECTION)
    bucket_collection = database.get_collection(BUCKET_COLLECTION)
    flight_collection = database.get_collection(FLIGHT_COLLECTION)
    app.user_dal = UserDAL(user_collection, bucket_collection, flight_collection)

    # Yield back to FastAPI Application
    yield

    # Shutdown
    client.close()

app = FastAPI(lifespan=lifespan)
app.include_router(openai_router, prefix="/api/openai")

# Enable CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*", "http://localhost:3000"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Pydantic Models
class UserCreate(BaseModel):
    username: str
    password: str

class UserLogin(BaseModel):
    username: str
    password: str

class NewItem(BaseModel):
    description: str

class NewItemResponse(BaseModel):
    id: str
    description: str

class ItemUpdate(BaseModel):
    completed: bool

class Price(BaseModel):
    total: float

class Links(BaseModel):
    flightDates: str
    flightOffers: str

# FlightInfo model
class FlightInfo(BaseModel):
    origin: str
    destination: str
    departureDate: str
    price: float


class FlightResponse(BaseModel):
    data: list[FlightInfo]

# Helper function to create session and set cookie
def create_session(response: Response, bucket_id: str):
    session_id = str(uuid.uuid4())  # Generate a unique session ID
    sessions[session_id] = bucket_id  # Store bucket_id in memory
    response.set_cookie(key=SESSION_COOKIE_NAME, value=session_id, httponly=True, secure=False, samesite='Lax')

# check the session
@app.get("/api/session")
async def check_session(request: Request):
    """Check if the user is authenticated"""
    try:
        bucket_id = get_current_bucket_id(request)
        return {"message": "Session is valid", "bucket_id": bucket_id}
    except HTTPException:
        raise HTTPException(status_code=401, detail="Not authenticated")

# Login and registration
@app.post("/api/register", status_code=status.HTTP_201_CREATED)
async def register_user(user: UserCreate, response: Response):
    """Register a new user and create a bucket for them"""
    existing_user = await app.user_dal.get_user_by_username(user.username)
    if existing_user:
        raise HTTPException(status_code=400, detail="Username already exists")

    new_user = await app.user_dal.create_user(user.username, user.password)
    
    # Create session and store bucket_id in session
    create_session(response, new_user.bucket_id)
    
    return {"message": "User created successfully", "bucket_id": new_user.bucket_id}

@app.post("/api/login", status_code=status.HTTP_200_OK)
async def login_user(user: UserLogin, response: Response):
    """Log in a user and create a session"""
    db_user = await app.user_dal.get_user_by_username(user.username)
    if not db_user or not await app.user_dal.verify_password(user.password, db_user.hashed_password):
        raise HTTPException(status_code=400, detail="Invalid credentials")

    # Create session and store bucket_id in session
    create_session(response, db_user.bucket_id)
    print(f"User logged in - ID: {db_user.id}, Username: {db_user.username}")

    return {"message": "Login successful", "user_id": str(db_user.id)}

# Get current bucket_id from session
def get_current_bucket_id(request: Request) -> str:
    session_id = request.cookies.get(SESSION_COOKIE_NAME)
    if not session_id or session_id not in sessions:
        raise HTTPException(status_code=401, detail="Not authenticated")
    return sessions[session_id]

# Bucket operations
@app.get("/api/bucket", response_model=BucketList)
async def get_user_bucket(request: Request):
    """Retrieve the logged-in user's bucket"""
    bucket_id = get_current_bucket_id(request)
    bucket = await app.user_dal.get_bucket(bucket_id)
    if not bucket:
        raise HTTPException(status_code=404, detail="Bucket not found")
    return bucket

@app.post("/api/bucket/items", status_code=status.HTTP_201_CREATED, response_model=NewItemResponse)
async def add_item_to_bucket(item: NewItem, request: Request):
    """Add a new item to the user's bucket"""
    bucket_id = get_current_bucket_id(request)
    print(bucket_id)
    bucket = await app.user_dal.add_item_to_bucket(bucket_id, item.description)
    if not bucket:
        raise HTTPException(status_code=404, detail="Bucket not found")
    print(bucket)
    return NewItemResponse(id=bucket.items[-1].id, description=item.description)

@app.post("/api/bucket/items/{item_id}/completed", response_model=BucketList)
async def update_item_completed(item_id: str, update: ItemUpdate, request: Request):
    """Update the completion status of a bucket list ite
[truncated — 2172 more characters]
```

### frontend/src/pages/App/App.jsx

```javascript
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Navbar from "../../components/Navbar/Navbar";
import Home from '../Home/Home';
import Login from '../Login/Login';
import Dashboard from '../Dashboard/Dashboard';
import About from '../About/About';

export default function App() {
  return (
    <Router>
      <div className="flex flex-col min-h-screen">
        <Navbar />
        <main className="flex-grow">
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/login" element={<Login />} />
            <Route path="/dashboard" element={<Dashboard />} />
            <Route path="/about" element={<About />} />
          </Routes>
        </main>
      </div>
    </Router>
  );
}

```

### frontend/postcss.config.js

```javascript
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

### frontend/tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}


```

### flight-extension/popup.css

```css
.popup-container {
    width: 300px;
    padding: 12px;
    text-align: center;
    font-family: Arial, sans-serif;
}

h1 {
    font-size: 1.5rem;
    margin-bottom: 8px;
}

h3 {
    margin-top: 30px;
}

button {
    margin-top: 12px;
    padding: 10px 20px;
    background-color: #187df1;
    color: white;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    font-size: 14px;
}

button:hover {
    background-color: #5da9ff;
    transition: ease-in;
    
}

select {
    padding: 6px;
    width: 100%;
    border-radius: 10px;
    border: 1px solid #ccc;
}

```

[19 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]