# Project export: Plannr

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: UC Berkeley AI Hackathon 2025
- Tagline: Organize Entire Hackathons with Just One Click with AI Agents!
- Devpost: https://devpost.com/software/plannr-k5bpmx
- GitHub: https://github.com/subodh-thallada/ai-assist-planner
- Demo: https://ai-assist-planner.vercel.app/
- Team: 3 GitHub contributor(s) — subodh-thallada (22 commits), gpt-engineer-app[bot] (2 commits), Chelsea W. (1 commits)

## Devpost submission (written by the team)

### Inspiration

As hackathon organizers ourselves, we know firsthand how overwhelming and chaotic planning can get. Finding sponsors, booking venues, managing transportation, designing websites, ordering swag, handling outreach, and running logistics, all while keeping everything on schedule, requires hundreds of emails, calls, and spreadsheet updates. Inspired by the theme of this hackathon, we asked: Why not build an AI system that can do most of this for us? That’s how Plannr was born: an intelligent AI-powered assistant that automates the hardest parts of organizing hackathons.

### What it does

Plannr is an AI Hackathon Organizer Assistant powered by a system of specialized agents that automate and streamline every stage of hackathon planning. It helps you: Find and reach out to sponsors, write contextual emails, follow up, and log progress Search for venues, call vendors with Vapi, negotiate pricing, and track details Coordinate bussing and catering, automatically call around for quotes and log everything Generate a content calendar with posts, reels, and emails using Claude and Gemini Schedule and log Instagram posts, with AI-generated visuals Manage outreach for mentors, speakers, and communities Auto-generate websites, hackathon applications, and answer FAQs Everything is coordinated through a central spreadsheet system and connected via n8n workflows that use agents from Claude, Gemini, Fetch.ai, Unify, Orkes, Groq, Vapi, and letta.ai.

### How we built it

Claude (via Fetch.ai uAgents): Content generation, email writing, route suggestions, sponsor research Gemini: Generated visuals (posts, reels), swag design, website copy Vapi: Outbound voice calls for bus quotes, venue calls, meal vendor outreach n8n: Our orchestration layer; we built a suite of agent-based workflows across outreach, logistics, and marketing Google Sheets API: All metadata is logged to editable and synced spreadsheets Groq, Orkes: Integrated to power backend services, real-time decisioning, and scalable processing Frontend: Simple interface to add and edit hackathon metadata (in progress)

### Challenges we ran into

Workflow explosion: Managing over 10 parallel n8n workflows with asynchronous agents was messy Voice API hiccups: Setting up Vapi assistants and linking IDs dynamically in n8n required a lot of debugging LLM agent coordination: Syncing Claude with Fetch.ai agents and letting Gemini handle visual generation within time constraints Rate limits and APIs: Many services had undocumented rate limits or unstable behavior Time constraints: Trying to ship a multi-agent production system in under 24 hours with only two people.

### Accomplishments we're proud of

Built a modular, multi-agent automation system for planning events Designed workflows that can run independently or in sequence Used voice agents to actually call real vendors (bus, venue, catering) Auto-generated a full week of Instagram content (posts and reels) Created our own Claude sponsor research and outreach agent Integrated multiple AI platforms together in one cohesive system

### What we learned

How to orchestrate multi-agent workflows using n8n, Claude, and Fetch.ai How to integrate voice automation using Vapi and parse responses How to structure event metadata centrally for agents to read and write from That AI can reduce hours of planning into minutes with the right system design That even the best agents need solid UX, traceability, and logging

### What's next

Let student hackathon teams onboard and use our planner assistant One-click snack, merch, and bus ordering with pre-filled AI quotes Improve location-based planning with map integration Deploy a chat interface so users can ask for tasks like "find me 3 venues" Offer integrations with Devpost, Luma, Vercel, and Slack Create a public library of reusable AI workflows for event organizers

## README (from the GitHub repository)

# Welcome to your the project

## Project info

**URL**: https://ai-assist-planner.vercel.app/

# Inspiration
As hackathon organizers ourselves, we know firsthand how overwhelming and chaotic planning can get. Finding sponsors, booking venues, managing transportation, designing websites, ordering swag, handling outreach, and running logistics, all while keeping everything on schedule, requires hundreds of emails, calls, and spreadsheet updates. Inspired by the theme of this hackathon, we asked: Why not build an AI system that can do most of this for us? That’s how Plannr was born: an intelligent AI-powered assistant that automates the hardest parts of organizing hackathons.

# What it does
Plannr is an AI Hackathon Organizer Assistant powered by a system of specialized agents that automate and streamline every stage of hackathon planning.

# It helps you:
<img width="806" height="373" alt="image" src="https://github.com/user-attachments/assets/42de1ba9-2ada-4960-8c4c-a8d350ac4477" />
<img width="806" height="534" alt="image" src="https://github.com/user-attachments/assets/27739ce2-a37c-4fcc-ac2f-6db0d0c79242" />

- Find and reach out to sponsors, write contextual emails, follow up, and log progress
- Search for venues, call vendors with Vapi, negotiate pricing, and track details
- Coordinate bussing and catering, automatically call around for quotes and log everything
- Generate a content calendar with posts, reels, and emails using Claude and Gemini
- Schedule and log Instagram posts, with AI-generated visuals
- Manage outreach for mentors, speakers, and communities
- Auto-generate websites, hackathon applications, and answer FAQs
- Everything is coordinated through a central spreadsheet system and connected via n8n workflows that use agents from Claude, Gemini, Fetch.ai, Unify, Orkes, Groq, Vapi, and letta.ai.

# How we built it
<img width="806" height="453" alt="image" src="https://github.com/user-attachments/assets/00df6baa-4396-4986-b147-80caa6469bbc" />

- Claude (via Fetch.ai uAgents): Content generation, email writing, route suggestions, sponsor research
- Gemini: Generated visuals (posts, reels), swag design, website copy
- Vapi: Outbound voice calls for bus quotes, venue calls, meal vendor outreach
- n8n: Our orchestration layer; we built a suite of agent-based workflows across outreach, logistics, and marketing
- Google Sheets API: All metadata is logged to editable and synced spreadsheets
- Groq, Orkes: Integrated to power backend services, real-time decisioning, and scalable processing
- Frontend: Simple interface to add and edit hackathon metadata (in progress)

<img width="806" height="256" alt="image" src="https://github.com/user-attachments/assets/00a802b0-6655-467e-8b2d-b0575208e7d1" />


## Detected evidence (automated analysis)

Indexed codebase: 71 recognized source files, 304 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- Supabase (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (79 of 79)

```
.gitignore
bun.lockb
components.json
eslint.config.js
index.html
package.json
postcss.config.js
public/robots.txt
README.md
src/App.css
src/App.tsx
src/components/ChatPanel.tsx
src/components/ProjectPanel.tsx
src/components/ui/accordion.tsx
src/components/ui/alert-dialog.tsx
src/components/ui/alert.tsx
src/components/ui/aspect-ratio.tsx
src/components/ui/avatar.tsx
src/components/ui/badge.tsx
src/components/ui/breadcrumb.tsx
src/components/ui/button.tsx
src/components/ui/calendar.tsx
src/components/ui/card.tsx
src/components/ui/carousel.tsx
src/components/ui/chart.tsx
src/components/ui/checkbox.tsx
src/components/ui/collapsible.tsx
src/components/ui/command.tsx
src/components/ui/context-menu.tsx
src/components/ui/dialog.tsx
src/components/ui/drawer.tsx
src/components/ui/dropdown-menu.tsx
src/components/ui/form.tsx
src/components/ui/hover-card.tsx
src/components/ui/input-otp.tsx
src/components/ui/input.tsx
src/components/ui/label.tsx
src/components/ui/menubar.tsx
src/components/ui/navigation-menu.tsx
src/components/ui/pagination.tsx
src/components/ui/popover.tsx
src/components/ui/progress.tsx
src/components/ui/radio-group.tsx
src/components/ui/resizable.tsx
src/components/ui/scroll-area.tsx
src/components/ui/select.tsx
src/components/ui/separator.tsx
src/components/ui/sheet.tsx
src/components/ui/sidebar.tsx
src/components/ui/skeleton.tsx
src/components/ui/slider.tsx
src/components/ui/sonner.tsx
src/components/ui/switch.tsx
src/components/ui/table.tsx
src/components/ui/tabs.tsx
src/components/ui/textarea.tsx
src/components/ui/toast.tsx
src/components/ui/toaster.tsx
src/components/ui/toggle-group.tsx
src/components/ui/toggle.tsx
src/components/ui/tooltip.tsx
src/components/ui/use-toast.ts
src/hooks/use-mobile.tsx
src/hooks/use-toast.ts
src/index.css
src/lib/gemini.ts
src/lib/project-context.tsx
src/lib/supabase.ts
src/lib/utils.ts
src/lib/vapi-service.ts
src/main.tsx
src/pages/Index.tsx
src/pages/NotFound.tsx
src/vite-env.d.ts
tailwind.config.ts
tsconfig.app.json
tsconfig.json
tsconfig.node.json
vite.config.ts
```

### Dependencies

- package.json: @eslint/js@^9.9.0, @google/genai@^1.6.0, @hookform/resolvers@^3.9.0, @letta-ai/letta-client@^0.1.132, @radix-ui/react-accordion@^1.2.0, @radix-ui/react-alert-dialog@^1.1.1, @radix-ui/react-aspect-ratio@^1.1.0, @radix-ui/react-avatar@^1.1.0, @radix-ui/react-checkbox@^1.1.1, @radix-ui/react-collapsible@^1.1.0, @radix-ui/react-context-menu@^2.2.1, @radix-ui/react-dialog@^1.1.2, @radix-ui/react-dropdown-menu@^2.1.1, @radix-ui/react-hover-card@^1.1.1, @radix-ui/react-label@^2.1.0, @radix-ui/react-menubar@^1.1.1, @radix-ui/react-navigation-menu@^1.2.0, @radix-ui/react-popover@^1.1.1, @radix-ui/react-progress@^1.1.0, @radix-ui/react-radio-group@^1.2.0, @radix-ui/react-scroll-area@^1.1.0, @radix-ui/react-select@^2.1.1, @radix-ui/react-separator@^1.1.0, @radix-ui/react-slider@^1.2.0, @radix-ui/react-slot@^1.1.0, @radix-ui/react-switch@^1.1.0, @radix-ui/react-tabs@^1.1.0, @radix-ui/react-toast@^1.2.1, @radix-ui/react-toggle@^1.1.0, @radix-ui/react-toggle-group@^1.1.0, @radix-ui/react-tooltip@^1.1.4, @supabase/supabase-js@^2.50.0, @tailwindcss/typography@^0.5.15, @tanstack/react-query@^5.56.2, @types/node@^22.5.5, @types/react@^18.3.3, @types/react-dom@^18.3.0, @vapi-ai/web@^2.3.6, @vitejs/plugin-react-swc@^3.5.0, autoprefixer@^10.4.20, class-variance-authority@^0.7.1, clsx@^2.1.1, cmdk@^1.0.0, date-fns@^3.6.0, docx@^9.5.1, embla-carousel-react@^8.3.0, eslint@^9.9.0, eslint-plugin-react-hooks@^5.1.0-rc.0, eslint-plugin-react-refresh@^0.4.9, file-saver@^2.0.5, globals@^15.9.0, input-otp@^1.2.4, lovable-tagger@^1.1.7, lucide-react@^0.462.0, next-themes@^0.3.0, postcss@^8.4.47, react@^18.3.1, react-day-picker@^8.10.1, react-dom@^18.3.1, react-hook-form@^7.53.0, react-resizable-panels@^2.1.3, react-router-dom@^6.26.2, recharts@^2.12.7, sonner@^1.5.0, tailwind-merge@^2.5.2, tailwindcss@^3.4.11, tailwindcss-animate@^1.0.7, typescript@^5.5.3, typescript-eslint@^8.0.1, vaul@^0.9.3, vite@^5.4.1, zod@^3.23.8

### Recent commits (newest first)

- Update README.md
- Update README.md
- letta shit
- letta shit
- ui changes
- changes
- changes idk
- Update README.md
- sponsorhip stuff done
- database integration with supabase
- UI changes done
- added different views to view tasks
- better UI
- file adding changes
- file adding works
- Delete .env
- Update .env
- vapi calling works. big Ws
- branding added (colours lmfao)
- editable data

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

### package.json

```
{
  "name": "vite_react_shadcn_ts",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:dev": "vite build --mode development",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@google/genai": "^1.6.0",
    "@hookform/resolvers": "^3.9.0",
    "@letta-ai/letta-client": "^0.1.132",
    "@radix-ui/react-accordion": "^1.2.0",
    "@radix-ui/react-alert-dialog": "^1.1.1",
    "@radix-ui/react-aspect-ratio": "^1.1.0",
    "@radix-ui/react-avatar": "^1.1.0",
    "@radix-ui/react-checkbox": "^1.1.1",
    "@radix-ui/react-collapsible": "^1.1.0",
    "@radix-ui/react-context-menu": "^2.2.1",
    "@radix-ui/react-dialog": "^1.1.2",
    "@radix-ui/react-dropdown-menu": "^2.1.1",
    "@radix-ui/react-hover-card": "^1.1.1",
    "@radix-ui/react-label": "^2.1.0",
    "@radix-ui/react-menubar": "^1.1.1",
    "@radix-ui/react-navigation-menu": "^1.2.0",
    "@radix-ui/react-popover": "^1.1.1",
    "@radix-ui/react-progress": "^1.1.0",
    "@radix-ui/react-radio-group": "^1.2.0",
    "@radix-ui/react-scroll-area": "^1.1.0",
    "@radix-ui/react-select": "^2.1.1",
    "@radix-ui/react-separator": "^1.1.0",
    "@radix-ui/react-slider": "^1.2.0",
    "@radix-ui/react-slot": "^1.1.0",
    "@radix-ui/react-switch": "^1.1.0",
    "@radix-ui/react-tabs": "^1.1.0",
    "@radix-ui/react-toast": "^1.2.1",
    "@radix-ui/react-toggle": "^1.1.0",
    "@radix-ui/react-toggle-group": "^1.1.0",
    "@radix-ui/react-tooltip": "^1.1.4",
    "@supabase/supabase-js": "^2.50.0",
    "@tanstack/react-query": "^5.56.2",
    "@vapi-ai/web": "^2.3.6",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "^1.0.0",
    "date-fns": "^3.6.0",
    "docx": "^9.5.1",
    "embla-carousel-react": "^8.3.0",
    "file-saver": "^2.0.5",
    "input-otp": "^1.2.4",
    "lucide-react": "^0.462.0",
    "next-themes": "^0.3.0",
    "react": "^18.3.1",
    "react-day-picker": "^8.10.1",
    "react-dom": "^18.3.1",
    "react-hook-form": "^7.53.0",
    "react-resizable-panels": "^2.1.3",
    "react-router-dom": "^6.26.2",
    "recharts": "^2.12.7",
    "sonner": "^1.5.0",
    "tailwind-merge": "^2.5.2",
    "tailwindcss-animate": "^1.0.7",
    "vaul": "^0.9.3",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@eslint/js": "^9.9.0",
    "@tailwindcss/typography": "^0.5.15",
    "@types/node": "^22.5.5",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react-swc": "^3.5.0",
    "autoprefixer": "^10.4.20",
    "eslint": "^9.9.0",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.9",
    "globals": "^15.9.0",
    "lovable-tagger": "^1.1.7",
    "postcss": "^8.4.47",
    "tailwindcss": "^3.4.11",
    "typescript": "^5.5.3",
    "typescript-eslint": "^8.0.1",
    "vite": "^5.4.1"
  }
}

```

### src/App.tsx

```typescript
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Index from "./pages/Index";
import NotFound from "./pages/NotFound";

const queryClient = new QueryClient();

const App = () => (
  <QueryClientProvider client={queryClient}>
    <TooltipProvider>
      <Toaster />
      <Sonner />
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Index />} />
          {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
          <Route path="*" element={<NotFound />} />
        </Routes>
      </BrowserRouter>
    </TooltipProvider>
  </QueryClientProvider>
);

export default App;

```

### src/main.tsx

```typescript
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import './index.css';
import HackathonWebsite from './pages/Index';
import { ProjectProvider } from './lib/project-context';
import { ChatPanel } from './components/ChatPanel';
import { ProjectPanel } from './components/ProjectPanel';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from './components/ui/resizable';

function HomePage() {
  const [isChatOpen, setIsChatOpen] = React.useState(false);
  return (
    <ProjectProvider>
      <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-white">
        {/* Mobile Chat Toggle */}
        <div className="lg:hidden fixed top-4 left-4 z-50">
          <button
            onClick={() => setIsChatOpen(!isChatOpen)}
            className="bg-blue-600 text-white p-3 rounded-full shadow-lg hover:bg-blue-700 transition-colors"
          >
            <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
            </svg>
          </button>
        </div>
        <div className="flex min-h-screen">
          {/* Desktop: Resizable Panels */}
          <div className="hidden lg:flex w-full">
            <ResizablePanelGroup direction="horizontal" className="w-full h-screen">
              <ResizablePanel defaultSize={30} minSize={20} maxSize={50} className="h-full">
                <ChatPanel />
              </ResizablePanel>
              <ResizableHandle withHandle />
              <ResizablePanel defaultSize={70} minSize={50} className="h-full">
                <ProjectPanel />
              </ResizablePanel>
            </ResizablePanelGroup>
          </div>
          {/* Mobile: Modal ChatPanel */}
          <div className={`${isChatOpen ? 'fixed inset-0 z-40' : 'hidden'} lg:hidden`}>
            <ChatPanel onClose={() => setIsChatOpen(false)} />
          </div>
          {/* Overlay for mobile */}
          {isChatOpen && (
            <div 
              className="fixed inset-0 bg-black bg-opacity-50 z-30 lg:hidden"
              onClick={() => setIsChatOpen(false)}
            />
          )}
          {/* Mobile: ProjectPanel always visible */}
          <div className="flex-1 lg:hidden">
            <ProjectPanel />
          </div>
        </div>
      </div>
    </ProjectProvider>
  );
}

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/hackathon" element={<HackathonWebsite />} />
      </Routes>
    </BrowserRouter>
  </React.StrictMode>
);

```

### src/pages/Index.tsx

```typescript
import React from "react";

export default function HackathonWebsite() {
  return (
    <div style={{ minHeight: "100vh", background: "linear-gradient(135deg, #0f2027 0%, #2c5364 100%)", color: "#fff", fontFamily: "'Inter', sans-serif" }}>
      <header style={{ padding: "2rem 0", textAlign: "center", borderBottom: "1px solid #1a2636", background: "rgba(0,0,0,0.7)" }}>
        <h1 style={{ fontSize: "3rem", fontWeight: 900, letterSpacing: "-2px", color: "#4fc3f7", textShadow: "0 2px 16px #0ff" }}>
          Gen AI Hackathon 2024
        </h1>
        <p style={{ fontSize: "1.5rem", color: "#b3e5fc", marginTop: "1rem" }}>
          October 17-18, Madison Square Garden, NYC
        </p>
        <p style={{ fontSize: "1.1rem", color: "#90caf9", marginTop: "0.5rem" }}>
          ~400 participants | Theme: <span style={{ color: "#fff" }}>Generative AI</span>
        </p>
      </header>
      <main style={{ maxWidth: 700, margin: "3rem auto", background: "rgba(20,30,50,0.85)", borderRadius: 24, boxShadow: "0 8px 32px #000a", padding: "2.5rem 2rem" }}>
        <section style={{ marginBottom: "2.5rem" }}>
          <h2 style={{ fontSize: "2rem", fontWeight: 700, color: "#4fc3f7", marginBottom: 12 }}>About the Hackathon</h2>
          <p style={{ fontSize: "1.15rem", color: "#e3f2fd" }}>
            Join us for an electrifying 36-hour hackathon at the iconic Madison Square Garden! Dive into the world of Generative AI, collaborate with top talent, and build the next wave of AI-powered applications. Whether you're a coder, designer, or AI enthusiast, this is your chance to innovate, learn, and connect.
          </p>
        </section>
        <section style={{ marginBottom: "2.5rem" }}>
          <h2 style={{ fontSize: "2rem", fontWeight: 700, color: "#4fc3f7", marginBottom: 12 }}>Event Details</h2>
          <ul style={{ fontSize: "1.1rem", color: "#b3e5fc", lineHeight: 2, listStyle: "none", padding: 0 }}>
            <li><strong>Date:</strong> October 17-18, 2024</li>
            <li><strong>Location:</strong> Madison Square Garden, New York City</li>
            <li><strong>Participants:</strong> ~400</li>
            <li><strong>Theme:</strong> Generative AI</li>
            <li><strong>Prizes:</strong> $20,000+ in cash & swag</li>
            <li><strong>Workshops:</strong> AI, ML, and more</li>
            <li><strong>Free food, swag, and 24/7 venue access</strong></li>
          </ul>
        </section>
        <section>
          <h2 style={{ fontSize: "2rem", fontWeight: 700, color: "#4fc3f7", marginBottom: 12 }}>Register Now</h2>
          <a href="#" style={{ display: "inline-block", background: "linear-gradient(90deg, #1565c0, #00bcd4)", color: "#fff", fontWeight: 700, fontSize: "1.2rem", padding: "0.9rem 2.5rem", borderRadius: 999, boxShadow: "0 2px 16px #00bcd4aa", textDecoration: "none", marginTop: 8, letterSpacing: 1 }}>
            Registration Coming Soon
          </a>
        </section>
      </main>
      <footer style={{ textAlign: "center", color: "#b3e5fc", padding: "2rem 0 1rem 0", fontSize: "1rem" }}>
        &copy; 2024 Gen AI Hackathon. All rights reserved.
      </footer>
    </div>
  );
}

```

### postcss.config.js

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

```

### vite.config.ts

```typescript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import path from "path";
import { componentTagger } from "lovable-tagger";

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
  server: {
    host: "::",
    port: 8080,
  },
  plugins: [
    react(),
    mode === 'development' &&
    componentTagger(),
  ].filter(Boolean),
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
}));

```

### eslint.config.js

```javascript
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
  { ignores: ["dist"] },
  {
    extends: [js.configs.recommended, ...tseslint.configs.recommended],
    files: ["**/*.{ts,tsx}"],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
    plugins: {
      "react-hooks": reactHooks,
      "react-refresh": reactRefresh,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      "react-refresh/only-export-components": [
        "warn",
        { allowConstantExport: true },
      ],
      "@typescript-eslint/no-unused-vars": "off",
    },
  }
);

```

### index.html

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>AI Project Manager</title>
    <meta name="description" content="AI-powered project management with natural language commands" />
    <meta name="author" content="Lovable" />

    <meta property="og:title" content="AI Project Manager" />
    <meta property="og:description" content="AI-powered project management with natural language commands" />
    <meta property="og:type" content="website" />
    <meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />

    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:site" content="@lovable_dev" />
    <meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />

    <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap" rel="stylesheet" />
  </head>

  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

```

### tailwind.config.ts

```typescript
import type { Config } from "tailwindcss";

export default {
	darkMode: ["class"],
	content: [
		"./pages/**/*.{ts,tsx}",
		"./components/**/*.{ts,tsx}",
		"./app/**/*.{ts,tsx}",
		"./src/**/*.{ts,tsx}",
	],
	prefix: "",
	theme: {
		container: {
			center: true,
			padding: '2rem',
			screens: {
				'2xl': '1400px'
			}
		},
		extend: {
			colors: {
				border: 'hsl(var(--border))',
				input: 'hsl(var(--input))',
				ring: 'hsl(var(--ring))',
				background: 'hsl(var(--background))',
				foreground: 'hsl(var(--foreground))',
				primary: {
					DEFAULT: 'hsl(var(--primary))',
					foreground: 'hsl(var(--primary-foreground))'
				},
				secondary: {
					DEFAULT: 'hsl(var(--secondary))',
					foreground: 'hsl(var(--secondary-foreground))'
				},
				destructive: {
					DEFAULT: 'hsl(var(--destructive))',
					foreground: 'hsl(var(--destructive-foreground))'
				},
				muted: {
					DEFAULT: 'hsl(var(--muted))',
					foreground: 'hsl(var(--muted-foreground))'
				},
				accent: {
					DEFAULT: 'hsl(var(--accent))',
					foreground: 'hsl(var(--accent-foreground))'
				},
				popover: {
					DEFAULT: 'hsl(var(--popover))',
					foreground: 'hsl(var(--popover-foreground))'
				},
				card: {
					DEFAULT: 'hsl(var(--card))',
					foreground: 'hsl(var(--card-foreground))'
				},
				sidebar: {
					DEFAULT: 'hsl(var(--sidebar-background))',
					foreground: 'hsl(var(--sidebar-foreground))',
					primary: 'hsl(var(--sidebar-primary))',
					'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
					accent: 'hsl(var(--sidebar-accent))',
					'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
					border: 'hsl(var(--sidebar-border))',
					ring: 'hsl(var(--sidebar-ring))'
				}
			},
			borderRadius: {
				lg: 'var(--radius)',
				md: 'calc(var(--radius) - 2px)',
				sm: 'calc(var(--radius) - 4px)'
			},
			keyframes: {
				'accordion-down': {
					from: {
						height: '0'
					},
					to: {
						height: 'var(--radix-accordion-content-height)'
					}
				},
				'accordion-up': {
					from: {
						height: 'var(--radix-accordion-content-height)'
					},
					to: {
						height: '0'
					}
				}
			},
			animation: {
				'accordion-down': 'accordion-down 0.2s ease-out',
				'accordion-up': 'accordion-up 0.2s ease-out'
			}
		}
	},
	plugins: [require("tailwindcss-animate")],
} satisfies Config;

```

### src/vite-env.d.ts

```typescript
/// <reference types="vite/client" />

```

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