Your AI event planner that never forgets. From idea to check-in in minutes.
Com-Plan-ion is a full-stack, production-quality AI event planning platform built for IndyHack 2026. It demonstrates best use of Gemini, MongoDB, Solana, and ElevenLabs through one coherent, end-to-end product — not a collection of demos duct-taped together.
An organizer speaks: "I want a rustic outdoor networking event for 200 people in September, budget $8k, vegetarian-friendly." The app generates a structured plan, finds vendors via semantic search, detects timeline conflicts, mints an NFT ticket, publishes a guest microsite, and lets every attendee talk to a live AI voice concierge. All in one flow.
Project Overview Prerequisites Setup & Installation Connecting Real APIs
- Gemini
- MongoDB Atlas
- Solana
- ElevenLabs Project Structure Architecture Pages & Routes Data Models Tech Stack
App name: Com-Plan-ion Hackathon: IndyHack 2026 Node version: 18+ Framework: Next.js 14 (App Router) Language: TypeScript Mock mode: Fully functional with zero API keys
The core demo scenario:
- Organizer describes their event in natural language
- Gemini turns it into a structured plan with schedule, vendor recs, and risks
- MongoDB Atlas Vector Search finds the most semantically relevant vendors
- Gemini detects planning conflicts (deposit timing, budget overruns)
- Solana mints a compressed NFT ticket with rich metadata and QR code
- A public guest event page is generated automatically
- ElevenLabs powers a voice concierge that answers guest questions in the organizer's cloned voice
- Node.js 18+ and npm 9+
- Git
- A Google AI Studio account (Gemini API key)
- A MongoDB Atlas cluster with Vector Search enabled
- A Solana CLI keypair (devnet)
- An ElevenLabs account (API key)
node --version # must print v18.x.x or higherIf you need to install or upgrade:
macOS
brew install nodeUbuntu / Debian
# via nvm (recommended — avoids sudo and version conflicts)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc # or restart your terminal
nvm install 18
nvm use 18Windows — download the LTS installer from nodejs.org.
git clone https://github.com/your-org/indyhack2026-project.git
cd indyhack2026-projectnpm installTakes 30–60 seconds. If you hit peer dependency errors, run:
npm install --legacy-peer-depscp .env.example .env.localThe default file already contains MOCK_MODE=true. No API keys are needed to run the full demo.
Development (with hot reload):
npm run devProduction build (faster, closer to a real deployment):
npm run build
npm startOpen http://localhost:3000 in your browser.
If port 3000 is already in use:
npm run dev -- -p 3001Edit .env.local and set MOCK_MODE=false, then add keys for each service you want to use. Services without keys fall back to mock mode individually — you can mix real and mock services.
- Go to https://aistudio.google.com/app/apikey
- Create a new API key
- Add to
.env.local:
GEMINI_API_KEY=your_key_hereThe app uses:
gemini-1.5-profor event planning, chat, and conflict detectiontext-embedding-004for generating vendor embedding vectors (768 dimensions)
Relevant file: src/lib/services/gemini.ts
- Create a free cluster at https://cloud.mongodb.com
- Create a database named
complanion - Get the connection string from Connect → Drivers → Node.js
- Add to
.env.local:
MONGODB_URI=mongodb+srv://<user>:<password>@<cluster>.mongodb.net/
MONGODB_DB_NAME=complanionSetting up Atlas Vector Search (for vendor semantic search):
In the Atlas UI, go to your cluster → Search → Create Search Index → JSON editor, then apply this to the vendors collection:
{
"fields": [
{
"type": "vector",
"path": "embeddingVector",
"numDimensions": 768,
"similarity": "cosine"
}
]
}Name the index vendor_embedding.
Seeding real data into Atlas:
Visit http://localhost:3000/api/seed to retrieve all mock seed data as JSON. Import it into your Atlas collections using mongoimport or the Atlas Data Explorer.
Relevant file: src/lib/services/mongodb.ts
The app targets Solana devnet by default.
- Install the Solana CLI: https://docs.solana.com/cli/install-solana-cli-tools
- Generate a wallet keypair:
solana-keygen new --outfile /tmp/mint-keypair.json
solana airdrop 2 $(solana-keygen pubkey /tmp/mint-keypair.json) --url devnet- Add to
.env.local:
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_MINT_KEYPAIR=<base58-encoded private key>The ticket minting architecture uses Metaplex Bubblegum (compressed NFTs). The mintTicket function in src/lib/services/solana.ts has a // TODO: Implement Metaplex Bubblegum minting scaffold with the connection setup already wired. To complete it, install the Metaplex JS SDK and follow the Bubblegum docs.
Relevant file: src/lib/services/solana.ts
- Create an account at https://elevenlabs.io
- Copy your API key from Settings → API Keys
- Add to
.env.local:
ELEVENLABS_API_KEY=your_key_hereOptional — organizer voice cloning:
- Go to https://elevenlabs.io/voice-lab
- Create a new voice clone using a short audio recording
- Copy the Voice ID and add:
ELEVENLABS_CLONED_VOICE_ID=your_voice_id_hereIn the app, toggle "Organizer Voice" mode on the Voice Concierge page to use the cloned voice.
The app uses the eleven_turbo_v2 model with stability 0.5 and similarity boost 0.75.
Relevant file: src/lib/services/elevenlabs.ts
- Open
http://localhost:3000 - Click "Run 3-Minute Demo" or navigate to
/demo - Press the "Run Hackathon Demo" button
- The app auto-progresses through 9 steps with animations — narrate along
indyhack2026-project/
├── src/
│ ├── app/
│ │ ├── layout.tsx Root layout — fonts, providers, Toaster
│ │ ├── page.tsx Landing page (/)
│ │ ├── demo/
│ │ │ └── page.tsx Scripted demo runner (/demo)
│ │ ├── dashboard/
│ │ │ ├── layout.tsx Sidebar + TopBar shell
│ │ │ ├── page.tsx Overview dashboard (/dashboard)
│ │ │ ├── planner/page.tsx AI planning workspace
│ │ │ ├── vendors/page.tsx Vendor matching
│ │ │ ├── budget/page.tsx Budget intelligence
│ │ │ ├── operations/page.tsx Timeline & operations
│ │ │ ├── tickets/page.tsx Solana NFT ticketing
│ │ │ └── voice/page.tsx ElevenLabs voice concierge
│ │ ├── event/[slug]/
│ │ │ └── page.tsx Public guest event microsite
│ │ └── api/
│ │ ├── gemini/route.ts POST — event planning + chat
│ │ ├── vendors/route.ts GET — vector search
│ │ ├── tickets/mint/route.ts POST — Solana NFT mint
│ │ ├── voice/route.ts POST — ElevenLabs TTS
│ │ └── seed/route.ts GET — export seed data as JSON
│ │
│ ├── components/
│ │ ├── layout/
│ │ │ ├── Sidebar.tsx Left nav with active state + event badge
│ │ │ └── TopBar.tsx Page title + alert bell + demo button
│ │ └── shared/
│ │ ├── StatCard.tsx Animated KPI card
│ │ ├── AlertCard.tsx AI insight card (dismissible)
│ │ ├── LoadingSkeleton.tsx Shimmer skeletons for all card types
│ │ └── EmptyState.tsx Empty state with icon + action
│ │
│ ├── lib/
│ │ ├── services/
│ │ │ ├── gemini.ts Gemini adapter — real + mock
│ │ │ ├── mongodb.ts MongoDB adapter — real + mock
│ │ │ ├── solana.ts Solana adapter — devnet + mock
│ │ │ └── elevenlabs.ts ElevenLabs adapter — real + mock
│ │ ├── store/
│ │ │ └── eventStore.ts Zustand global state
│ │ ├── data/
│ │ │ ├── events.ts Demo event, memory, guests, AI insights
│ │ │ ├── vendors.ts 15 vendors + semantic scoring function
│ │ │ └── budgets.ts 10 budget items + 15 timeline milestones
│ │ ├── schemas/
│ │ │ └── index.ts Zod schemas + TypeScript types (all models)
│ │ └── utils.ts cn(), formatCurrency(), formatDate(), etc.
│ │
│ └── styles/
│ └── globals.css CSS variables, utility classes, animations
│
├── .env.example All supported env vars with docs
├── .env.local Local config (MOCK_MODE=true by default)
├── next.config.mjs
├── tailwind.config.ts
├── tsconfig.json
└── README.md
┌─────────────────────────────────────────────────────────┐
│ Browser / Client │
│ Next.js App Router · Zustand State · Framer Motion │
└──────────────┬──────────────────────────────────────────┘
│ fetch / server actions
┌──────────────▼──────────────────────────────────────────┐
│ API Routes (Edge) │
│ /api/gemini /api/vendors /api/tickets/mint /api/voice│
└──────────────┬──────────────────────────────────────────┘
│
┌──────────────▼──────────────────────────────────────────┐
│ Service Layer │
│ gemini.ts · mongodb.ts · solana.ts · elevenlabs.ts│
│ │
│ MOCK_MODE=true ──────────▶ src/lib/data/*.ts │
│ MOCK_MODE=false ──────────▶ Real external APIs │
└──────────────────────────────────────────────────────────┘
Key design decision: Every external integration is abstracted behind src/lib/services/*.ts. Swapping from mock to real is a single .env.local change — no application code changes needed. This also means each sponsor integration can be demonstrated independently.
| Route | Description |
|---|---|
/ |
Landing page — hero, feature grid, sponsor badges, animated preview |
/demo |
Scripted 9-step hackathon demo runner |
/dashboard |
Event overview — stats, AI alerts, budget strip, upcoming milestones |
/dashboard/planner |
AI chat workspace — Gemini plan generation + conflict detection |
/dashboard/vendors |
Vendor matching — semantic search, relevance scores, compare modal |
/dashboard/budget |
Budget intelligence — Recharts charts, AI recommendations, line items |
/dashboard/operations |
Timeline — milestone checklist, live updates panel, run-of-show |
/dashboard/tickets |
Solana ticketing — wallet connect, NFT mint, QR code, escrow |
/dashboard/voice |
Voice concierge — ElevenLabs TTS, transcript, voice selector |
/event/[slug] |
Public guest microsite — RSVP, agenda, FAQ, embedded concierge |
/api/gemini |
POST — Gemini event plan + chat endpoint |
/api/vendors |
GET ?q= — vector vendor search endpoint |
/api/tickets/mint |
POST — Solana NFT mint endpoint |
/api/voice |
POST — ElevenLabs TTS endpoint |
/api/seed |
GET — Export all seed data as JSON |
All models are defined as Zod schemas in src/lib/schemas/index.ts and used identically in mock data and real Atlas collections.
| Collection | Key fields |
|---|---|
events |
slug, name, date, location, guestCount, budget, status |
eventMemory |
eventId, context, decisions[], preferences, constraints |
vendors |
category, specialties, pricePerHead/flatRate, rating, embeddingVector |
guests |
eventId, mealPreference, accessTier, rsvpStatus, ticketId |
tickets |
mintAddress, tier, metadata (attendeeName, perks, POAP), qrCode |
budgets |
category, label, projected, actual, isPaid, dueDate |
timelineItems |
type (milestone/deadline/task/deposit/runofshow), status, priority, dueDate |
aiInsights |
type (conflict/warning/suggestion/opportunity), severity, isResolved |
voiceLogs |
question, answer, audioUrl, voice, durationMs |
escrowMilestones |
vendorId, amount, currency (SOL/USDC), condition, status |
| Layer | Library |
|---|---|
| Framework | Next.js 14 (App Router) |
| Language | TypeScript |
| Styling | Tailwind CSS |
| UI primitives | Radix UI (via shadcn/ui pattern) |
| Animation | Framer Motion |
| State | Zustand |
| Charts | Recharts |
| Forms | React Hook Form + Zod |
| QR codes | qrcode.react |
| Notifications | Sonner |
| Icons | Lucide React |
| Fonts | Inter · Plus Jakarta Sans · JetBrains Mono |
| Blockchain | @solana/web3.js |
| Database | MongoDB Node.js driver |
Built for IndyHack 2026 · Node 18 · Next.js 14 · MOCK_MODE=true runs everything offline