# Project export: BenefitFinder

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: CruzHacks 2025
- Tagline: Find benefits even when you think there's none to be found.
- Devpost: https://devpost.com/software/benefitfinder
- GitHub: https://github.com/ggrantrichards/cruzhackies
- Demo: https://chickenjockeys.web.app/
- Result: winner (Best Beginner Hack)
- Team: 3 GitHub contributor(s) — Glenn Grant-Richards (24 commits), KeeperOfTheFire (9 commits), Nxver-GitHub (2 commits)

## Devpost submission (written by the team)

### Overview

🎓 Introduction Once upon a time, in a bustling college town where students juggled textbooks, part-time jobs, and dreams of the future, there lived an AI agent unlike any other. Its name was BenefitFinder — a digital helper with a mission to level the playing field for students trying to get ahead. Whether it was a first-gen student navigating financial aid, or an international scholar unsure of local resources, BenefitFinder was designed to help them all. 🤖 What is BenefitFinder? BenefitFinder is a smart AI agent created to simplify and personalize the process of discovering: ✅ Government subsidies and assistance programs ✅ Scholarships and grants ✅ Student discounts and public benefits ✅ Local and national educational initiatives It asks for a bit of your background—your student status, major, residency, income level, and a few other key details—and within seconds, presents a curated list of real, applicable benefits you may qualify for. 🧩 How It Works You Start the Chat You open up the BenefitFinder app and it gently prompts: “Hi there! Want to find benefits you’re eligible for? I’ll just need a few quick details!” You Start the Chat You open up the BenefitFinder app and it gently prompts: “Hi there! Want to find benefits you’re eligible for? I’ll just need a few quick details!” You Answer a Few Questions It asks simple, privacy-respecting questions like: Are you a U.S. citizen or international student? Are you enrolled full-time or part-time? Do you or your family receive any public assistance? What’s your field of study? You Answer a Few Questions It asks simple, privacy-respecting questions like: Are you a U.S. citizen or international student? Are you enrolled full-time or part-time? Do you or your family receive any public assistance? What’s your field of study? BenefitFinder Searches Thousands of Programs Behind the scenes, it dives into: Federal and state aid databases Education department initiatives Local nonprofit offerings Campus-based opportunities BenefitFinder Searches Thousands of Programs Behind the scenes, it dives into: Federal and state aid databases Education department initiatives Local nonprofit offerings Campus-based opportunities You Get a Tailored Report BenefitFinder returns a friendly, organized list of resources—each with: A short summary The eligibility criteria (and how you meet them) Steps to apply, with links or direct forms A calendar reminder if there’s a deadline You Get a Tailored Report BenefitFinder returns a friendly, organized list of resources—each with: A short summary The eligibility criteria (and how you meet them) Steps to apply, with links or direct forms A calendar reminder if there’s a deadline ✨ A Day in the Life: Meet Aria Aria was a second-year community college student pursuing a degree in computer science. Working 20 hours a week while studying, she often skipped meals to save money. She knew there had to be help out there—but didn’t know where to start. One night, she found BenefitFinder. “Hey Aria! Based on your info, you may qualify for: • CalFresh (food assistance) • The Women in Tech Scholarship • A subsidized laptop program through your college • A transportation grant from your city’s student commuter fund.”_ Aria applied. Two weeks later, she had meal funds, a bus pass, and a brand-new laptop. That semester, she got her best grades ever. 🌐 Why BenefitFinder Matters Too many students leave resources on the table. Between confusing government sites, outdated PDF forms, and eligibility jargon, it’s easy to miss out. BenefitFinder: Removes friction Gives students agency Bridges the gap between need and access It's not just an app—it’s an equity engine for a better student experience. 🚀 The Future of BenefitFinder The team behind BenefitFinder envisions: Partnerships with colleges for embedded onboarding A multilingual chatbot interface for international students Real-time deadline alerts Integration with FAFSA and school portals 💬 Final Words If you're a student, or know someone navigating school and life on a budget, remember: “You don’t have to do it alone. BenefitFinder is here to find the help you deserve.

## README (from the GitHub repository)

# cruzhackies
# Glenn, Surya, Max

npm install
npm run dev

## Detected evidence (automated analysis)

Indexed codebase: 63 recognized source files, 151 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Firebase (technology) — detected in the code
- Google Gemini (technology) — 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
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (74 of 74)

```
.firebaserc
.github/workflows/firebase-hosting-merge.yml
.github/workflows/firebase-hosting-pull-request.yml
.gitignore
apphosting.yaml
backend/.gitignore
backend/app/__init__.py
backend/app/config.py
backend/app/database.py
backend/app/main.py
backend/app/models/__init__.py
backend/app/models/forms.py
backend/app/models/profile.py
backend/app/models/user.py
backend/app/routes/__init__.py
backend/app/routes/auth.py
backend/app/routes/benefits.py
backend/app/routes/forms.py
backend/app/routes/resouces.py
backend/app/services/__init__.py
backend/app/services/ai_intergration.py
backend/app/services/eligibility_engine.py
backend/app/services/form_filling.py
backend/app/services/scraping.py
backend/app/utils/__init__.py
backend/app/utils/pdf_utils.py
backend/app/utils/token_utils.py
backend/README.md
backend/requirements.txt
backend/tests/__init__.py
backend/tests/test_auth.py
backend/tests/test_benifits.py
backend/tests/test_eligibility.py
backend/tests/test_forms.py
firebase.json
frontend/.vite/deps_temp_60bc8463/package.json
frontend/.vite/deps_temp_a12f7fd1/package.json
frontend/eslint.config.js
frontend/index.html
frontend/package.json
frontend/postcss.config.js
frontend/src/App.tsx
frontend/src/components/AuthForm.tsx
frontend/src/components/Footer.tsx
frontend/src/components/Layout.tsx
frontend/src/components/Navbar.tsx
frontend/src/components/ui/button.tsx
frontend/src/components/ui/input.tsx
frontend/src/contexts/ThemeContext.tsx
frontend/src/index.css
frontend/src/lib/firebase.ts
frontend/src/lib/gemini.ts
frontend/src/lib/profileUtils.ts
frontend/src/lib/types.ts
frontend/src/lib/utils.ts
frontend/src/main.tsx
frontend/src/pages/AuthPage.tsx
frontend/src/pages/Benefits.tsx
frontend/src/pages/Home.tsx
frontend/src/pages/LandingPage.tsx
frontend/src/pages/QuestionnairePage.tsx
frontend/src/pages/Settings.tsx
frontend/src/pages/SignInPage.tsx
frontend/src/pages/SignUpPage.tsx
frontend/src/vite-env.d.ts
frontend/tailwind.config.js
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
Home.tsx
public/404.html
public/index.html
README.md
```

### Dependencies

- backend/requirements.txt: annotated-types@==0.7.0, anyio@==4.9.0, CacheControl@==0.14.2, cachetools@==5.5.2, certifi@==2025.1.31, cffi@==1.17.1, charset-normalizer@==3.4.1, click@==8.1.8, cryptography@==44.0.2, fastapi@==0.115.12, firebase-admin@==6.7.0, google-api-core@==2.24.2, google-api-python-client@==2.166.0, google-auth@==2.38.0, google-auth-httplib2@==0.2.0, google-cloud-core@==2.4.3, google-cloud-firestore@==2.20.1, google-cloud-storage@==3.1.0, google-crc32c@==1.7.1, google-resumable-media@==2.7.2, googleapis-common-protos@==1.69.2, grpcio@==1.72.0rc1, grpcio-status@==1.71.0, h11@==0.14.0, httplib2@==0.22.0, idna@==3.10, msgpack@==1.1.0, proto-plus@==1.26.1, protobuf@==5.29.4, pyasn1@==0.6.1, pyasn1_modules@==0.4.2, pycparser@==2.22, pydantic@==2.11.3, pydantic_core@==2.33.1, PyJWT@==2.10.1, pyparsing@==3.2.3, python-dotenv@==1.1.0, requests@==2.32.3, rsa@==4.9, sniffio@==1.3.1, starlette@==0.46.1, typing_extensions@==4.13.2, typing-inspection@==0.4.0, uritemplate@==4.1.1, urllib3@==2.4.0, uvicorn@==0.34.0
- frontend/package.json: @eslint/js@^9.9.1, @google/generative-ai@^0.2.1, @headlessui/react@^1.7.18, @radix-ui/react-alert-dialog@^1.1.7, @radix-ui/react-slot@^1.2.0, @types/file-saver@^2.0.7, @types/react@^18.3.5, @types/react-dom@^18.3.0, @vitejs/plugin-react@^4.3.1, autoprefixer@^10.4.18, class-variance-authority@^0.7.1, clsx@^2.1.1, eslint@^9.9.1, eslint-plugin-react-hooks@^5.1.0-rc.0, eslint-plugin-react-refresh@^0.4.11, file-saver@^2.0.5, firebase@^10.8.0, framer-motion@^11.0.8, globals@^15.9.0, lucide-react@^0.344.0, pdf-lib@^1.17.1, postcss@^8.4.35, react@^18.3.1, react-dom@^18.3.1, react-router-dom@^6.22.2, styled-jsx@^5.1.6, tailwind-merge@^3.2.0, tailwindcss@^3.4.1, typescript@^5.5.3, typescript-eslint@^8.3.0, vite@^5.4.2

### Recent commits (newest first)

- Merge branch 'main' of github.com:ggrantrichards/cruzhackies
- Fixed firebase
- Merge pull request #1 from ggrantrichards/Surya
- Firebase hosting
- Adding skips
- Added skip button
- Fixed Gemini prompt issues
- Fixed pdf styling
- better PDF
- Can create PDF
- Solid UI
- fixed UI bugs
- Different coloring
- Building UI
- Ask more relevant questions
- May have accidentally submitted cal grant lol
- Uses info fetched about user for responses
- Fixed text dissapearing issue
- Better UI and questionnaire
- Testing commit

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

### backend/requirements.txt

```
annotated-types==0.7.0
anyio==4.9.0
CacheControl==0.14.2
cachetools==5.5.2
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
cryptography==44.0.2
fastapi==0.115.12
firebase-admin==6.7.0
google-api-core==2.24.2
google-api-python-client==2.166.0
google-auth==2.38.0
google-auth-httplib2==0.2.0
google-cloud-core==2.4.3
google-cloud-firestore==2.20.1
google-cloud-storage==3.1.0
google-crc32c==1.7.1
google-resumable-media==2.7.2
googleapis-common-protos==1.69.2
grpcio==1.72.0rc1
grpcio-status==1.71.0
h11==0.14.0
httplib2==0.22.0
idna==3.10
msgpack==1.1.0
proto-plus==1.26.1
protobuf==5.29.4
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.22
pydantic==2.11.3
pydantic_core==2.33.1
PyJWT==2.10.1
pyparsing==3.2.3
python-dotenv==1.1.0
requests==2.32.3
rsa==4.9
sniffio==1.3.1
starlette==0.46.1
typing-inspection==0.4.0
typing_extensions==4.13.2
uritemplate==4.1.1
urllib3==2.4.0
uvicorn==0.34.0

```

### frontend/package.json

```
{
  "name": "vite-react-typescript-starter",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@google/generative-ai": "^0.2.1",
    "@headlessui/react": "^1.7.18",
    "@radix-ui/react-alert-dialog": "^1.1.7",
    "@radix-ui/react-slot": "^1.2.0",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "file-saver": "^2.0.5",
    "firebase": "^10.8.0",
    "framer-motion": "^11.0.8",
    "lucide-react": "^0.344.0",
    "pdf-lib": "^1.17.1",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.22.2",
    "styled-jsx": "^5.1.6",
    "tailwind-merge": "^3.2.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.9.1",
    "@types/file-saver": "^2.0.7",
    "@types/react": "^18.3.5",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.1",
    "autoprefixer": "^10.4.18",
    "eslint": "^9.9.1",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.11",
    "globals": "^15.9.0",
    "postcss": "^8.4.35",
    "tailwindcss": "^3.4.1",
    "typescript": "^5.5.3",
    "typescript-eslint": "^8.3.0",
    "vite": "^5.4.2"
  }
}

```

### frontend/.vite/deps_temp_60bc8463/package.json

```
{
  "type": "module"
}

```

### frontend/.vite/deps_temp_a12f7fd1/package.json

```
{
  "type": "module"
}

```

### frontend/src/main.tsx

```typescript
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import './index.css';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>
);

```

### backend/app/main.py

```python
from fastapi import FastAPI
from app.routes import auth
# from app import config

# Create a FastAPI app instance
app = FastAPI(
    title="BenefitFinder API",
    description="Backend for BenefitFinder to determine eligible benefits and assist users",
    version="0.1.0",
)

app.include_router(auth.router, prefix="/auth", tags=["Authentication"])


# Root endpoint to verify service status
@app.get("/")
def read_root():
    return {"message": "Welcome to BenefitFinder API"}

```

### frontend/src/App.tsx

```typescript
import React from "react";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { ThemeProvider } from "./contexts/ThemeContext";
import { Layout } from "./components/Layout";
import LandingPage from "./pages/LandingPage";
import SignUpPage from "./pages/SignUpPage";
import SignInPage from "./pages/SignInPage";
import { Home } from "./pages/Home";
import { Benefits } from "./pages/Benefits";
import { Settings } from "./pages/Settings";

function App() {
  return (
    <BrowserRouter>
      <ThemeProvider>
        <Routes>
          <Route path="/" element={<LandingPage />} />
          <Route path="/signin" element={<SignInPage />} />
          <Route path="/signup" element={<SignUpPage />} />
          <Route path="/home" element={<Layout><Home /></Layout>} />
          <Route path="/benefits" element={<Layout><Benefits /></Layout>} />
          <Route path="/settings" element={<Layout><Settings /></Layout>} />
          <Route path="*" element={<Navigate to="/" replace />} />
        </Routes>
      </ThemeProvider>
    </BrowserRouter>
  );
}

export default App;

```

### apphosting.yaml

```yaml
# Settings for Backend (on Cloud Run).
# See https://firebase.google.com/docs/app-hosting/configure#cloud-run
runConfig:
  minInstances: 0
  # maxInstances: 100
  # concurrency: 80
  # cpu: 1
  # memoryMiB: 512

# Environment variables and secrets.
# env:
  # Configure environment variables.
  # See https://firebase.google.com/docs/app-hosting/configure#user-defined-environment
  # - variable: MESSAGE
  #   value: Hello world!
  #   availability:
  #     - BUILD
  #     - RUNTIME

  # Grant access to secrets in Cloud Secret Manager.
  # See https://firebase.google.com/docs/app-hosting/configure#secret-parameters
  # - variable: MY_SECRET
  #   secret: mySecretRef

```

### Home.tsx

```typescript
import React, { useState, useEffect } from "react";
import { motion } from "framer-motion";
import { useNavigate } from "react-router-dom";
import { doc, getDoc } from "firebase/firestore";
import { auth, db } from "@/lib/firebase"
import { School, Briefcase, Home as HomeIcon, Heart } from "lucide-react";

const categories = [
  {
    id: 'education',
    title: 'Education Support',
    icon: School,
    description: 'Find student loans, grants, and scholarship opportunities',
    gradient: 'from-blue-500 to-indigo-500',
  },
  {
    id: 'employment',
    title: 'Employment Benefits',
    icon: Briefcase,
    description: 'Discover unemployment benefits and job training programs',
    gradient: 'from-green-500 to-emerald-500',
  },
  {
    id: 'housing',
    title: 'Housing Assistance',
    icon: HomeIcon,
    description: 'Learn about housing vouchers and rental assistance',
    gradient: 'from-orange-500 to-red-500',
  },
  {
    id: 'healthcare',
    title: 'Healthcare Programs',
    icon: Heart,
    description: 'Explore Medicaid, Medicare, and other health benefits',
    gradient: 'from-purple-500 to-pink-500',
  },
];

const container = {
  hidden: { opacity: 0 },
  show: { opacity: 1, transition: { staggerChildren: 0.1 } },
};

const item = {
  hidden: { opacity: 0, y: 20 },
  show: { opacity: 1, y: 0 },
};

export function Home() {
  const navigate = useNavigate();
  const [incomplete, setIncomplete] = useState(false);

  useEffect(() => {
    const fetchProfile = async () => {
      if (auth.currentUser) {
        const userDoc = await getDoc(doc(db, "users", auth.currentUser.uid));
        if (userDoc.exists()) {
          const data = userDoc.data();
          if (!data.isStudent || !data.hasJob || !data.hasDependents) {
            setIncomplete(true);
          }
        }
      }
    };
    fetchProfile();
  }, []);

  return (
    <div className="space-y-12">
      {incomplete && (
        <div className="bg-yellow-300 p-4 text-black text-center">
          Please{" "}
          <button
            className="underline"
            onClick={() => navigate("/settings")}
          >
            fill in your info
          </button>{" "}
          to receive personalized recommendations.
        </div>
      )}

      <motion.div
        initial={{ opacity: 0, y: -20 }}
        animate={{ opacity: 1, y: 0 }}
        className="text-center"
      >
        <h1 className="text-5xl font-bold text-gray-900 dark:text-white mb-6 bg-clip-text text-transparent bg-gradient-to-r from-blue-500 to-purple-500">
          How can we help you today?
        </h1>
        <p className="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
          Select a category to explore available benefits and support programs tailored to your needs.
        </p>
      </motion.div>
      
      <motion.div
        variants={container}
        initial="hidden"
        animate="show"
        className="grid grid-cols-1 md:grid-cols-2 gap-8"
      >
        {categories.map((category) => (
          <motion.div
            key={category.id}
            variants={item}
            whileHover={{ scale: 1.02 }}
            whileTap={{ scale: 0.98 }}
            className="group cursor-pointer"
            onClick={() => navigate("/benefits", { state: { category: category.id } })}
          >
            <div className="h-full p-8 rounded-2xl bg-white dark:bg-gray-800 shadow-lg hover:shadow-xl transition-all duration-300 relative overflow-hidden">
              <div className="absolute inset-0 bg-gradient-to-r opacity-0 group-hover:opacity-5 transition-opacity duration-300 dark:group-hover:opacity-10" />
              <div className="flex items-start gap-6 relative z-10">
                <div className={`p-4 rounded-xl bg-gradient-to-br ${category.gradient} text-white`}>
                  <category.icon size={28} />
                </div>
                <div>
                <h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-3 bg-clip-text bg-gradient-to-r transition-all duration-300">
                  {category.title}
                </h3>
                  <p className="text-gray-600 dark:text-gray-400 text-lg">
                    {category.description}
                  </p>
                </div>
              </div>
            </div>
          </motion.div>
        ))}
      </motion.div>
    </div>
  );
}

```

### frontend/postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

```

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