# Project export: Eon - Earth Saga

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: Explore the world through environmental data and interactive storytelling
- Devpost: https://devpost.com/software/eon-earth-saga
- GitHub: https://github.com/Cmk31311/Eon
- Demo: https://eon-six.vercel.app/
- Video: https://www.youtube.com/embed/Wu_rzhCkWtI?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Cmk31311 (5 commits)

## Devpost submission (written by the team)

No Devpost description available.

## README (from the GitHub repository)

# 🌍 EON - Earth Saga

> **Interactive Environmental Data Visualization & Claude AI-Powered Storytelling**

An immersive web application that transforms real-time environmental data from 222+ global regions into dynamic, Claude AI-generated narratives with multi-voice text-to-speech capabilities.

![EON Earth Saga](https://img.shields.io/badge/Status-Production%20Ready-brightgreen)
![React](https://img.shields.io/badge/React-18.3.1-blue)
![TypeScript](https://img.shields.io/badge/TypeScript-5.5.4-blue)
![Claude AI](https://img.shields.io/badge/AI-Claude%20Sonnet%204.5-purple)
![Vercel](https://img.shields.io/badge/Deploy-Vercel-black)

## ✨ Features

### 🌐 Interactive 3D Globe
- **222+ Unique Regions** across multiple categories (Rainforest, Desert, Mountain, Coastal, Polar, Island, Plains)
- **Real-time Environmental Data** from Open-Meteo and OpenWeatherMap APIs
- **Smooth 3D Interactions** with Three.js and React Globe GL
- **Responsive Design** optimized for all devices

### 🤖 Claude AI-Powered Narratives
- **Dynamic Story Generation** using Claude Sonnet 4.5 API
- **Data-Driven Content** analyzing all environmental parameters
- **Unique Narratives** that change with each generation
- **Regional Context** with location-specific storytelling
- **Health Analysis** with implications and recommendations

### 🔊 Multi-Voice Text-to-Speech
- **Custom Voice Integration** with Fish Audio TTS
- **Multiple Voices** - rotates through available voices on each click
- **Real-time Audio Generation** with stop/play controls
- **High-Quality Audio** with professional voice synthesis

### 🎨 Advanced UI/UX
- **Glassmorphism Design** with modern aesthetics
- **Dark/Light Theme Toggle** with system preference detection
- **Smooth Animations** and micro-interactions
- **Performance Optimized** with lazy loading and memoization

### 🔍 Smart Features
- **Region Search** with instant filtering
- **Bookmark System** for favorite locations
- **Data Export** (CSV/JSON formats)
- **15+ Environmental Parameters**: Temperature, Humidity, Pressure, Wind, Precipitation, UV Index, Visibility, Cloud Cover, Solar Radiation, Air Quality, CO2, Ozone, Pollen, Soil Moisture, Noise Level

## 🚀 Quick Start

### Prerequisites
- Node.js 18+
- npm or yarn
- Anthropic Claude API key
- Fish Audio API key (for TTS)

### Installation

```bash
# Clone the repository
git clone https://github.com/Cmk31311/Eon.git
cd earthstory

# Install dependencies
cd frontend && npm install
cd ../server && npm install
```

### Environment Setup

Create a `.env` file in the root directory:

```env
# Anthropic Claude API
VITE_ANTHROPIC_API_KEY=your_anthropic_api_key_here

# Fish Audio TTS
FISH_API_KEY=your_fish_audio_api_key
FISH_VOICE_ID=your_voice_id
FISH_TTS_ENDPOINT=https://api.fish.audio/v1/tts
```

### Development

```bash
# Start the frontend development server (from frontend/)
npm run dev

# Start the TTS server (from server/) in another terminal
node index.js

# Open http://localhost:5173
```

## 🌐 Deployment

### Vercel (Recommended)

1. **Install Vercel CLI**
   ```bash
   npm i -g vercel
   ```

2. **Deploy**
   ```bash
   vercel login
   vercel
   ```

3. **Add Environment Variables** in Vercel Dashboard:
   ```
   VITE_ANTHROPIC_API_KEY=your_anthropic_api_key
   FISH_API_KEY=your_fish_audio_api_key
   FISH_VOICE_ID=your_voice_id
   FISH_TTS_ENDPOINT=https://api.fish.audio/v1/tts
   ```

## 🏗️ Architecture

### Frontend Stack
- **React 18** with TypeScript
- **Vite** for fast development and building
- **Tailwind CSS** for styling
- **Three.js** for 3D graphics
- **React Globe GL** for globe visualization
- **Anthropic SDK** for Claude AI integration

### Backend Services
- **Express.js** serverless functions (Vercel)
- **Fish Audio TTS** integration for voice synthesis
- **Open-Meteo API** for weather data
- **OpenWeatherMap** for air quality data

### Data Flow
```
User Interaction → Region Selection → API Data Fetch → Claude AI Analysis → Narrative Generation → Multi-Voice TTS → User Experience
```

## 📊 Environmental Data Sources

- **Weather Data**: Open-Meteo API (temperature, humidity, pressure, wind, precipitation, UV, visibility, clouds, solar radiation)
- **Air Quality**: OpenWeatherMap Air Pollution API (AQI, CO2, ozone, pollen)
- **Calculated Parameters**: Soil moisture, noise levels

## 🎯 Key Features Showcase

### 30-Second Demo
"EON Earth Saga transforms environmental data into immersive stories. Click any of 222 global regions to see real-time data analyzed by Claude AI, generating unique narratives that you can hear in multiple voices."

### Key Demo Points
1. **Interactive Globe**: "Explore 222 unique regions worldwide"
2. **Real-time Data**: "Live environmental parameters from space"
3. **Claude AI Analysis**: "Powered by Claude Sonnet 4.5"
4. **Multi-Voice TTS**: "Hear stories in different voices"
5. **Advanced Features**: "Search, bookmark, export data"

## 🔧 Configuration

### Environment Variables

```env
# Anthropic Claude API (Required for AI narratives)
VITE_ANTHROPIC_API_KEY=your_api_key_here

# Fish Audio TTS (Required for voice features)
FISH_API_KEY=your_api_key_here
FISH_VOICE_ID=your_voice_id
FISH_TTS_ENDPOINT=https://api.fish.audio/v1/tts
```

### Customization

- **Add Regions**: Edit `frontend/src/App.tsx` regions array
- **Modify Claude Prompts**: Update `frontend/src/services/claudeService.ts`
- **Change Styling**: Modify `frontend/src/index.css` and Tailwind config
- **Update APIs**: Configure in `frontend/src/services/environmentalDataService.ts`

## 📈 Performance

- **Bundle Size**: Optimized with code splitting
- **Loading**: Lazy loading for components
- **Caching**: Memoized calculations and API responses
- **Rendering**: React.memo for performance optimization
- **API Calls**: Efficient Claude API usage with fallback

## 🛠️ Development

### Project Structure
```
earthstory/
├── frontend/                 # React frontend
│   ├── src/
│   │   ├── components/       # React components
│   │   │   ├── EarthGlobe.tsx
│   │   │   ├── NarrativePanel.tsx
│   │   │   └── ThemeToggle.tsx
│   │   ├── services/         # API services
│   │   │   ├── claudeService.ts      # Claude AI integration
│   │   │   ├── narrativeService.ts   # Narrative orchestration
│   │   │   └── environmentalDataService.ts
│   │   ├── lib/             # Utilities
│   │   │   └── ttsClient.ts # Text-to-speech
│   │   └── utils/           # Helper functions
│   └── dist/                # Build output
├── server/                  # Express serverless functions
│   └── index.js            # TTS proxy server
├── vercel.json             # Vercel configuration
└── package.json            # Root package config
```

### Key Components
- **`App.tsx`**: Main application with 222 regions and data visualization
- **`EarthGlobe.tsx`**: 3D globe visualization
- **`NarrativePanel.tsx`**: Claude AI narrative display with TTS
- **`claudeService.ts`**: Claude AI API integration
- **`environmentalDataService.ts`**: Data fetching
- **`ttsClient.ts`**: Multi-voice text-to-speech

## 🤝 Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit changes (`git commit -m 'Add amazing feature'`)
4. Push to branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgments

- **Anthropic Claude AI** for intelligent narrative generation
- **Fish Audio** for text-to-speech capabilities
- **Open-Meteo** for weather data
- **OpenWeatherMap** for air quality data
- **Three.js** for 3D graphics
- **React Globe GL** for globe visualization

## 📞 Support

- **Repository**: [GitHub](https://github.com/Cmk31311/Eon)
- **Issues**: [GitHub Issues](https://github.com/Cmk31311/Eon/issues)

---

**Built with ❤️ for environmental awareness and storytelling**

*Transform data into stories. Explore the world through Claude AI-

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 25 recognized source files, 245 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- Express (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
- Node.js (technology) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository; commit authorship or trailers

## Codebase structure (from repository index)

### Files (38 of 38)

```
.claude/settings.local.json
.DS_Store
.env.example
.gitignore
.vercelignore
AI_MUSIC_GENERATION_FEATURE.md
backend/config.py
backend/services/anthropic_service.py
frontend/.DS_Store
frontend/.env.example
frontend/index.html
frontend/package.json
frontend/postcss.config.js
frontend/src/.DS_Store
frontend/src/App.tsx
frontend/src/components/EarthGlobe.tsx
frontend/src/components/NarrativePanel.tsx
frontend/src/components/ThemeToggle.tsx
frontend/src/index.css
frontend/src/lib/musicClient.ts
frontend/src/lib/ttsClient.ts
frontend/src/main.tsx
frontend/src/services/environmentalDataService.ts
frontend/src/services/musicGenerationService.ts
frontend/src/services/narrativeService.ts
frontend/src/utils/dataExport.ts
frontend/src/utils/imageOptimization.ts
frontend/src/utils/imageOptimization.tsx
frontend/src/utils/performance.ts
frontend/tailwind.config.js
frontend/tsconfig.json
frontend/vite.config.ts
package.json
README.md
SECURITY.md
server/index.js
server/package.json
vercel.json
```

### Dependencies

- frontend/package.json: @anthropic-ai/sdk@^0.67.0, @types/react@^18.2.66, @types/react-dom@^18.2.22, @vitejs/plugin-react@^4.7.0, autoprefixer@^10.4.21, axios@^1.7.2, postcss@^8.5.6, react@^18.3.1, react-dom@^18.3.1, react-globe.gl@^2.36.0, tailwindcss@^3.4.18, three@^0.180.0, typescript@^5.5.4, vite@^5.4.21
- package.json: @types/react@^18.2.66, @types/react-dom@^18.2.22, @vitejs/plugin-react@^4.7.0, autoprefixer@^10.4.21, axios@^1.7.2, cors@^2.8.5, dotenv@^17.2.3, express@^5.1.0, postcss@^8.5.6, react@^18.3.1, react-dom@^18.3.1, react-globe.gl@^2.36.0, tailwindcss@^3.4.18, three@^0.180.0, typescript@^5.5.4, vite@^5.4.21
- server/package.json: cors@^2.8.5, dotenv@^16.3.1, express@^4.18.2

### Recent commits (newest first)

- Merge pull request #2
- Add security documentation and API key protection guide
- Merge pull request #1
- Add AI music generation feature based on environmental data
- Fix Vercel config: Remove builds property conflict
- Updated new Features
- Update README
- Integrate Claude API, add TTS with multiple voices, remove Generate New button
- Initial Commit - EON
- Enhanced UI with categorized region selection
- Updated readme
- Add .gitignore and remove node_modules
- Initial commit: Eon - Earth Saga

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

### SECURITY.md

```markdown
# 🔐 Security Configuration

## ✅ Current Security Status

Your API keys are **SECURE** and properly protected:

1. ✅ `.env` file is in `.gitignore`
2. ✅ `.env` file is **NOT** tracked by git
3. ✅ `.env` file is **NOT** in the remote repository
4. ✅ Only `.env.example` with placeholder values is committed

## 🔒 Protected Files

The following files contain secrets and are **gitignored**:
- `.env` (contains real API keys)
- `frontend/.env`
- Any files matching: `*secret*`, `*key*`, `*token*`, `*password*`, `*credential*`

## 📄 Safe Files

These files are safe to commit (no secrets):
- `.env.example` (only contains placeholder text like "your_api_key_here")
- Configuration files that reference `process.env.*`

## 🚨 If GitHub Shows a Secret Alert

If you're seeing a GitHub secret scanning alert, it could be:

### 1. **False Positive from .env.example**
   - The FISH_VOICE_ID (`062e70ee3ef24b0280b605cfcdf03be7`) in `.env.example` is NOT a secret
   - It's just a voice profile ID, not an API key
   - **Safe to ignore** this warning

### 2. **Old Commit History**
   - Check if an API key was committed before we added `.gitignore`
   - To remove from history:
     ```bash
     # Remove file from all commits (BE CAREFUL!)
     git filter-branch --force --index-filter \
       "git rm --cached --ignore-unmatch .env" \
       --prune-empty --tag-name-filter cat -- --all

     # Force push (only if necessary)
     git push origin --force --all
     ```

### 3. **Revoke and Rotate Keys**
   If an actual API key was exposed:

   **For Replicate API:**
   1. Go to https://replicate.com/account/api-tokens
   2. Delete the exposed token
   3. Generate a new token
   4. Update your local `.env` file

   **For Anthropic API (if using):**
   1. Go to https://console.anthropic.com/settings/keys
   2. Delete the exposed key
   3. Generate a new key
   4. Update your backend `.env` file

## 🛡️ Best Practices

1. **Never commit `.env` files**
   - Always use `.env.example` with placeholder values

2. **Use environment variables**
   - Access via `process.env.VARIABLE_NAME` (Node.js)
   - Access via `os.getenv("VARIABLE_NAME")` (Python)

3. **Rotate keys regularly**
   - Change API keys every 90 days
   - Immediately rotate if exposed

4. **Use different keys for different environments**
   - Development: Use test/sandbox keys
   - Production: Use production keys
   - Never mix them!

5. **Add comments to .env.example**
   ```bash
   # Get your key from: https://example.com/api-keys
   API_KEY=your_api_key_here
   ```

## 📝 Your Current .env.example

Your `.env.example` is correctly configured with placeholders:

```bash
# Fish Audio TTS Configuration
FISH_API_KEY=your_fish_audio_api_key_here
FISH_VOICE_ID=062e70ee3ef24b0280b605cfcdf03be7  # ⚠️ This is a voice ID, NOT a secret
FISH_TTS_ENDPOINT=https://api.fish.audio/v1/tts

# Replicate API for AI Music Generation
REPLICATE_API_TOKEN=your_replicate_api_token_here

# Server Configuration
PORT=3001
NODE_ENV=developmen
[truncated — 976 more characters]
```

### AI_MUSIC_GENERATION_FEATURE.md

```markdown
# AI Music Generation Feature - Implementation Summary

## Overview
I've successfully implemented an AI-powered music generation feature for the EON (Earth Saga) application. This feature generates ambient music based on real-time environmental data from 222+ global regions.

## 🎵 How It Works

The system analyzes **15+ environmental parameters** and intelligently maps them to musical characteristics:

### Environmental Data → Music Mapping

1. **Temperature** → Tempo/Warmth
   - Cold (-10°C or below): Very slow, stark mood
   - Cool (10-15°C): Slow tempo
   - Comfortable (15-25°C): Medium tempo, peaceful
   - Hot (30-35°C): Fast tempo
   - Very hot (35°C+): Energetic tempo, intense mood

2. **Wind Speed** → Energy/Intensity
   - Calm (< 5 m/s): Still, gentle intensity
   - Breezy (5-15 m/s): Moderate intensity
   - Windy (15-25 m/s): Strong intensity, dynamic
   - Very windy (25+ m/s): Intense, dramatic mood

3. **Humidity & Cloud Cover** → Atmospheric Depth
   - High humidity + clouds: Dense and misty
   - Rain: Rain-soaked atmosphere
   - Clear skies: Crisp and clear
   - Overcast: Somber atmosphere

4. **Time of Day** → Mood
   - Dawn (5-7am): Hopeful
   - Morning (7-12pm): Energetic
   - Afternoon (12-5pm): Bright
   - Evening (5-8pm): Calm
   - Night (8pm-5am): Mysterious

5. **Biome/Location** → Genre
   - **Rainforest**: Tropical ambient with lush, organic textures
   - **Desert**: Minimal ambient with sparse, expansive soundscapes
   - **Mountain**: Epic ambient with majestic, vast atmospheres
   - **Ocean/Coastal**: Aquatic ambient with flowing, serene waves
   - **Polar**: Glacial ambient with frozen, crystalline sounds
   - **Urban**: Electronic ambient with rhythmic, pulsing elements
   - **Volcanic**: Dark ambient with powerful, primal energy
   - **Wetland**: Organic ambient with natural, breathing textures

6. **Air Quality Index (AQI)** → Harmony
   - Clean air (< 100): Consonant harmonies
   - Moderate (100-150): Textured complexity
   - Unhealthy (150+): Tense, dissonant mood

## 📁 Files Created/Modified

### New Files:
1. **`/frontend/src/services/musicGenerationService.ts`** (326 lines)
   - Core music parameter mapping logic
   - Analyzes environmental data and generates:
     - Musical mood, genre, tempo, intensity
     - Atmospheric descriptors
     - Descriptive tags
     - Detailed AI prompts

2. **`/frontend/src/lib/musicClient.ts`** (121 lines)
   - API client for music generation
   - Handles music playback controls
   - Manages audio state and error handling

3. **`/.env.example`**
   - Environment variable template
   - Documents required API keys

### Modified Files:
1. **`/server/index.js`**
   - Added `/api/generate-music` endpoint
   - Integrates with Replicate API for MusicGen
   - Handles async music generation with polling
   - Includes fallback for development mode

2. **`/frontend/src/components/NarrativePanel.tsx`**
   - Added music generation button
   - Integrated music controls (Generate/Play/Stop)
  
[truncated — 5994 more characters]
```

### package.json

```
{
  "name": "eon-earth-saga",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "cd frontend && npm run dev",
    "build": "cd frontend && npm run build",
    "preview": "cd frontend && npm run preview",
    "server": "node server/index.js",
    "vercel-build": "cd frontend && npm install && npm run build"
  },
  "dependencies": {
    "axios": "^1.7.2",
    "cors": "^2.8.5",
    "dotenv": "^17.2.3",
    "express": "^5.1.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-globe.gl": "^2.36.0",
    "three": "^0.180.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.66",
    "@types/react-dom": "^18.2.22",
    "@vitejs/plugin-react": "^4.7.0",
    "autoprefixer": "^10.4.21",
    "postcss": "^8.5.6",
    "tailwindcss": "^3.4.18",
    "typescript": "^5.5.4",
    "vite": "^5.4.21"
  }
}

```

### server/package.json

```
{
  "name": "eon-tts-server",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "dotenv": "^16.3.1"
  }
}

```

### frontend/package.json

```
{
  "name": "eon-earth-saga-frontend",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "vercel-build": "npm run build"
  },
  "dependencies": {
    "@anthropic-ai/sdk": "^0.67.0",
    "axios": "^1.7.2",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-globe.gl": "^2.36.0",
    "three": "^0.180.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.66",
    "@types/react-dom": "^18.2.22",
    "@vitejs/plugin-react": "^4.7.0",
    "autoprefixer": "^10.4.21",
    "postcss": "^8.5.6",
    "tailwindcss": "^3.4.18",
    "typescript": "^5.5.4",
    "vite": "^5.4.21"
  }
}

```

### server/index.js

```javascript
import dotenv from 'dotenv';
import express from 'express';
import cors from 'cors';

// Load environment variables
dotenv.config();

const app = express();
app.use(cors());
app.use(express.json({ limit: '2mb' }));

app.post('/api/tts', async (req, res) => {
  try {
    const { text, voiceId, speed = 1.0, volume = 0, format = 'mp3' } = req.body || {};
    if (!text) return res.status(400).json({ error: 'Missing text' });
    if (!process.env.FISH_API_KEY) return res.status(500).json({ error: 'Missing FISH_API_KEY' });

    const endpoint = process.env.FISH_TTS_ENDPOINT || 'https://api.fish.audio/v1/tts';
    const payload = {
      text,
      voice_id: voiceId || process.env.FISH_VOICE_ID || undefined,
      speed,
      volume,
      format
    };

    const r = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.FISH_API_KEY}`
      },
      body: JSON.stringify(payload)
    });

    if (!r.ok) {
      const errText = await r.text().catch(() => '');
      return res.status(r.status).json({ error: 'Fish TTS request failed', detail: errText });
    }

    const ct = r.headers.get('content-type') || '';
    if (ct.includes('application/json')) {
      const data = await r.json();
      const maybeUrl = data?.data?.url || data?.url || data?.download_link;
      const maybeB64 = data?.data?.audio_base64 || data?.audio_base64;
      if (maybeUrl) return res.json({ url: maybeUrl });
      if (maybeB64) return res.json({ base64: maybeB64, contentType: `audio/${format}` });
      return res.status(500).json({ error: 'Unexpected Fish TTS JSON response', data });
    } else {
      const buf = Buffer.from(await r.arrayBuffer());
      const b64 = buf.toString('base64');
      return res.json({ base64: b64, contentType: ct || `audio/${format}` });
    }
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'TTS proxy failed', detail: String(err) });
  }
});

// Music generation endpoint using Replicate API
app.post('/api/generate-music', async (req, res) => {
  try {
    const { prompt, duration = 8 } = req.body || {};
    if (!prompt) return res.status(400).json({ error: 'Missing prompt' });

    // Check for Replicate API key
    if (!process.env.REPLICATE_API_TOKEN) {
      // Fallback: Return a sample/mock response for development
      console.warn('REPLICATE_API_TOKEN not set, returning mock response');
      return res.json({
        audioUrl: null,
        mock: true,
        message: 'Music generation requires REPLICATE_API_TOKEN. Set it in your .env file.',
        prompt: prompt
      });
    }

    // Call Replicate API for MusicGen
    const response = await fetch('https://api.replicate.com/v1/predictions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.REPLICATE_API_TOKEN}`
      },
      body: JSON.stringify({
        version: 'stereo-melody-large', // MusicGen model version
        input: {
          prompt: prompt,
          duration: Math.min(duration, 30), // Cap at 30 seconds for performance
          model_version: 'stereo-melody-large',
          output_format: 'mp3',
          normalization_strategy: 'peak'
        }
      })
    });

    if (!response.ok) {
      const errorText = await response.text().catch(() => '');
      console.error('Replicate API error:', errorText);
      return res.status(response.status).json({
        error: 'Music generation failed',
        detail: errorText
      });
    }

    const prediction = await response.json();

    // Replicate uses async processing, poll for result
    let result = prediction;
    let attempts = 0;
    const maxAttempts = 60; // 60 attempts with 2s interval = 2 minutes max

    while (result.status !== 'succeeded' && result.status !== 'failed' && attempts < maxAttempts) {
      await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds

      const statusResponse = await fetch(
        `https://api.replicate.com/v1/predictions/${result.id}`,
        {
          headers: {
            'Authorization': `Bearer ${process.env.REPLICATE_API_TOKEN}`
          }
        }
      );

      if (!statusResponse.ok) break;
      result = await statusResponse.json();
      attempts++;
    }

    if (result.status === 'succeeded' && result.output) {
      return res.json({
        audioUrl: result.output,
        prompt: prompt,
        duration: duration
      });
    } else if (result.status === 'failed') {
      return res.status(500).json({
        error: 'Music generation failed',
        detail: result.error
      });
    } else {
      return res.status(408).json({
        error: 'Music generation timeout',
        detail: 'Generation took too long, please try again'
      });
    }

  } catch (err) {
    console.error('Music generation error:', err);
    res.status(500).json({
      error: 'Music generation failed',
      detail: String(err)
    });
  }
});

// Export for Vercel
export default app;

// For local development
if (process.env.NODE_ENV !== 'production') {
  const PORT = process.env.PORT || 3001;
  app.listen(PORT, () => console.log(`Server listening on http://localhost:${PORT}`));
}

```

### frontend/src/main.tsx

```typescript
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(<React.StrictMode><App/></React.StrictMode>)

```

### frontend/postcss.config.js

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

```

### frontend/tailwind.config.js

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

```

### backend/config.py

```python
import os
from dotenv import load_dotenv

load_dotenv()

class Config:
    # API Keys
    ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
    
    # API Endpoints
    ANTHROPIC_BASE_URL = "https://api.anthropic.com"


```

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