# Image Atoms

This document describes the implementation of image generation functionality in Suno Spaces using the fal.ai API.

## Overview

Image atoms allow users to generate AI images through the Orphy assistant. When users ask Orphy to create images, the system:
1. Uses OpenAI to parse the user's request into a detailed image prompt
2. Generates 2 image variations using fal.ai's Flux Schnell model
3. Uploads the images to Convex file storage
4. Displays the images side-by-side in the chat interface

## Architecture

### Backend Components

#### 1. Fal.ai Client (`lib/falClient.ts`)

The `FalClient` class provides a clean interface to the fal.ai API:

```typescript
const client = createFalClient();
const result = await client.generateImages(prompt, { numImages: 2 });
```

**Key features:**
- Uses fal.ai's `flux/schnell` model (optimized for 4 inference steps)
- Generates 2 images by default
- Downloads generated images for storage
- Includes safety checker by default

**Configuration:**
- Requires `FAL_API_KEY` environment variable
- Base URL: `https://fal.run`
- Model: `fal-ai/flux/schnell`

#### 2. Image Generation Action (`convex/atoms.ts`)

The `generateImage` internal action orchestrates the image generation workflow:

```typescript
export const generateImage = internalAction({
  args: {
    prompt: v.string(),
    spaceId: v.id("spaces"),
    userId: v.id("users"),
  },
  handler: async (ctx, args): Promise<Array<any>> => {
    // 1. Generate images via fal.ai
    // 2. Download images
    // 3. Upload to Convex storage
    // 4. Create atom records
  }
});
```

**Workflow:**
1. Calls fal.ai API with the prompt
2. Downloads each generated image as an ArrayBuffer
3. Uploads images to Convex file storage using `ctx.storage.store()`
4. Creates an `image` atom for each generated image with metadata:
   - `prompt`: The text prompt used for generation
   - `width` / `height`: Image dimensions
   - `storageId`: Convex storage identifier
   - `originalUrl`: Original fal.ai URL (for reference)

#### 3. Assistant Integration (`convex/assistant.ts`)

The Orphy assistant now supports two tools:
- `generate_song`: Creates music (existing)
- `generate_image`: Creates images (new)

**Tool Definition:**
```typescript
const GENERATE_IMAGE_TOOL: OpenAI.Chat.Completions.ChatCompletionTool = {
  type: "function",
  function: {
    name: "generate_image",
    description: "Generate images using AI. Creates 2 variations of the image based on the prompt.",
    parameters: {
      type: "object",
      properties: {
        prompt: {
          type: "string",
          description: "Detailed description of the image to generate..."
        }
      },
      required: ["prompt"]
    }
  }
};
```

**Request Flow:**
1. User mentions `@orphy` with an image request
2. OpenAI classifies the intent and extracts parameters
3. Assistant creates a "processing" message
4. Calls `internal.atoms.generateImage` action
5. Updates message with atom references when complete

### Frontend Components

#### 1. ImageAtomCard Component (`components/ImageAtomCard.tsx`)

A card component that displays a generated image with metadata and interaction controls.

**Features:**
- Full-width image display with aspect ratio preservation
- Like button with count
- Download button (saves image to local filesystem)
- Prompt text display (line-clamped to 2 lines)
- Image dimensions display
- Loading states with progress bar
- Error states with visual feedback

**States:**
- `pending` / `processing`: Shows spinner and progress bar
- `completed`: Shows image with full interactions
- `failed`: Shows error icon and message

#### 2. Page Integration (`app/space/[id]/page.tsx`)

Images are displayed in messages using a grid layout:

```tsx
{atoms.some((atom) => atom?.type === "image") ? (
  <div className="grid grid-cols-2 gap-3">
    {atoms.map((atom) => atom && atom.type === "image" && (
      <ImageAtomCard key={atom._id} atom={atom} currentUserId={user.user?._id} />
    ))}
  </div>
) : (
  // ... song rendering
)}
```

**Layout:**
- Images are displayed in a 2-column grid (side-by-side)
- Grid uses `gap-3` for spacing between cards
- Responsive design maintains aspect ratios

## Schema

The `atoms` table already includes support for image atoms through the type union:

```typescript
atoms: defineTable({
  type: v.union(
    v.literal("song"),
    v.literal("video"),
    v.literal("image"),  // ← Already defined
    v.literal("lyrics"),
    v.literal("webview")
  ),
  // ... other fields
})
```

**Image Atom Metadata Structure:**
```typescript
{
  prompt: string;           // Generation prompt
  width: number;            // Image width in pixels
  height: number;           // Image height in pixels
  storageId: string;        // Convex storage ID
  originalUrl: string;      // Original fal.ai URL (backup)
}
```

## Usage

### User Examples

**Basic image generation:**
```
@orphy generate an album cover with neon lights
```

**Detailed requests:**
```
@orphy create an image of a sunset over mountains with vibrant colors
```

**Style-specific:**
```
@orphy generate a cyberpunk city scene at night
```

### Assistant Behavior

When processing image requests, Orphy:
1. Extracts or enhances the prompt for optimal results
2. Creates a placeholder message: "🎨 Generating 2 images..."
3. Calls fal.ai API to generate images
4. Uploads images to Convex storage
5. Updates the message with image atom references
6. Images appear side-by-side in the chat

## API Keys

**Required Environment Variable:**
```
FAL_API_KEY=your_fal_api_key_here
```

Get your API key from: https://fal.ai/dashboard

## Image Storage

Generated images are stored using Convex's built-in file storage:
- Images are uploaded as Blobs with appropriate content types
- Storage IDs are stored in atom metadata
- Images are served via `ctx.storage.getUrl()` (accessed through `api.atoms.getImageUrl` query)
- URLs are temporary and expire after a period (Convex handles this automatically)
- No external CDN dependencies

## Performance Considerations

- **Generation time:** ~4-8 seconds for 2 images (depends on fal.ai API)
- **Image size:** Typically 1-2MB per image
- **Concurrent requests:** fal.ai handles rate limiting automatically
- **Storage:** Convex storage has generous limits for image files

## Future Enhancements

Possible improvements:
- Support for different image sizes/aspect ratios
- Custom style presets (photorealistic, artistic, cartoon, etc.)
- Image editing capabilities (upscaling, variations)
- Batch generation (more than 2 images)
- Image-to-image generation
- Integration with other AI image models
- Image gallery view for a space
- Image search and filtering

## Troubleshooting

**Images not generating:**
- Verify `FAL_API_KEY` is set in environment variables
- Check Convex logs for API errors
- Ensure fal.ai account has sufficient credits

**Images not displaying:**
- Check browser console for storage endpoint errors
- Verify `storageId` is correctly saved in atom metadata
- Check Convex dashboard for storage file status

**Slow generation:**
- fal.ai API response time varies by load
- Consider implementing request queuing for high volume
- Check network connectivity to fal.ai services
