# Slidev API Documentation

Complete API reference for the Slidev presentation generation and control system.

**Production Base URL:** `https://slide-system-production-5813.up.railway.app/`

**Framework:** Motia.dev on Railway

**Implementation:** `apps/slide-system/steps/`

---

## Table of Contents

1. [Generate Deck](#generate-deck)
2. [Control Deck](#control-deck)
3. [Create Demo Session](#create-demo-session)
4. [Error Handling](#error-handling)
5. [Rate Limits](#rate-limits)
6. [Authentication](#authentication)

---

## Generate Deck

Generate a Slidev presentation from a template and publish it to GitHub Pages.

### Endpoint

```
POST /api/slidev/generate
```

### Request Headers

```
Content-Type: application/json
```

### Request Body

```json
{
  "sessionId": "uuid-string",
  "templateId": "starter",
  "data": {
    "company": "Acme Corporation",
    "tagline": "Building the future",
    "description": "We create innovative solutions",
    "industry": "SaaS"
  }
}
```

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `sessionId` | string | Yes | UUID of conversation session from Supabase `conversation_sessions` table |
| `templateId` | string | Yes | Template identifier (currently only `"starter"` supported) |
| `data` | object | Yes | Key-value pairs for placeholder replacement in template |

**Data Field Support:**

The `data` object supports any key-value pairs. Common fields:
- `company` - Company name (replaces `{{company}}` in template)
- `tagline` - Company tagline
- `description` - Company description
- `industry` - Industry sector

### Response

**Success (200 OK):**

```json
{
  "deckId": "abc1-def2-ghi3",
  "deckUrl": "https://buzztrail.github.io/buzztrail-presentations/abc1-def2-ghi3/",
  "message": "Deck generated successfully"
}
```

**Response Fields:**

| Field | Type | Description |
|-------|------|-------------|
| `deckId` | string | Unique 12-character deck identifier (format: `xxxx-xxxx-xxxx`) |
| `deckUrl` | string | GitHub Pages URL where deck is accessible |
| `message` | string | Success message |

### Error Responses

**400 Bad Request - Missing Fields:**

```json
{
  "error": "Validation failed",
  "details": "Missing required fields: sessionId, templateId, and data"
}
```

**404 Not Found - Invalid Session:**

```json
{
  "error": "Session not found",
  "details": "No session exists with ID: invalid-uuid"
}
```

**500 Internal Server Error:**

```json
{
  "error": "Failed to generate deck",
  "details": "Specific error message"
}
```

### Example Usage

**cURL:**

```bash
curl -X POST https://slide-system-production-5813.up.railway.app/api/slidev/generate \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "550e8400-e29b-41d4-a716-446655440000",
    "templateId": "starter",
    "data": {
      "company": "Acme Corp",
      "tagline": "Innovation at scale",
      "description": "Leading provider of SaaS solutions",
      "industry": "Technology"
    }
  }'
```

**JavaScript (fetch):**

```javascript
const response = await fetch('https://slide-system-production-5813.up.railway.app/api/slidev/generate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    sessionId: '550e8400-e29b-41d4-a716-446655440000',
    templateId: 'starter',
    data: {
      company: 'Acme Corp',
      tagline: 'Innovation at scale',
      description: 'Leading provider of SaaS solutions',
      industry: 'Technology'
    }
  })
});

const result = await response.json();
console.log('Deck URL:', result.deckUrl);
```

**Python (requests):**

```python
import requests

response = requests.post(
    'https://slide-system-production-5813.up.railway.app/api/slidev/generate',
    json={
        'sessionId': '550e8400-e29b-41d4-a716-446655440000',
        'templateId': 'starter',
        'data': {
            'company': 'Acme Corp',
            'tagline': 'Innovation at scale',
            'description': 'Leading provider of SaaS solutions',
            'industry': 'Technology'
        }
    }
)

result = response.json()
print(f"Deck URL: {result['deckUrl']}")
```

### Implementation Details

**File:** `apps/slide-system/steps/slidev-generate.step.ts`

**Process:**
1. Validates request payload
2. Verifies session exists in Supabase `conversation_sessions` table
3. Generates unique 12-character deck ID
4. Replaces placeholders in template with provided data
5. Generates HTML presentation with Supabase Realtime integration
6. Stores deck metadata in Supabase `slidev_decks` table
7. Updates session with deck URL
8. Returns deck ID and GitHub Pages URL

**Performance:**
- Target: < 30s (build time)
- Target: < 60s (GitHub Pages publish)
- Target: < 90s (total end-to-end)

---

## Control Deck

Send navigation commands to a Slidev presentation via Supabase Realtime.

### Endpoint

```
POST /api/slidev/control
```

### Request Headers

```
Content-Type: application/json
x-api-key: your-slidev-api-key
```

**Authentication:** Requires valid API key in `x-api-key` header.

### Request Body

**Next Slide:**

```json
{
  "deckId": "abc1-def2-ghi3",
  "command": "next"
}
```

**Previous Slide:**

```json
{
  "deckId": "abc1-def2-ghi3",
  "command": "prev"
}
```

**Go to Specific Slide:**

```json
{
  "deckId": "abc1-def2-ghi3",
  "command": "goto",
  "slideId": "2"
}
```

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `deckId` | string | Yes | Unique deck identifier from generation response |
| `command` | string | Yes | Navigation command: `"next"`, `"prev"`, or `"goto"` |
| `slideId` | string | Conditional | Required for `"goto"` command. Slide number (1-indexed) |

### Response

**Success (200 OK):**

```json
{
  "success": true,
  "command": "next",
  "message": "Command broadcast successfully"
}
```

### Error Responses

**401 Unauthorized - Missing/Invalid API Key:**

```json
{
  "error": "Invalid or missing API key"
}
```

**400 Bad Request - Missing Fields:**

```json
{
  "error": "Validation failed",
  "details": "Missing required fields: deckId and command"
}
```

**400 Bad Request - Invalid Command:**

```json
{
  "error": "Validation failed",
  "details": "Invalid command. Must be one of: next, prev, goto"
}
```

**400 Bad Request - Missing slideId for goto:**

```json
{
  "error": "Validation failed",
  "details": "slideId is required for goto command"
}
```

**404 Not Found - Invalid Deck:**

```json
{
  "error": "Deck not found",
  "details": "No deck exists with ID: invalid-deck-id"
}
```

**500 Internal Server Error:**

```json
{
  "error": "Failed to send command",
  "details": "Specific error message"
}
```

### Example Usage

**cURL:**
```bash
# Next slide
curl -X POST https://slide-system-production-5813.up.railway.app/api/slidev/control \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key-here" \
  -d '{
    "deckId": "abc1-def2-ghi3",
    "command": "next"
  }'

# Previous slide
curl -X POST https://slide-system-production-5813.up.railway.app/api/slidev/control \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key-here" \
  -d '{
    "deckId": "abc1-def2-ghi3",
    "command": "prev"
  }'

# Go to slide 3
curl -X POST https://slide-system-production-5813.up.railway.app/api/slidev/control \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key-here" \
  -d '{
    "deckId": "abc1-def2-ghi3",
    "command": "goto",
    "slideId": "3"
  }'
```

**JavaScript (fetch):**

```javascript
async function controlDeck(deckId, command, slideId = null) {
  const response = await fetch('https://slide-system-production-5813.up.railway.app/api/slidev/control', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': 'your-api-key-here'
    },
    body: JSON.stringify({
      deckId,
      command,
      ...(slideId && { slideId })
    })
  });

  return await response.json();
}

// Usage
await controlDeck('abc1-def2-ghi3', 'next');
await controlDeck('abc1-def2-ghi3', 'goto', '5');
```

**Python (requests):**

```python
import requests

def control_deck(deck_id, command, slide_id=None):
    payload = {
        'deckId': deck_id,
        'command': command
    }

    if slide_id:
        payload['slideId'] = slide_id

    response = requests.post(
        'https://slide-system-production-5813.up.railway.app/api/slidev/control',
        headers={
            'Content-Type': 'application/json',
            'x-api-key': 'your-api-key-here'
        },
        json=payload
    )

    return response.json()

# Usage
control_deck('abc1-def2-ghi3', 'next')
control_deck('abc1-def2-ghi3', 'goto', '5')
```

### Implementation Details

**File:** `apps/slide-system/steps/slidev-control.step.ts`

**Process:**
1. Validates API key from `x-api-key` header
2. Validates request payload and command type
3. Verifies deck exists in Supabase `slidev_decks` table
4. Inserts command into Supabase `slide_control_commands` table
5. Supabase Realtime automatically broadcasts to subscribed clients
6. Presentation receives command and executes navigation

**Performance:**
- Target: < 500ms latency
- Typical: ~200ms latency

**Realtime Flow:**
```
API → Supabase slide_control_commands table
     → Supabase Realtime broadcast
     → Presentation client receives via postgres_changes
     → Slide navigation executed
```

---

## Create Demo Session

Create a new demo session in Supabase for deck generation.

### Endpoint

```
POST /demo-sessions
```

### Request Body

```json
{
  "session_type": "live_demo",
  "environment": "prod"
}
```

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_type` | string | Yes | Type of session: `"live_demo"` or `"test"` |
| `environment` | string | Yes | Environment: `"prod"`, `"staging"`, or `"dev"` |

### Response

**Success (200 OK):**

```json
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "initiated",
  "created_at": "2025-10-09T18:00:00Z"
}
```

### Example Usage

**cURL:**

```bash
curl -X POST https://slide-system-production-5813.up.railway.app/demo-sessions \
  -H "Content-Type: application/json" \
  -d '{
    "session_type": "test",
    "environment": "prod"
  }'
```

---

## Error Handling

### Error Response Format

All error responses follow this format:

```json
{
  "error": "Error category",
  "details": "Specific error message"
}
```

### HTTP Status Codes

| Code | Meaning | When Used |
|------|---------|-----------|
| 200 | OK | Request successful |
| 400 | Bad Request | Invalid request payload or parameters |
| 401 | Unauthorized | Missing or invalid API key (control endpoint only) |
| 404 | Not Found | Session or deck not found |
| 500 | Internal Server Error | Server-side error occurred |

### Common Error Scenarios

**Missing Required Fields:**
- HTTP 400
- Occurs when required fields are omitted from request
- Check request payload matches documented format

**Invalid Session ID:**
- HTTP 404
- Session doesn't exist in Supabase
- Create session first via `/demo-sessions`

**Invalid Deck ID:**
- HTTP 404
- Deck doesn't exist or was never generated
- Verify deck ID from generation response

**Invalid API Key:**
- HTTP 401
- API key missing from `x-api-key` header or doesn't match
- Verify API key is configured in Railway environment

**Server Configuration Error:**
- HTTP 500
- Environment variables not configured
- Contact system administrator

---

## Rate Limits

**Current Implementation:** No rate limiting enforced at API level.

**Recommended Client-Side Limits:**
- Generation: Max 10 concurrent requests
- Control: Max 100 commands per minute per deck

**Future Considerations:**
- Implement rate limiting via Railway or API gateway
- Monitor for abuse patterns
- Add rate limit headers in responses

---

## Authentication

### Generate Endpoint

**Authentication:** None required

**Rationale:** Generation requires valid session ID which provides implicit authentication through Supabase session validation.

### Control Endpoint

**Authentication:** API Key via `x-api-key` header

**Configuration:** Set `SLIDEV_API_KEY` environment variable in Railway dashboard.

**Example:**
```
x-api-key: f0b1323a70bbaa1fcdf34bcabaa8ca2dc14b880225c41c8d337d9a60ceeee2de
```

**Security Best Practices:**
- Store API key securely (environment variables, secrets management)
- Never commit API key to version control
- Rotate API key periodically
- Use HTTPS for all requests (enforced by Railway)

---

## Database Schema

### slidev_decks

Stores generated deck metadata.

```sql
CREATE TABLE slidev_decks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  deck_id TEXT UNIQUE NOT NULL,
  session_id UUID REFERENCES conversation_sessions(id),
  template_id TEXT NOT NULL DEFAULT 'starter',
  generation_data JSONB,
  deck_url TEXT,
  html_content TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
```

### slide_control_commands

Stores control commands for Realtime broadcast.

```sql
CREATE TABLE slide_control_commands (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  deck_id TEXT NOT NULL,
  command TEXT NOT NULL,
  slide_id TEXT,
  timestamp TIMESTAMPTZ DEFAULT NOW()
);
```

---

## Testing

### Performance Testing

Run performance tests against production API:

```bash
# Install dependencies
npm install

# Set environment variables
export MOTIA_API_URL=https://slide-system-production-5813.up.railway.app
export SLIDEV_API_KEY=your-api-key-here

# Run tests
npm run test:performance
npm run test:concurrent
```

**Test Files:**
- `scripts/performance-test.ts` - Performance benchmarking
- `scripts/concurrent-test.ts` - Load testing
- `scripts/test-utils.ts` - Shared utilities

### Manual Testing

**Test Generation:**

```bash
# 1. Create session
curl -X POST https://slide-system-production-5813.up.railway.app/demo-sessions \
  -H "Content-Type: application/json" \
  -d '{"session_type":"test","environment":"prod"}' \
  | jq -r '.session_id'

# 2. Generate deck (use session_id from step 1)
curl -X POST https://slide-system-production-5813.up.railway.app/api/slidev/generate \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId":"SESSION_ID_HERE",
    "templateId":"starter",
    "data":{"company":"Test Corp"}
  }' \
  | jq

# 3. Open deck URL in browser
```

**Test Control:**

```bash
# Send next command (use deckId from generation)
curl -X POST https://slide-system-production-5813.up.railway.app/api/slidev/control \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"deckId":"DECK_ID_HERE","command":"next"}'
```

---

## Support

**Documentation:**
- Setup Guide: `.claude/docs/phase0-setup-guide.md`
- Debugging Guide: `.claude/docs/phase0-debugging-guide.md`
- Testing Guide: `docs/testing/`

**Production URL:** https://slide-system-production-5813.up.railway.app

**GitHub Pages:** https://buzztrail.github.io/buzztrail-presentations/

**Framework:** [Motia.dev Documentation](https://docs.motia.dev)

---

**Last Updated:** 2025-10-09
