# Project export: AMPLIE

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 12.0
- Tagline: Have you ever gone home after a terrible day, and to make it worse, you can't find any good songs to improve your mood? We introduce AMPLIE, an app run by AI agents to determine your perfect playlist.
- Devpost: https://devpost.com/software/amplie
- GitHub: https://github.com/sezavala/AMPLIE-cloud
- Demo: https://github.com/sezavala/AMPLIE-app
- Video: https://www.youtube.com/embed/QhWaKfUgvus?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — Sergio Zavala (9 commits), aleguzmancs9 (9 commits)

## Devpost submission (written by the team)

### Inspiration

Music has always been something that spoke to us. Music can be used as a sort of therapy for some people. However, we are only limited to the music we like, not by what music may help us. We introduce AMPLIE (Auto-Generated Music Playlist Linked to an Individual's Emotions), a web app that tracks a user's actions throughout the day and generates a policy for the best music tracks to help them "reflect" or "work with" their emotions. We were inspired by: Mental health awareness: Music therapy is scientifically proven to help manage anxiety, depression, and stress Privacy concerns: Emotion data and an individual's activity data is personal. Social connection: Shared music experiences bring people together, even when they're feeling different things

### What it does

AMPLIE (Auto-generated Music Playlist Linked to Individuals' Emotions) is an emotion-aware music platform that generates personalized playlists tailored to your mood—whether solo or in groups. 🎵 Core Features 1. Individual Mood Detection Users input how they're feeling via text or voice Groq AI (LLaMA 3.1) analyzes the emotional content Returns detected emotion with confidence score 2. Intelligent Policy Mapping ASI:One translates emotions into musical attributes: Tempo (BPM) Energy (0-1 scale) Valence (happiness/positivity) Genre preferences Tempo (BPM) Energy (0-1 scale) Valence (happiness/positivity) Genre preferences Supports two modes: "Reflect my mood" -> Match your current emotion "Work with my mood" -> Balance/uplift your emotion "Reflect my mood" -> Match your current emotion "Work with my mood" -> Balance/uplift your emotion 3. Semantic Track Retrieval Chroma vector database stores music embeddings Semantic similarity search finds tracks matching your emotional policy Returns ranked playlist with match percentages 4. Group Room Mood Blending Multiple users join a shared room via Fetch.ai agents Each person sets their individual mood ShareAgent negotiates and blends emotional policies Generates a compromise playlist that works for everyone Perfect for car rides, parties, or study sessions with friends 5. Privacy-First Design Explicit consent flow before any data processing Local storage for history (expo-secure-store) No background recording Transparent data usage

### How we built it

🏗️ Architecture We built AMPLIE as a full-stack mobile application with multi-agent orchestration: 🛠️ Tech Stack Frontend: React Native + Expo: Cross-platform mobile development TypeScript: Type safety and developer experience Expo Router: File-based navigation Zustand: Lightweight state management expo-av: Audio recording and playback Clerk: OAuth authentication (Google/Apple) NativeWind: Tailwind CSS for React Native Backend: Node.js 20 + TypeScript: Modern JavaScript runtime Fastify: High-performance web framework Chroma: Vector database for embeddings Docker: Containerized Chroma deployment AI/ML Services: Groq: LLM-based emotion detection (LLaMA 3.1-8b-instant) ASI:One: Emotion-to-music policy mapping Chroma: Semantic similarity search Fetch.ai/Agentverse: Multi-agent room negotiation DevOps: Postman: API testing (16 automated tests) Git: Version control npm/pnpm: Package management 👥 Team Division (4 Developers) Frontend Lead: React Native app, UI/UX, consent flow, audio playback ML Lead: Emotion detection, Groq integration, on-device model research Backend Lead: Fastify API, ASI:One, Chroma, Postman tests Agent Lead: Fetch.ai agents, ShareAgent, room orchestration, Docker 📋 Build Process (48 Hours) Hours 0-8: Setup repos, scaffold frontend/backend, implement consent flow Hours 8-16: Emotion detection (Groq), policy mapping (ASI:One), track embeddings (Chroma) Hours 16-24: Connect frontend ↔ backend, build playlist UI, test individual flow Hours 24-36: Implement group rooms, deploy ShareAgent, test mood blending Hours 36-44: UI polish, comprehensive testing, Postman collection, documentation Hours 44-48: Final integration, demo rehearsal, Devpost submission

### Challenges we ran into

1. Audio API Migration Hell 🎤 Started with expo-audio-recorder → deprecated Tried AudioRecorder from Expo → doesn't exist in current SDK Solution: Migrated to expo-av Audio API with proper permission handling Learned: Always check package compatibility with current Expo SDK version 2. Agent Communication Debugging 🤖 Fetch.ai agents needed precise message formats ShareAgent wasn't receiving room mood updates Solution: Implemented request/response logging, validated JSON schemas Added health check endpoints for agent monitoring 3. Vector Embedding Quality 📊 Initial track retrieval returned poor matches Track metadata wasn't normalized (tempo ranges, genre tags) Solution: Preprocessed embeddings with weighted features, normalized scales Improved match accuracy from ~40% to ~85% 4. Real-time Group Synchronization 👥 Multiple users setting moods simultaneously caused race conditions ShareAgent needed to debounce rapid updates Solution: Implemented request queuing, added 3-second debounce for playlist generation Used in-memory state management with timestamp validation 5. Frontend ↔ Backend Integration 🔌 Initially used mock data for everything Connecting real APIs revealed error handling gaps Solution: Enhanced lib/api.ts with retry logic, timeout handling, user-friendly errors Added loading states for all async operations 6. Time Management ⏰ Ambitious scope (Fish Audio, Letta Cloud, Visa API) Had to prioritize core features over nice-to-haves Solution: Focused on 3 strong integrations (Groq, Chroma, Fetch.ai) rather than 7 weak ones Built modular architecture for future expansion 7. Testing on Physical Devices 📱 localhost doesn't work on phones Needed local network IP addresses Solution: Created environment variable guide, added network detection helper Used QR code scanning for easy testing

### Accomplishments we're proud of

🏆 Technical Achievements Multi-Agent Orchestration: Successfully implemented Fetch.ai agent-to-agent negotiation for real-time mood blending—one of the most complex features we've built Multi-Agent Orchestration: Successfully implemented Fetch.ai agent-to-agent negotiation for real-time mood blending—one of the most complex features we've built Semantic Music Search: Chroma vector database retrieves tracks with 85%+ match accuracy using embedding-based similarity Semantic Music Search: Chroma vector database retrieves tracks with 85%+ match accuracy using embedding-based similarity Production-Ready Testing: Created 16 automated Postman tests with 100% endpoint coverage and detailed assertions Production-Ready Testing: Created 16 automated Postman tests with 100% endpoint coverage and detailed assertions Privacy Architecture: Built explicit consent system with local storage and transparent data usage—no creepy background tracking Privacy Architecture: Built explicit consent system with local storage and transparent data usage—no creepy background tracking Complete Documentation: 5 comprehensive markdown files (1000+ lines) covering setup, architecture, troubleshooting, and demo scripts Complete Documentation: 5 comprehensive markdown files (1000+ lines) covering setup, architecture, troubleshooting, and demo scripts 🎨 Product Achievements Intuitive UX: Clean, accessible interface with color-coded moods, waveform visualizations, and smooth animations Intuitive UX: Clean, accessible interface with color-coded moods, waveform visualizations, and smooth animations Dual Input Modes: Support for both text and voice input to accommodate different user preferences Dual Input Modes: Support for both text and voice input to accommodate different user preferences Group Experience: Solved the "what should we listen to?" problem with algorithmic mood blending Group Experience: Solved the "what should we listen to?" problem with algorithmic mood blending Demo-Ready: Fully functional app that works end-to-end—not just slides and mockups Demo-Ready: Fully functional app that works end-to-end—not just slides and mockups 🚀 Team Achievements Parallel Development: Frontend, backend, agents, and DevOps worked simultaneously with minimal conflicts Parallel Development: Frontend, backend, agents, and DevOps worked simultaneously with minimal conflicts Knowledge Sharing: Every team member learned new technologies (React Native, Fastify, Fetch.ai, Chroma) Knowledge Sharing: Every team member learned new technologies (React Native, Fastify, Fetch.ai, Chroma) 48-Hour Sprint: Went from idea to fully functional demo with comprehensive testing in 2 days 48-Hour Sprint: Went from idea to fully functional demo with comprehensive testing in 2 days

### What we learned

🧠 Technical Learnings Vector Databases Are Powerful: Chroma's semantic search eliminated complex filtering logic—embeddings just "understand" similarity Vector Databases Are Powerful: Chroma's semantic search eliminated complex filtering logic—embeddings just "understand" similarity Agent-Based Systems Are Hard: Debugging asynchronous multi-agent systems requires excellent logging and monitoring Agent-Based Systems Are Hard: Debugging asynchronous multi-agent systems requires excellent logging and monitoring LLMs for Emotion Detection Work Well: Groq + LLaMA 3.1 achieved surprisingly high accuracy with simple prompts LLMs for Emotion Detection Work Well: Groq + LLaMA 3.1 achieved surprisingly high accuracy with simple prompts TypeScript Saves Time: Caught 50+ bugs at compile-time that would've been runtime disasters TypeScript Saves Time: Caught 50+ bugs at compile-time that would've been runtime disasters Testing Early Matters: Postman tests caught integration bugs before they reached the app Testing Early Matters: Postman tests caught integration bugs before they reached the app 🎨 Product Learnings Privacy Is a Feature: Users loved the explicit consent flow—transparency builds trust Privacy Is a Feature: Users loved the explicit consent flow—transparency builds trust Emotion Modes Matter: "Reflect" vs "Work with" resonated strongly—people want control over whether music matches or shifts their mood Emotion Modes Matter: "Reflect" vs "Work with" resonated strongly—people want control over whether music matches or shifts their mood Group Features Are Complex: Synchronization, conflict resolution, and fairness algorithms are non-trivial Group Features Are Complex: Synchronization, conflict resolution, and fairness algorithms are non-trivial 👥 Team Learnings Scope Ruthlessly: Better to nail 3 integrations than half-finish 7 Scope Ruthlessly: Better to nail 3 integrations than half-finish 7 Document as You Build: READMEs written during development are 10x better than post-hoc documentation Document as You Build: READMEs written during development are 10x better than post-hoc documentation Demo is King: Judges care more about working features than architectural perfection Demo is King: Judges care more about working features than architectural perfection 🌐 Ecosystem Learnings Sponsor Tools Are Powerful: Fetch.ai, ASI:One, Groq, and Chroma provided capabilities we couldn't build in 48 hours Sponsor Tools Are Powerful: Fetch.ai, ASI:One, Groq, and Chroma provided capabilities we couldn't build in 48 hours API Design Matters: Consistent error formats and response structures made integration painless API Design Matters: Consistent error formats and response structures made integration painless Docker Simplifies Deployment: Chroma running in a container eliminated setup headaches Docker Simplifies Deployment: Chroma running in a container eliminated setup headaches

### What's next

🎯 Short-Term (Next 2 Weeks) Complete Fish Audio Integration: Generate 20-30s music clips from emotional policies Letta Cloud Memory: Store long-term mood patterns for personalized recommendations Visa Tipping: Enable artist/creator support with micro-donations On-Device Emotion Model: TensorFlow Lite for fully local inference (no cloud calls) iOS + Android Builds: Publish to App Store and Google Play (TestFlight/beta) 🚀 Medium-Term (Next 3 Months) Spotify/Apple Music Integration: Play full tracks, not just metadata Advanced Mood Blending: ML-based fairness algorithms for groups >2 people Emotion History Analytics: Visualize mood patterns over time Playlist Sharing: Export to Spotify, create shareable links Voice Commands: "Play something uplifting" hands-free control Wearable Integration: Apple Watch, Fitbit for context-aware music (workout, sleep) 🌟 Long-Term Vision (6+ Months) Music Therapy Partnerships: Collaborate with mental health professionals for clinical validation Artist Collaboration: Let musicians tag tracks with emotional metadata Community Rooms: Public mood-based listening parties (study, workout, chill) Emotion Insights: Optional analytics for users to understand emotional patterns Multi-Modal Input: Detect emotion from photos, calendar events, biometric data (with consent) Accessibility Features: Audio descriptions, high-contrast modes, screen reader support International Expansion: Support for 20+ languages, cultural music preferences B2B Licensing: Workplace wellbeing programs, therapy clinics, fitness studios Research Platform: Anonymized, opt-in dataset for emotion-music research 💡 Moonshot Ideas AI-Generated Music: Beyond retrieval—create original tracks for your exact emotional state Emotional Social Network: Connect with others feeling similar emotions (with privacy controls) Predictive Mood Detection: Anticipate emotional needs based on time, location, history VR Music Therapy: Immersive audiovisual experiences for emotional regulation 🔗 Links GitHub (Backend): AMPLIE-cloud GitHub (Frontend): AMPLIE-app Demo Video: [Coming Soon - YouTube] Postman Collection: Available in /postman directory Architecture Diagram: See ARCHITECTURE.md in repo 👥 Team 4 Developers | 48 Hours | Built at CalHacks 2025 Frontend Lead - Mobile app, UI/UX, consent flow ML Lead - Emotion detection, Groq integration Backend Lead - API, integrations, testing Agent Lead - Fetch.ai agents, orchestration 🙏 Acknowledgments Special thanks to: CalHacks organizers for an incredible hackathon Fetch.ai for agent infrastructure and support ASI:One for emotion mapping technology Groq for lightning-fast LLM inference Chroma for vector database capabilities Postman for testing tools The entire open-source community for making this possible AMPLIE - Music that understands you 🎵❤️ Built with ❤️ in 48 hours at CalHacks 2025

## README (from the GitHub repository)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.


## Detected evidence (automated analysis)

Indexed codebase: 26 recognized source files, 59 KB.
- CSS (language) — detected in the code
- Next.js (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (35 of 35)

```
.gitignore
agents/agent.py
agents/share_agent.py
api/[...path].ts
eslint.config.mjs
next.config.ts
package.json
postman/collections/amplie-api.postman_collection.json
postman/environments/local.postman_collection.json
postman/environments/staging.postman_environment.json
README.md
src/api/app.ts
src/api/routes/embed.ts
src/api/routes/emotion.ts
src/api/routes/generate.ts
src/api/routes/policy.ts
src/api/routes/retrieve.ts
src/api/routes/room.ts
src/api/services/fishAudio.ts
src/api/services/storage.ts
src/app/clients/asione.ts
src/app/clients/chroma.ts
src/app/clients/groq.ts
src/app/data/chroma-data/seed.json
src/app/env.ts
src/app/globals.css
src/app/layout.tsx
src/app/middleware/auth.ts
src/app/page.module.css
src/app/page.tsx
src/index.ts
test-api.sh
test-chroma.ts
tsconfig.json
vercel.json
```

### Dependencies

- package.json: @aws-sdk/client-s3@^3.917.0, @fastify/cors@^11.1.0, @fastify/helmet@^13.0.2, @fastify/sensible@^6.0.3, @types/node@^20.19.23, @types/react@^19, @types/react-dom@^19, @typescript-eslint/eslint-plugin@^8.46.2, @typescript-eslint/parser@^8.46.2, babel-plugin-react-compiler@1.0.0, dotenv@^17.2.3, eslint@^9.38.0, eslint-config-next@16.0.0, fastify@^5.6.1, jose@^6.1.0, newman@^6.2.1, newman-reporter-htmlextra@^1.23.1, next@16.0.0, nodemon@^3.1.10, react@19.2.0, react-dom@19.2.0, tsx@^4.20.6, typescript@^5.9.3, zod@^4.1.12

### Recent commits (newest first)

- Implemented rooms to allow users to join and test audio / text retrieval and playlist generation (#24)
- Merge pull request #22 from sezavala/generate-fish-audio&signed-storage
- Merge branch 'main' into generate-fish-audio&signed-storage
- Implemented chroma  for policy storage (#23)
- integrate Fish Audio TTS + S3 upload with emotion-based generation prompt
- Sergio emotion endpoint (#21)
- Sergio emotion/mode (#20)
- Merge pull request #19 from sezavala/ShareAgent-group-mood-blending
- implement ShareAgent for group mood blending
- Merge pull request #18 from sezavala/Elastic-Agent-Builder-setup#8
- Merge pull request #17 from sezavala/sergio_JWT_API
- Merge branch 'main' into sergio_JWT_API
- merge conflict for package-lock
- complete Elastic Agent Builder setup with local DJAgent
- Implemented JWT auth and initialized starting endpoints for health + protected endpoint
- base packagelock
- Update .gitignore
- Base Layout

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

### package.json

```
{
  "name": "amplie-cloud",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "nodemon --watch src --ext ts --exec \"npx tsx src/index.ts\"",
    "start": "node dist/local.js",
    "build": "tsc -p tsconfig.json",
    "lint": "eslint .",
    "vercel-build": "tsc -p tsconfig.json",
    "test": "echo \"(add tests later)\"",
    "pm:test:local": "newman run postman/collections/amplie-api.postman_collection.json -e postman/environments/local.postman_environment.json -r cli,htmlextra --reporter-htmlextra-export postman/reports/local.html",
    "pm:test:staging": "newman run postman/collections/amplie-api.postman_collection.json -e postman/environments/staging.postman_environment.json -r cli,htmlextra --reporter-htmlextra-export postman/reports/staging.html"
  },
  "dependencies": {
    "@aws-sdk/client-s3": "^3.917.0",
    "@fastify/cors": "^11.1.0",
    "@fastify/helmet": "^13.0.2",
    "@fastify/sensible": "^6.0.3",
    "dotenv": "^17.2.3",
    "fastify": "^5.6.1",
    "jose": "^6.1.0",
    "next": "16.0.0",
    "react": "19.2.0",
    "react-dom": "19.2.0",
    "zod": "^4.1.12"
  },
  "devDependencies": {
    "@types/node": "^20.19.23",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "@typescript-eslint/eslint-plugin": "^8.46.2",
    "@typescript-eslint/parser": "^8.46.2",
    "babel-plugin-react-compiler": "1.0.0",
    "eslint": "^9.38.0",
    "eslint-config-next": "16.0.0",
    "newman": "^6.2.1",
    "newman-reporter-htmlextra": "^1.23.1",
    "nodemon": "^3.1.10",
    "tsx": "^4.20.6",
    "typescript": "^5.9.3"
  },
  "description": "This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/sezavala/AMPLIE-cloud.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "bugs": {
    "url": "https://github.com/sezavala/AMPLIE-cloud/issues"
  },
  "homepage": "https://github.com/sezavala/AMPLIE-cloud#readme"
}

```

### src/index.ts

```typescript
import { buildApp } from "./api/app.js";
import { ENV } from "./app/env.js";

async function main() {
  // Build our Fastify App to access routes
  const app = buildApp();
  try {
    await app.listen({ port: ENV.PORT, host: "0.0.0.0" });
    app.log.info(`API listening on http://localhost:${ENV.PORT}`);
  } catch (err) {
    app.log.error(err);
    process.exit(1);
  }
}

main();

```

### src/app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={`${geistSans.variable} ${geistMono.variable}`}>
        {children}
      </body>
    </html>
  );
}

```

### src/api/app.ts

```typescript
import Fastify from "fastify";
import cors from "@fastify/cors";
import helmet from "@fastify/helmet";
import sensible from "@fastify/sensible";
import authPlugin from "../app/middleware/auth.js";
import { ENV } from "../app/env.js";

// Existing routes
import policyRoutes from "./routes/policy.js";
import emotionRoutes from "./routes/emotion.js";
import embedRoutes from "./routes/embed.js";
import retrieveRoutes from "./routes/retrieve.js";
// import generateRoute from "./routes/generate.js"; // ❌ Temporarily comment out

// Room routes
import roomRoutes from "./routes/room.js";

export function buildApp() {
  const app = Fastify({
    logger: {
      level: process.env.NODE_ENV === "production" ? "info" : "debug",
    },
  });

  app.register(cors, { origin: true });
  app.register(helmet);
  app.register(sensible);
  app.register(authPlugin);

  // Business logic routes
  app.register(policyRoutes);
  // app.register(generateRoute); // ❌ Temporarily disabled
  app.register(emotionRoutes);
  app.register(embedRoutes);
  app.register(retrieveRoutes);
  app.register(roomRoutes);

  app.get("/health", async () => {
    return { status: "ok", version: ENV.API_VERSION };
  });

  app.get("/protected", { preHandler: app.verifyJWT }, async (request) => {
    return { ok: true, sub: request.user?.sub, version: ENV.API_VERSION };
  });

  return app;
}

```

### src/app/page.tsx

```typescript
import Image from "next/image";
import styles from "./page.module.css";

export default function Home() {
  return (
    <div className={styles.page}>
      <main className={styles.main}>
        <Image
          className={styles.logo}
          src="/next.svg"
          alt="Next.js logo"
          width={100}
          height={20}
          priority
        />
        <div className={styles.intro}>
          <h1>To get started, edit the page.tsx file.</h1>
          <p>
            Looking for a starting point or more instructions? Head over to{" "}
            <a
              href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
              target="_blank"
              rel="noopener noreferrer"
            >
              Templates
            </a>{" "}
            or the{" "}
            <a
              href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learning
            </a>{" "}
            center.
          </p>
        </div>
        <div className={styles.ctas}>
          <a
            className={styles.primary}
            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            <Image
              className={styles.logo}
              src="/vercel.svg"
              alt="Vercel logomark"
              width={16}
              height={16}
            />
            Deploy Now
          </a>
          <a
            className={styles.secondary}
            href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            Documentation
          </a>
        </div>
      </main>
    </div>
  );
}

```

### next.config.ts

```typescript
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
  reactCompiler: true,
};

export default nextConfig;

```

### test-api.sh

```shell
#!/bin/bash
# Test AMPLIE Chroma Integration

echo "🧪 Testing AMPLIE API with Chroma..."
echo ""

# 1. Health check
echo "1️⃣  Health Check"
curl -s http://localhost:3000/health | jq -C '.'
echo ""

# 2. Embed tracks  
echo "2️⃣  Embedding Tracks"
curl -s -X POST http://localhost:3000/embed | jq -C '.'
echo ""

# 3. Retrieve happy/energetic tracks
echo "3️⃣  Retrieving Happy/Energetic Tracks (EDM/Pop, 128 BPM)"
curl -s -X POST http://localhost:3000/retrieve \
  -H "content-type: application/json" \
  -d '{
    "policy": {
      "tempo": 128,
      "energy": 0.85,
      "valence": 0.9,
      "genres": ["pop", "edm"]
    },
    "k": 3
  }' | jq -C '.'
echo ""

# 4. Retrieve sad/low-energy tracks  
echo "4️⃣  Retrieving Sad/Low-Energy Tracks (Ambient, 70 BPM)"
curl -s -X POST http://localhost:3000/retrieve \
  -H "content-type: application/json" \
  -d '{
    "policy": {
      "tempo": 70,
      "energy": 0.3,
      "valence": 0.2,
      "genres": ["ambient", "piano"]
    },
    "k": 2
  }' | jq -C '.'

echo ""
echo "✅ All tests complete!"

```

### test-chroma.ts

```typescript
#!/usr/bin/env tsx
import { createChromaClient } from "./src/app/clients/chroma.js";
import seed from "./src/app/data/chroma-data/seed.json" assert { type: "json" };

async function test() {
  console.log("Testing Chroma client...");
  
  const chroma = createChromaClient();
  
  try {
    console.log("\n1. Upserting tracks...");
    const { collection, count } = await chroma.upsert("amplie_tracks_v1", seed);
    console.log(`✓ Upserted ${count} tracks to collection: ${collection.name}`);
    
    console.log("\n2. Querying for happy/energetic tracks...");
    const results = await chroma.query(
      "amplie_tracks_v1",
      {
        tempo: 128,
        energy: 0.85,
        valence: 0.9,
        genres: ["pop", "edm"],
      },
      3
    );
    
    console.log(`✓ Found ${results.results.length} results:`);
    results.results.forEach((r, i) => {
      console.log(
        `  ${i + 1}. ${r.metadata?.title} by ${r.metadata?.artist} (distance: ${r.distance.toFixed(4)})`
      );
    });
    
    console.log("\n✅ All tests passed!");
  } catch (err: any) {
    console.error("\n❌ Test failed:");
    console.error(err.message);
    if (err.stack) console.error(err.stack);
    process.exit(1);
  }
}

test();

```

### api/[...path].ts

```typescript
import type { FastifyInstance } from "fastify";
import { buildApp } from "../src/api/app.js";

let app: FastifyInstance | undefined;

export default async function handler(req: any, res: any) {
  try {
    if (!app) {
      app = buildApp();
      await app.ready();
    }
    // Normalize path so Fastify sees "/health" instead of "/api/health"
    if (typeof req.url === "string" && req.url.startsWith("/api/")) {
      req.url = req.url.slice(4) || "/";
    }
    app.server.emit("request", req, res);
  } catch (err) {
    res.statusCode = 500;
    res.setHeader("content-type", "application/json");
    res.end(JSON.stringify({ error: "Internal Server Error" }));
  }
}

```

### agents/share_agent.py

```python
from fastapi import FastAPI, Request
import uvicorn
import threading
import statistics
import json
import redis
import logging

# ----------------------------------------------------
# 🧠 Setup Logging
# ----------------------------------------------------
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
)

# ----------------------------------------------------
# ⚙️ Redis Connection
# ----------------------------------------------------
try:
    r = redis.Redis(host="localhost", port=6379, decode_responses=True)
    r.ping()
    logging.info("✅ Connected to Redis successfully.")
except redis.ConnectionError:
    logging.warning("⚠️ Redis is not running. Start it before using ShareAgent.")
    r = None

# ----------------------------------------------------
# 🎵 Emotion → Policy Mapping
# ----------------------------------------------------
EMOTION_MAP = {
    "happy": {"valence": 0.9, "tempo": 0.8},
    "sad": {"valence": 0.2, "tempo": 0.3},
    "angry": {"valence": 0.3, "tempo": 0.9},
    "relaxed": {"valence": 0.7, "tempo": 0.4},
    "hopeful": {"valence": 0.8, "tempo": 0.6},
    "tired": {"valence": 0.4, "tempo": 0.3},
}

# ----------------------------------------------------
# 🚀 FastAPI App
# ----------------------------------------------------
api = FastAPI(title="ShareAgent", version="1.0")

@api.get("/health")
async def health_check():
    """Simple health check endpoint."""
    redis_status = "connected" if r else "not connected"
    return {"status": "ok", "redis": redis_status, "agent": "ShareAgent"}

@api.get("/")
async def root():
    """Root route for browser access."""
    return {"message": "ShareAgent is running! Use /room/blend or /health."}

# ----------------------------------------------------
# 🔮 /room/blend — Group Mood Blending Endpoint
# ----------------------------------------------------
@api.post("/room/blend")
async def blend_emotions(req: Request):
    """
    Input: { "roomId": "room_001", "userEmotions": [{"userId": "u1", "emotion": "happy"}, ...] }
    Output: { "roomId": "room_001", "policy": {"valence": 0.6, "tempo": 0.5, "count": 3} }
    """
    data = await req.json()
    room_id = data.get("roomId")
    user_emotions = data.get("userEmotions", [])

    if not room_id or not user_emotions:
        return {"error": "roomId and userEmotions[] required"}

    valences = []
    tempos = []

    for ue in user_emotions:
        emo = ue.get("emotion", "").lower()
        if emo in EMOTION_MAP:
            valences.append(EMOTION_MAP[emo]["valence"])
            tempos.append(EMOTION_MAP[emo]["tempo"])
        else:
            logging.warning(f"⚠️ Unknown emotion: {emo}")

    if not valences:
        return {"error": "No valid emotions provided"}

    # Deterministic blend (same input → same output)
    blended_valence = round(statistics.mean(valences), 3)
    blended_tempo = round(statistics.mean(tempos), 3)

    policy = {
        "valence": blended_valence,
        "tempo": blended_tempo,
        "count": len(valences),
    }

    # Write result to Redis (for /room/playlist to use)
    if r:
        redis_key = f"room:{room_id}:policy"
        r.set(redis_key, json.dumps(policy))
        logging.info(f"📝 Stored blended policy in Redis: {redis_key} → {policy}")
    else:
        logging.warning("⚠️ Redis unavailable — skipping cache write.")

    return {"roomId": room_id, "policy": policy}

# ----------------------------------------------------
# 🧵 Entry Point
# ----------------------------------------------------
if __name__ == "__main__":
    print("🚀 Starting ShareAgent on http://127.0.0.1:5001 ...")
    uvicorn.run("share_agent:api", host="0.0.0.0", port=5001, reload=True)

```

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