# Installation Guide for Next.js

Complete guide for installing `@karaplay/kar-player` in Next.js projects (including Firebase Studio).

## Quick Install

### Method 1: Standard Installation (Recommended)

```bash
# Clear npm cache
npm cache clean --force

# Install package
npm install @karaplay/kar-player@1.0.0

# Install peer dependency
npm install buffer@^6.0.3
```

### Method 2: Force Installation (if Method 1 fails)

```bash
# Install with legacy peer deps
npm install @karaplay/kar-player@1.0.0 --legacy-peer-deps

# Or with force flag
npm install @karaplay/kar-player@1.0.0 --force
```

### Method 3: Exact Version (for Firebase Studio)

```bash
# Install exact versions
npm install @karaplay/kar-player@1.0.0 \
  @karaplay/file-coder@1.3.4 \
  buffer@6.0.3 \
  iconv-lite@0.6.3 \
  grapheme-splitter@1.0.4 \
  midi-file@1.2.4 \
  pako@2.1.0 \
  spessasynth_lib@0.1.6
```

---

## Troubleshooting

### Error: "Module not found: Can't resolve '@karaplay/kar-player'"

**Solution 1: Clear Next.js Cache**

```bash
# Remove .next folder
rm -rf .next

# Clear node_modules
rm -rf node_modules package-lock.json

# Reinstall
npm install
npm install @karaplay/kar-player@1.0.0
```

**Solution 2: Check Next.js Config**

Create or update `next.config.js`:

```javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config) => {
    config.resolve.fallback = {
      ...config.resolve.fallback,
      fs: false,
      net: false,
      tls: false,
    };
    return config;
  },
};

module.exports = nextConfig;
```

**Solution 3: Firebase Studio Specific**

If using Firebase Studio/Hosting:

1. Install in correct directory:
```bash
cd functions  # If using Cloud Functions
npm install @karaplay/kar-player@1.0.0

# Or for Next.js app
cd app  # Your Next.js app directory
npm install @karaplay/kar-player@1.0.0
```

2. Update `package.json`:
```json
{
  "dependencies": {
    "@karaplay/kar-player": "^1.0.0",
    "buffer": "^6.0.3",
    "next": "^15.5.9",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
```

### Error: "@types/iconv-lite version not found"

**Solution:**

This is fixed in v1.0.0. If you still see this:

```bash
# Remove old versions
npm uninstall @karaplay/kar-player

# Clear cache
npm cache clean --force

# Install fresh
npm install @karaplay/kar-player@1.0.0
```

### Error: "Cannot find module 'buffer'"

**Solution:**

```bash
npm install buffer@^6.0.3
```

Then add to `next.config.js`:

```javascript
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        buffer: require.resolve('buffer/'),
      };
    }
    return config;
  },
};
```

---

## Verification

After installation, verify it works:

```typescript
// test-install.ts
import { MIDIPlayer, KarFile } from '@karaplay/kar-player';

console.log('✅ Import successful!');
console.log('MIDIPlayer:', typeof MIDIPlayer);
console.log('KarFile:', typeof KarFile);
```

Run:
```bash
npx ts-node test-install.ts
```

Expected output:
```
✅ Import successful!
MIDIPlayer: function
KarFile: function
```

---

## Next.js Usage

### App Router (Client Component)

```tsx
'use client';

import { useState } from 'react';
import { MIDIPlayer } from '@karaplay/kar-player';

export default function Player() {
  const [player] = useState(() => new MIDIPlayer());

  const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      await player.openFileWithEmkSupport(file);
      await player.play();
    }
  };

  return <input type="file" accept=".kar,.emk" onChange={handleFile} />;
}
```

### App Router (Server Component)

```typescript
// app/api/convert/route.ts
import { convertEmkBufferToKar } from '@karaplay/kar-player';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const formData = await request.formData();
  const file = formData.get('file') as File;
  
  const buffer = Buffer.from(await file.arrayBuffer());
  const result = await convertEmkBufferToKar(buffer, file.name);
  
  return NextResponse.json(result.metadata);
}
```

---

## Firebase Studio Specific

### Project Structure

```
firebase-project/
├── functions/
│   ├── package.json  # ← Install here if using Cloud Functions
│   └── src/
└── hosting/
    ├── package.json  # ← Install here if using Next.js
    └── pages/
```

### Cloud Functions

```typescript
// functions/src/index.ts
import { convertEmkToKarServer } from '@karaplay/kar-player';
import * as functions from 'firebase-functions';

export const convertEmk = functions.https.onRequest(async (req, res) => {
  const result = await convertEmkToKarServer('/tmp/song.emk');
  res.json(result.metadata);
});
```

### Next.js + Firebase

```json
// package.json
{
  "dependencies": {
    "@karaplay/kar-player": "^1.0.0",
    "buffer": "^6.0.3",
    "firebase": "^10.0.0",
    "firebase-admin": "^12.0.0",
    "next": "^15.5.9"
  }
}
```

---

## Common Issues

### Issue: Import fails in server component

**Solution:** Use dynamic import

```typescript
// Server Component
import dynamic from 'next/dynamic';

const PlayerComponent = dynamic(
  () => import('./PlayerClient'),
  { ssr: false }
);

export default function Page() {
  return <PlayerComponent />;
}
```

### Issue: Build fails with "Can't resolve 'fs'"

**Solution:** Update `next.config.js`

```javascript
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        fs: false,
        net: false,
        tls: false,
        child_process: false,
      };
    }
    return config;
  },
};
```

### Issue: TypeScript errors

**Solution:** Add types

```bash
npm install --save-dev @types/node
```

```json
// tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "types": ["node"]
  }
}
```

---

## Environment Variables

Create `.env.local`:

```bash
# SpessaSynth Config
NEXT_PUBLIC_SPESSASYNTH_LIB=/spessasynth_lib.js
NEXT_PUBLIC_SPESSASYNTH_CORE=/spessasynth_core.js
NEXT_PUBLIC_SOUNDFONT=/soundfont.sf2

# Lyric Config
NEXT_PUBLIC_KAR_PLAYER_THEME=extreme-karaoke
NEXT_PUBLIC_KAR_PLAYER_GOOGLE_FONT=Kanit
NEXT_PUBLIC_KAR_PLAYER_WORD_SPACING=-0.05em
```

---

## Production Deployment

### Build Check

```bash
# Test build
npm run build

# Check for errors
npm run start
```

### Firebase Deploy

```bash
# Build Next.js
npm run build

# Deploy to Firebase
firebase deploy --only hosting
```

### Vercel Deploy

```bash
# Deploy to Vercel
vercel deploy --prod
```

---

## Support

If you still have issues:

1. **Check version:**
   ```bash
   npm list @karaplay/kar-player
   ```
   Expected: `@karaplay/kar-player@1.0.0`

2. **Check dependencies:**
   ```bash
   npm list @karaplay/file-coder
   npm list iconv-lite
   ```

3. **Try clean install:**
   ```bash
   rm -rf node_modules package-lock.json .next
   npm install
   ```

4. **Check Node version:**
   ```bash
   node --version  # Should be >= 18.x
   ```

---

## Quick Reference

| Command | Purpose |
|---------|---------|
| `npm install @karaplay/kar-player@1.0.0` | Install package |
| `npm cache clean --force` | Clear npm cache |
| `rm -rf .next` | Clear Next.js cache |
| `npm run build` | Test build |
| `npm list @karaplay/kar-player` | Check version |

---

## Minimal Working Example

```json
// package.json
{
  "name": "my-karaoke-app",
  "dependencies": {
    "@karaplay/kar-player": "^1.0.0",
    "buffer": "^6.0.3",
    "next": "^15.5.9",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
```

```javascript
// next.config.js
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        buffer: require.resolve('buffer/'),
        fs: false,
      };
    }
    return config;
  },
};

module.exports = nextConfig;
```

```tsx
// app/page.tsx
'use client';

import { MIDIPlayer } from '@karaplay/kar-player';

export default function Home() {
  const player = new MIDIPlayer();
  return <div>Ready!</div>;
}
```

**Done!** 🎉
