### Start Convex Backend Development Server
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Initializes the Convex backend development environment. Deploys the Convex schema and functions while starting the real-time sync server with debugging logs. Requires Node.js dependencies to be installed and the project directory to be properly structured. Leave this terminal running throughout the development session.
```shell
cd /Users/jigyoung/Dropbox/Mac\ \(2\)/Desktop/RomanCircus_Apps/Chatkut
npx convex dev
```
--------------------------------
### Debug Convex Backend with Verbose Logging
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Starts the Convex development server with enhanced debug-level logging. Provides detailed output for troubleshooting schema deployment failures, function errors, and database connection issues. Use this when standard logging does not reveal sufficient information for problem resolution.
```shell
npx convex dev --debug
```
--------------------------------
### Start Next.js Frontend Development Server
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Launches the Next.js development server for the ChatKut frontend application. The server binds to all network interfaces on port 3000 and provides hot reloading for efficient development. Must be run in a separate terminal while the Convex backend is active for full application functionality.
```shell
cd /Users/jigyoung/Dropbox/Mac\ \(2\)/Desktop/RomanCircus_Apps/Chatkut
npm run dev
```
--------------------------------
### Setup Project Dependencies in Bash
Source: https://github.com/taikuun/chatkut/blob/master/CLAUDE.md
Installs dependencies, sets up Convex, and configures environment variables for the ChatKut project. Requires Node.js and npm; outputs a configured local environment. Limited to initial setup phase and requires provided environment variables.
```bash
# Install dependencies
npm install
# Set up Convex
npx convex dev
# Set up environment variables
cp .env.example .env.local
# Add: CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN, DEDALUS_API_KEY
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/taikuun/chatkut/blob/master/TESTING_GUIDE.md
Installs all necessary Node.js dependencies for the ChatKut project. This command should be run in the project's root directory.
```bash
npm install
```
--------------------------------
### Initialize Convex Backend
Source: https://github.com/taikuun/chatkut/blob/master/TESTING_GUIDE.md
Starts the Convex development server. This command initializes the Convex project, generates the schema, deploys functions, and provides the Convex URL needed for the frontend.
```bash
# First terminal - Start Convex dev server
npx convex dev
```
--------------------------------
### Start Next.js Development Server
Source: https://github.com/taikuun/chatkut/blob/master/TESTING_GUIDE.md
Launches the Next.js development server for the ChatKut application. After running this, the application should be accessible at http://localhost:3000.
```bash
# Second terminal - Start Next.js
npm run dev
```
--------------------------------
### Initialize Convex for Real-time Backend
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
Commands to install the Convex package and start the Convex development server. Convex will manage the backend logic, database, and real-time functionalities for ChatKut.
```bash
npm install convex
npx convex dev
```
--------------------------------
### Configure ChatKut Environment Variables
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Defines essential environment variables for ChatKut's core features. These include the Convex deployment URL for backend communication, Dedalus API key for AI chat functionality, and Cloudflare credentials for video upload processing. Save this content in a .env.local file at the project root directory before starting services.
```shell
NEXT_PUBLIC_CONVEX_URL=https://graceful-falcon-340.convex.cloud
DEDALUS_API_KEY=dsk_live_...
CLOUDFLARE_ACCOUNT_ID=...
CLOUDFLARE_STREAM_TOKEN=...
```
--------------------------------
### Run Next.js on Alternative Port 3001
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Starts the Next.js development server on port 3001 instead of the default port 3000. This resolves conflicts when port 3000 is occupied by another application. After startup, access the application at http://localhost:3001. All other functionality remains identical to the standard development server.
```shell
npm run dev -- -p 3001
```
--------------------------------
### Run Development Server in Bash
Source: https://github.com/taikuun/chatkut/blob/master/CLAUDE.md
Starts the development servers for Next.js and Convex to enable local development. Depends on npm and Convex CLI; no inputs required, outputs running local servers. Limited to development environment and requires prior setup completion.
```bash
# Run dev server (Next.js + Convex)
npm run dev
# Run Convex functions locally
npx convex dev
# Type check
npm run type-check
# Lint
npm run lint
```
--------------------------------
### Set Up Environment Variables
Source: https://github.com/taikuun/chatkut/blob/master/TESTING_GUIDE.md
Configures essential environment variables for ChatKut. This involves creating a `.env.local` file in the project root with specific keys for Convex, Dedalus AI, Cloudflare, and Remotion.
```bash
# Convex (auto-generated when you run npx convex dev)
NEXT_PUBLIC_CONVEX_URL=https://your-convex-url.convex.cloud
CONVEX_DEPLOYMENT=dev:your-deployment-name
# Dedalus AI (for GPT-4o access)
DEDALUS_API_KEY=your-dedalus-api-key
# Cloudflare Stream (for video uploads)
CLOUDFLARE_ACCOUNT_ID=your-cloudflare-account-id
CLOUDFLARE_STREAM_TOKEN=your-stream-token
# Cloudflare R2 (for storage)
CLOUDFLARE_R2_ACCESS_KEY=your-r2-access-key
CLOUDFLARE_R2_SECRET_KEY=your-r2-secret-key
CLOUDFLARE_R2_BUCKET=chatkut-assets
CLOUDFLARE_R2_ENDPOINT=https://your-account.r2.cloudflarestorage.com
# Remotion Lambda (optional - for cloud rendering)
REMOTION_AWS_REGION=us-east-1
REMOTION_FUNCTION_NAME=remotion-render-lambda
REMOTION_S3_BUCKET=chatkut-renders
```
--------------------------------
### Verify Convex URL Configuration
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Extracts and displays the Convex URL from the .env.local configuration file. Use this command to verify that the environment variable matches the deployment URL shown when running 'npx convex dev'. Mismatched URLs will cause "Convex deployment not found" errors and prevent backend communication.
```shell
cat .env.local | grep CONVEX_URL
```
--------------------------------
### Deploy Project Components in Bash
Source: https://github.com/taikuun/chatkut/blob/master/CLAUDE.md
Deploys the backend, frontend, and rendering components to production. Depends on Convex CLI, Vercel, and Remotion CLI; no inputs, outputs deployment status. Limited to configured production accounts and requires environment setup.
```bash
# Deploy Convex backend
npx convex deploy
# Deploy Next.js frontend (Vercel)
vercel deploy --prod
# Deploy Remotion Lambda bundle
npx remotion lambda deploy
```
--------------------------------
### Tail Convex Logs in Real-Time
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Displays streaming logs from the Convex backend showing function calls, database queries, and error messages in real-time. Can be executed independently of the development server to monitor ongoing application activity. Press Ctrl+C to stop tailing the logs.
```shell
npx convex logs --tail
```
--------------------------------
### Install Dedalus SDK
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
This command installs the Dedalus SDK using npm, which is required for integrating Dedalus services into the project for AI model routing and other functionalities.
```bash
npm install dedalus-labs
```
--------------------------------
### AI Client Multi-Model Routing for Various Tasks (TypeScript)
Source: https://context7.com/taikuun/chatkut/llms.txt
Demonstrates an AI client that routes different tasks (code generation, chat, simple edits, JSON plan) to the most suitable model, tracking token usage and costs. Includes examples of invoking the client and calculating overall cost savings versus a single-model approach. Requires the dedalus AI client library.
```TypeScript
import { getAIClient, MODEL_ROUTING } from "@/lib/dedalus/client";
const aiClient = getAIClient();
// Example 1: Code generation (uses Claudenet - best quality)
const codeResponse = await aiClient.generateText({
task: "code-generation",
systemPrompt: "Generate a Remotion component that...",
prompt: "Create a video with fade in transition",
temperature: 0.3,
maxTokens: 4096
});
console.log(codeResponse);
// {
// text: "import { AbsoluteFill, interpolate... }",
// model: "claude-sonnet-4-5",
// provider: "anthropic",
// tokenUsage: { input: 245, output: 1823, total: 2068 },
// cost: 0.028 // $3/MTok input + $15/MTok output
// }
// Example 2: Chat response (uses GPT-4o - balanced)
const chatResponse = await aiClient.generateText({
task: "chat-response",
systemPrompt: "You are ChatKut assistant...",
prompt: "How do I add background music?",
temperature: 0.7
});
console.log(chatResponse);
// {
// text: "To add background music, upload an audio file...",
// model: "gpt-4o",
// provider: "openai",
// tokenUsage: { input: 187, output: 342, total: 529 },
// cost: 0.0038 // 67% cheaper than Claude
// }
// Example 3: Simple edituses Gemini Flash - fast/free)
const simpleEdit = await aiClient.generateText({
task: "simple-edit",
prompt: "Change video volume to 0.7",
temperature: 0.5
});
console.log(simpleEdit);
// {
// text: "{ 'properties': { 'volume': 0.7 } }",
// model: "gemini-2.0-flash",
// provider: "googlen// cost: 0 // Essentially free
// }
// Example 4: Structured JSON output for edit plans
const planResponse = await aiClient.generateJSON({
task: "plan-generation",
systemPrompt: "Generate Edit Plan JSON...",
prompt: "Make second clip louder"
});
console.log(planResponse.data);
// {
// operation: "update",
// selector { type: "byType", elementType: "video", index: 1 },
// changes: { properties: { volume: 1.5 } }
// }
// Cost savings vs single-model approach
import { calculateCostSavings } from "@/lib/dedalus/client";
const savings = calculateCostSavings({
"code-generation": 20,
"chat-response": 100,
"simple-edit": 50,
"plan-generation": 30,
"code-analysis": 10
});
console.log(savings);
// {
// multiModelCost: 0.89,
// singleModelCost: 1.32,
// savings: 0.43,
// savingsPercent: 32.58
// }
```
--------------------------------
### Start Cloud Video Render Job with Cost Estimation (TypeScript)
Source: https://context7.com/taikuun/chatkut/llms.txt
Uses Convex actions and queries to estimate render costs, initiate a render job, and monitor its progress in real time. Requires the Convex API and rendering functions defined in the backend. Outputs estimated cost, render job details, and live status updates until completion.
```TypeScript
import { api } from "./_generated/api";
import { useAction, useQuery } from "convex/react";
const startRender = useAction(api.rendering.startRender);
const getRenderStatus = useQuery(api.rendering.getRenderStatus);
// Estimate cost before rendering
const estimate = await api.rendering.estimateRenderCost({
compositionId: "c2x3y4z5..." as Id<"compositions">,
codec: "h264"
});
console.log(estimate);
// {
// estimatedCost: 0.15,
// estimatedTime: 45,
// durationInSeconds: 30,
// disclaimer: "Estimate based on standard quality H.264 encoding..."
// }
// Start render with user confirmation
const renderJob = await startRender({
compositionId: "c2x3y4z5..." as Id<"compositions">,
codec: "h264",
quality: 80
});
console.log("Render started:", renderJob);
// {
// renderJobId: "r4x5y6z7...",
// renderId: "render_1234567890_abc",
// status: "pending"
// }
// Monitor progress in real-time
const status = getRenderStatus({ renderJobId: renderJob.renderJobId });
console.log(status);
// {
// status: "rendering",
// progress: 0.45,
// estimatedCost: 0.15,
// actualCost: 0,
// createdAt: 1699564800000,
// updatedAt: 1699564830000
// }
// When complete:
// {
// status: "complete",
// progress: 1.0,
// actualCost: 0.142,
// renderTime: 42,
// outputUrl: "httpschatkut-media.r2.dev/renders/output.mp4"
// }
```
--------------------------------
### Create Mock Composition in Convex
Source: https://github.com/taikuun/chatkut/blob/master/TESTING_GUIDE.md
A JavaScript snippet to create a mock composition using the Convex dashboard. This is useful for testing features that require an existing composition, such as the Remotion Player preview or undo/redo functionality.
```javascript
// In Convex dashboard, run this mutation:
compositions.create({
projectId: "your-project-id",
name: "Test Composition",
width: 1920,
height: 1080,
fps: 30,
durationInFrames: 300
})
```
--------------------------------
### Execute Edit Plan with Various Selectors (TypeScript)
Source: https://context7.com/taikuun/chatkut/llms.txt
Demonstrates executing edit plans with different selector types (byId, byLabel, byType, byIndex) and operations (update, delete, add) on a CompositionIR object. It includes examples of applying changes like volume adjustments, animations, and element removal/addition. This function requires the 'composition-engine' and relevant type definitions.
```typescript
import { executeEditPlan } from "@/lib/composition-engine/executor";
import type { EditPlan, CompositionIR } from "@/types/composition-ir";
// Example composition with multiple elements
const composition: CompositionIR = {
id: "comp_123",
version: 1,
metadata: { width: 1920, height: 1080, fps: 30, durationInFrames: 300 },
elements: [
{ id: "el_1", type: "video", label: "Intro", from: 0, durationInFrames: 90, properties: { src: "...", volume: 1.0 } },
{ id: "el_2", type: "video", label: "Main", from: 90, durationInFrames: 120, properties: { src: "...", volume: 0.8 } },
{ id: "el_3", type: "audio", label: "Background Music", from: 0, durationInFrames: 300, properties: { src: "...", volume: 0.5 } }
],
patches: []
};
// Selector 1: By ID (most precise)
const planById: EditPlan = {
operation: "update",
selector: { type: "byId", id: "el_2" },
changes: { properties: { volume: 1.2 } }
};
let result = executeEditPlan(composition, planById);
console.log(result);
// {
// success: true,
// updatedIR: { ... },
// affectedElements: ["el_2"],
// receipt: "Updated \"Main\""
// }
// Selector 2: By label (user-friendly)
const planByLabel: EditPlan = {
operation: "update",
selector: { type: "byLabel", label: "Background Music" },
changes: { properties: { volume: 0.3 } }
};
result = executeEditPlan(result.updatedIR, planByLabel);
console.log(result.receipt); // "Updated \"Background Music\""
// Selector 3: By type with index (positional)
const planByType: EditPlan = {
operation: "update",
selector: { type: "byType", elementType: "video", index: 1 }, // Second video
changes: {
animation: {
property: "scale",
keyframes: [
{ frame: 90, value: 1.0 },
{ frame: 180, value: 1.15 }
],
easing: "ease-in-out"
}
}
};
result = executeEditPlan(result.updatedIR, planByType);
console.log(result.receipt); // "Updated \"Main\""
// Selector 4: By index (top-level only)
const planByIndex: EditPlan = {
operation: "delete",
selector: { type: "byIndex", index: 0 }, // First element
changes: {}
};
result = executeEditPlan(result.updatedIR, planByIndex);
console.log(result);
// {
// success: true,
// affectedElements: ["el_1"],
// receipt: "Deleted \"Intro\""
// }
// Add operation (no selector needed)
const addPlan: EditPlan = {
operation: "add",
selector: null,
changes: {
type: "text",
label: "Subtitle",
from: 60,
durationInFrames: 60,
properties: {
text: "Learn video editing with AI",
fontSize: 36,
color: "#ffffff"
}
}
};
result = executeEditPlan(result.updatedIR, addPlan);
console.log(result.receipt); // "Added text element \"Subtitle\""
// Ambiguous selector handling
const ambiguousPlan: EditPlan = {
operation: "update",
selector: { type: "byType", elementType: "video" }, // Matches multiple
changes: { properties: { volume: 0.5 } }
};
result = executeEditPlan(composition, ambiguousPlan);
if (result.needsDisambiguation) {
console.log("Multiple matches found:");
result.disambiguationOptions.forEach((opt, i) => {
console.log(` ${i + 1}. ${opt.label} (${opt.description})`);
});
// User selects option, then re-execute with resolvedElementId
}
```
--------------------------------
### Test Dedalus API Key Validity
Source: https://github.com/taikuun/chatkut/blob/master/START_TESTING.md
Verifies the Dedalus API key by making an authenticated request to the models endpoint. A successful response returns a JSON array of available AI models. If this test fails with an authentication error, the AI chat feature in ChatKut will not function. Replace the example key with your actual key before testing.
```shell
curl https://api.dedaluslabs.ai/v1/models \
-H "Authorization: Bearer dsk_live_32cec63b7e6b_806856c75152ad8326ca52585d4f5d2a"
```
--------------------------------
### Plan-Execute-Patch Flow for Deterministic Editing
Source: https://github.com/taikuun/chatkut/blob/master/chatkut-prd-v3.1-production-ready.md
Illustrates the workflow for deterministic editing using a Plan-Execute-Patch architecture. It outlines the steps from user input to LLM-generated plans, server-side validation, AST patching, and final code generation and persistence.
```text
User: "Make the second video clip zoom in slowly"
1. LLM (Dedalus) → Plan Generation
↓
Plan (IR):
{
operation: "addAnimation",
selector: { type: "byType", elementType: "video", index: 1 },
changes: {
property: "scale",
keyframes: [
{ frame: 0, value: 1.0 },
{ frame: 90, value: 1.2 }
],
easing: "ease-in"
}
}
2. Server → Validation & Resolution
↓
- Validate selector matches exactly one element
- If ambiguous, return disambiguator UI
- Resolve element ID from selector
3. AST Patcher → Code Modification
↓
- Parse existing Remotion code to AST
- Find element by ID in AST
- Insert/update interpolate() for scale
- Generate patched code
- Typecheck with TypeScript compiler
4. Persist & Update
↓
- Save patch to undo/redo stack
- Update IR in database
- Compile new Remotion code
- Update preview
5. Generate Receipt
↓
"✓ Updated video clip 'Background.mp4':
- Added zoom animation (1.0x → 1.2x over 3s)"
```
--------------------------------
### Create Composition
Source: https://context7.com/taikuun/chatkut/llms.txt
Initializes a new video composition with configurable dimensions, frame rate, and duration. Default values are applied if specific parameters are omitted.
```APIDOC
## POST /compositions/create
### Description
Initializes a new video composition with configurable dimensions, frame rate, and duration.
### Method
POST
### Endpoint
/compositions/create
### Parameters
#### Query Parameters
- **projectId** (Id<"projects">) - Required - The ID of the project this composition belongs to.
- **name** (string) - Optional - The name of the composition. Defaults to a generic name if not provided.
- **width** (number) - Optional - The width of the composition in pixels. Defaults to 1920.
- **height** (number) - Optional - The height of the composition in pixels. Defaults to 1080.
- **fps** (number) - Optional - The frame rate of the composition. Defaults to 30.
- **durationInFrames** (number) - Optional - The total duration of the composition in frames. Defaults to 300.
### Request Example
```json
{
"projectId": "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8",
"name": "Product Launch Video",
"width": 1920,
"height": 1080,
"fps": 30,
"durationInFrames": 900
}
```
### Request Example (Default Values)
```json
{
"projectId": "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8"
}
```
### Response
#### Success Response (200)
- **compositionId** (string) - The unique identifier for the newly created composition.
#### Response Example
```json
"c2x3y4z5w6a7b8c9d0e1f2g3h4i5j6k7"
```
```
--------------------------------
### Display Estimated Render Cost in React
Source: https://github.com/taikuun/chatkut/blob/master/chatkut-prd-v3.1-production-ready.md
This React component displays estimated cost and time for rendering a video. It fetches the estimate using a composition ID and updates the UI accordingly. The component includes a disclaimer and a button to start the render process.
```tsx
export function RenderDialog({ compositionId }) {
const [estimate, setEstimate] = useState(null);
useEffect(() => {
estimateRenderCost({ compositionId }).then(setEstimate);
}, [compositionId]);
return (
);
}
```
--------------------------------
### Initialize Dedalus Client and Runner (TypeScript)
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
This TypeScript code initializes the Dedalus client and creates a wrapper for the DedalusRunner. It sets up the foundation for interacting with Dedalus services, including implementing model routing logic for different AI tasks.
```typescript
// Placeholder for Dedalus client initialization and DedalusRunner wrapper
// This would involve importing necessary modules from 'dedalus-labs'
// and setting up the client with API keys or configuration.
// Example:
// import { AsyncDedalus } from 'dedalus-labs';
// const client = new AsyncDedalus({ apiKey: process.env.DEDALUS_API_KEY });
// const runner = new DedalusRunner(client);
```
--------------------------------
### Cloudflare Credentials for Media and Storage
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
Environment variables to store Cloudflare API credentials for Stream (video hosting) and R2 (object storage). These are essential for handling media assets within ChatKut.
```env
CLOUDFLARE_ACCOUNT_ID=xxx
CLOUDFLARE_STREAM_TOKEN=xxx
CLOUDFLARE_R2_ACCESS_KEY=xxx
CLOUDFLARE_R2_SECRET_KEY=xxx
```
--------------------------------
### Create Video Composition
Source: https://context7.com/taikuun/chatkut/llms.txt
Initializes a new video composition with configurable dimensions, frame rate, and duration. It uses Convex's `useMutation` hook. Dependencies include '@convex-dev/convex-react'. It takes project ID, name, width, height, FPS, and duration as input, returning the newly created composition ID. Default values are used if parameters are omitted.
```typescript
import { api } from "./_generated/api";
import { useMutation } from "convex/react";
const createComposition = useMutation(api.compositions.create);
// Create new 1080p composition at 30fps
const compositionId = await createComposition({
projectId: "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8" as Id<"projects">
name: "Product Launch Video",
width: 1920,
height: 1080,
fps: 30,
durationInFrames: 900 // 30 seconds at 30fps
});
console.log("Created composition:", compositionId);
// "c2x3y4z5w6a7b8c9d0e1f2g3h4i5j6k7"
// Default values if omitted:
const defaultComposition = await createComposition({
projectId: "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8" as Id<"projects">
});
// Uses: 1920x1080, 30fps, 300 frames (10 seconds)
```
--------------------------------
### List Project Assets and Compositions (TypeScript)
Source: https://context7.com/taikuun/chatkut/llms.txt
Fetches all assets and compositions for a given project ID using Convex React hooks. Supports filtering ready videos and retrieving single compositions. Dependencies include 'convex/react'. Outputs are arrays of asset and composition objects, or single composition objects.
```typescript
import { api } from "./_generated/api";
import { useQuery } from "convex/react";
// List all assets for a project
const assets = useQuery(api.media.listAssets, {
projectId: "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8" as Id<"projects">
});
console.log(assets);
// Filter ready videos
const readyVideos = assets?.filter(
a => a.type === "video" && a.status === "ready"
);
// List compositions for project
const compositions = useQuery(api.compositions.list, {
projectId: "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8" as Id<"projects">
});
console.log(compositions);
// Get single composition
const composition = useQuery(api.compositions.get, {
compositionId: compositions?.[0]._id
});
console.log(composition?.ir.elements.length); // Number of elements
console.log(composition?.version); // Edit version number
```
--------------------------------
### Execute Testing Commands in Bash
Source: https://github.com/taikuun/chatkut/blob/master/CLAUDE.md
Runs the test suite for the project, including all tests, specific files, or watch mode. Depends on npm and testing framework; inputs optional test file path. Outputs test results. Limited to local environment and requires test files to be present.
```bash
# Run all tests
npm test
# Run specific test file
npm test -- path/to/test.spec.ts
# Run tests in watch mode
npm test -- --watch
```
--------------------------------
### POST /api/ai/generateEditPlan
Source: https://context7.com/taikuun/chatkut/llms.txt
Creates structured edit operations from natural language requests with precise selector resolution for deterministic editing.
```APIDOC
## POST /api/ai/generateEditPlan
### Description
Creates structured edit operations from natural language requests with precise selector resolution for deterministic editing.
### Method
POST
### Endpoint
/api/ai/generateEditPlan
### Parameters
#### Request Body
- **projectId** (string) - Required - The ID of the project
- **compositionId** (string) - Required - The ID of the composition
- **userMessage** (string) - Required - The user's edit request in natural language
### Request Example
{
"projectId": "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8",
"compositionId": "c2x3y4z5...",
"userMessage": "Make the intro video 50% louder and add fade in"
}
### Response
#### Success Response (200)
- **plan** (object) - The generated edit plan with operation details
#### Response Example
{
"plan": {
"operation": "update",
"selector": {
"type": "byLabel",
"label": "intro"
},
"changes": {
"properties": {
"volume": 1.5
},
"animation": {
"property": "opacity",
"keyframes": [
{ "frame": 0, "value": 0 },
{ "frame": 30, "value": 1 }
],
"easing": "ease-in"
}
},
"reasoning": "Increase volume to 1.5x and add 1-second fade-in animation"
}
}
```
--------------------------------
### Remotion Render Cost Estimation in TypeScript
Source: https://github.com/taikuun/chatkut/blob/master/chatkut-prd-v3.1-production-ready.md
This TypeScript module provides actions for estimating and recording costs of Remotion Lambda renders using the official estimatePrice API, replacing hardcoded values. It stores estimates for user display and logs actual costs after completion for variance analysis and telemetry. Inputs include composition details, and outputs include cost/time estimates with a disclaimer about actual cost variations.
```typescript
// convex/rendering.ts
import { estimatePrice } from "@remotion/lambda/client";
export const estimateRenderCost = action({
handler: async (ctx, { compositionId, durationInFrames, region }) => {
const project = await ctx.runQuery(api.projects.get, { compositionId });
// Use Remotion's official estimation
const estimate = await estimatePrice({
region: region || "us-east-1",
durationInFrames,
memorySizeInMb: 2048,
diskSizeInMb: 2048,
lambdaEfficiencyLevel: 0.8, // Conservative
});
// Store estimate for user display
await ctx.runMutation(api.renders.createJob, {
compositionId,
estimatedCost: estimate.estimatedCost,
estimatedTime: estimate.estimatedTime,
status: "pending",
});
return {
cost: estimate.estimatedCost,
time: estimate.estimatedTime,
disclaimer: "Estimate based on current Remotion Lambda pricing. Actual costs may vary.",
};
},
});
export const recordActualCost = action({
handler: async (ctx, { renderId, actualCost, renderTime }) => {
// After render completes, record actual cost
await ctx.runMutation(api.renders.updateJob, {
renderId,
actualCost,
renderTime,
status: "complete",
});
// Calculate variance for telemetry
const job = await ctx.runQuery(api.renders.get, { renderId });
const variance = ((actualCost - job.estimatedCost) / job.estimatedCost) * 100;
// Log for cost optimization
await ctx.runMutation(api.telemetry.logCostVariance, {
variance,
composition: job.compositionId,
});
},
});
```
--------------------------------
### Scaffold Next.js 14 App with TypeScript
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
Command to create a new Next.js 14 project with TypeScript, Tailwind CSS, and the App Router. This serves as the foundational structure for the ChatKut application.
```bash
npx create-next-app@latest chatkut --typescript --tailwind --app --no-src-dir
```
--------------------------------
### Remotion Lambda Cost Estimation in TypeScript
Source: https://github.com/taikuun/chatkut/blob/master/CLAUDE.md
Handles cost estimation and recording for Remotion Lambda renders using the official API. It calculates estimates before rendering and logs actual costs after, dependent on @remotion/lambda/client. Inputs include render parameters like duration and memory; outputs cost estimates or records. Limited by Remotion licensing requirements for commercial use.
```typescript
import { estimatePrice } from "@remotion/lambda/client";
// Before render: show estimate
const estimate = await estimatePrice({
region: "us-east-1",
durationInFrames,
memorySizeInMb: 2048,
diskSizeInMb: 2048,
lambdaEfficiencyLevel: 0.8,
});
// After render: record actual cost for telemetry
await recordActualCost({ renderId, actualCost, renderTime });
```
--------------------------------
### TypeScript: Render Remotion Dynamic Composition with Player
Source: https://context7.com/taikuun/chatkut/llms.txt
Renders a video composition defined by an Intermediate Representation (IR) using Remotion's Player component. It takes composition details like dimensions, FPS, duration, and elements (video, text, audio) with their properties and animations. The Player component handles the rendering, including animation interpolation and easing.
```typescript
import { Player } from "@remotion/player";
import { DynamicComposition } from "@/remotion/DynamicComposition";
import type { CompositionIR } from "@/types/composition-ir";
// Define composition IR
const compositionIR: CompositionIR = {
id: "comp_demo",
version: 1,
metadata: {
width: 1920,
height: 1080,
fps: 30,
durationInFrames: 150,
backgroundColor: "#000000"
},
elements: [
{
id: "el_video_1",
type: "video",
label: "Hero Shot",
from: 0,
durationInFrames: 120,
properties: {
src: "https://customer-xxx.cloudflarestream.com/xxx/manifest/video.m3u8",
volume: 0.8,
width: "100%",
height: "auto"
},
animations: [
{
property: "scale",
keyframes: [
{ frame: 0, value: 1.0 },
{ frame: 120, value: 1.1 }
],
easing: "ease-in-out"
},
{
property: "opacity",
keyframes: [
{ frame: 0, value: 0 },
{ frame: 30, value: 1 },
{ frame: 90, value: 1 },
{ frame: 120, value: 0 }
],
easing: "linear"
}
]
},
{
id: "el_text_1",
type: "text",
label: "Title Card",
from: 30,
durationInFrames: 60,
properties: {
text: "ChatKut Demo",
fontSize: 96,
fontFamily: "Arial Black",
fontWeight: "bold",
color: "#ffffff",
x: 960,
y: 540,
textAlign: "center"
},
animations: [
{
property: "y",
keyframes: [
{ frame: 30, value: 600 },
{ frame: 60, value: 540 }
],
easing: "ease-out"
}
]
},
{
id: "el_audio_1",
type: "audio",
label: "BGM",
from: 0,
durationInFrames: 150,
properties: {
src: "https://chatkut-media.r2.dev/audio/background.mp3",
volume: 0.3
}
}
],
patches: []
};
// Render in React component
function VideoPreview() {
return (
);
}
// The DynamicComposition component automatically:
// - Wraps each element in with proper timing
// - Adds data-element-id attributes for tracking
// - Interpolates animation keyframes using Remotion's interpolate()
// - Handles video/audio/text/image rendering
// - Applies easing functions (linear, ease-in, ease-out, ease-in-out)
```
--------------------------------
### POST /api/ai/sendChatMessage
Source: https://context7.com/taikuun/chatkut/llms.txt
Handles user chat messages and generates AI responses with full project context including assets, composition state, and chat history.
```APIDOC
## POST /api/ai/sendChatMessage
### Description
Handles user chat messages and generates AI responses with full project context including assets, composition state, and chat history.
### Method
POST
### Endpoint
/api/ai/sendChatMessage
### Parameters
#### Request Body
- **projectId** (string) - Required - The ID of the project
- **message** (string) - Required - The user's chat message
### Request Example
{
"projectId": "k170yx7z9h8wh5p2q6e5d3f2g1h0j9k8",
"message": "Add a zoom animation to the second video clip"
}
### Response
#### Success Response (200)
- **messageId** (string) - The ID of the generated message
- **content** (string) - The AI's response content
- **model** (string) - The AI model used for the response
#### Response Example
{
"messageId": "m1x2y3z4...",
"content": "I'll add a smooth zoom animation to your second video clip, scaling from 1.0x to 1.2x over 3 seconds.",
"model": "gpt-4o"
}
```
--------------------------------
### Export to CapCut - TypeScript Implementation
Source: https://github.com/taikuun/chatkut/blob/master/chatkut-prd-v3.1-production-ready.md
Implementation of CapCut export feature as a Pro subscription action. Handles subscription verification, project/asset retrieval, CapCut MCP server integration, and export record creation with downloadable draft files.
```typescript
// convex/capcutExport.ts (Pro feature)
export const exportToCapCut = action({
handler: async (ctx, { projectId }) => {
// 1. Check Pro subscription
const user = await ctx.auth.getUserIdentity();
if (!user) throw new Error("Unauthorized");
const subscription = await ctx.runQuery(api.subscriptions.get, {
userId: user.subject,
});
if (subscription.tier !== "pro" && subscription.tier !== "team") {
throw new Error("CapCut export requires Pro subscription");
}
// 2. Get project and composition
const project = await ctx.runQuery(api.projects.get, { id: projectId });
const assets = await ctx.runQuery(api.assets.list, { projectId });
// 3. Call CapCut MCP server via backend proxy
const result = await ctx.runAction(api.mcpProxy.callMCPTool, {
toolName: "capcut-api/generate_draft",
parameters: {
compositionCode: project.compositionCode,
assets: assets.map(a => ({
url: a.playbackUrl, // Cloudflare Stream URL
type: a.type,
duration: a.duration,
})),
metadata: {
width: project.width,
height: project.height,
fps: project.fps,
},
},
userId: user.subject,
});
// 4. Store export record
await ctx.runMutation(api.exports.create, {
projectId,
userId: user.subject,
type: "capcut_draft",
status: "complete",
downloadUrl: result.draftZipUrl, // Signed R2 URL
expiresAt: Date.now() + 24 * 60 * 60 * 1000, // 24 hours
instructions: `
Download the .zip file and extract it.
Copy the dfd_xxxxx folder to:
- Windows: Documents/CapCut/User Data/Projects/com.lveditor.draft
- Mac: ~/Movies/CapCut/User Data/Projects/com.lveditor.draft
Open CapCut desktop app to see your project.
`.trim(),
});
return {
downloadUrl: result.draftZipUrl,
instructions: result.instructions,
expiration: "24 hours",
};
},
});
```
--------------------------------
### Manage Video Composition Elements with TypeScript
Source: https://context7.com/taikuun/chatkut/llms.txt
Demonstrates creating, adding, updating, finding, validating, and deleting elements in a video composition using IR helper functions. It utilizes functions like `createEmptyComposition`, `addElement`, `updateElement`, `findElementById`, `findElementsByLabel`, `validateComposition`, and `deleteElement`. The input is a composition object and element details, with the output being the modified composition or found elements/errors.
```typescript
import {
createEmptyComposition,
addElement,
updateElement,
deleteElement,
findElementById,
findElementsByLabel,
validateComposition
} from "@/lib/composition-engine/ir-helpers";
// Create new composition
let composition = createEmptyComposition({
width: 1920,
height: 1080,
fps: 30,
durationInFrames: 600 // 20 seconds
});
console.log(composition);
// Add video element
composition = addElement(composition, {
type: "video",
label: "Intro Scene",
from: 0,
durationInFrames: 150,
properties: {
src: "https://customer-xxx.cloudflarestream.com/xxx/manifest/video.m3u8",
volume: 1.0,
playbackRate: 1.0
},
animations: [{
property: "opacity",
keyframes: [
{ frame: 0, value: 0 },
{ frame: 30, value: 1 }
],
easing: "ease-in"
}]
});
console.log(composition.elements[0]);
// Add text overlay
composition = addElement(composition, {
type: "text",
label: "Title",
from: 30,
durationInFrames: 90,
properties: {
text: "Welcome to ChatKut",
fontSize: 72,
fontFamily: "Arial",
color: "#ffffff",
x: 960,
y: 540,
textAlign: "center"
},
animations: [{
property: "scale",
keyframes: [
{ frame: 30, value: 0.8 },
{ frame: 60, value: 1.0 }
],
easing: "ease-out"
}]
});
// Update element properties
const videoId = composition.elements[0].id;
composition = updateElement(composition, videoId, {
properties: {
...composition.elements[0].properties,
volume: 0.7
}
});
// Find elements
const foundById = findElementById(composition.elements, videoId);
console.log(foundById?.label);
const foundByLabel = findElementsByLabel(composition.elements, "title");
console.log(foundByLabel.length);
console.log(foundByLabel[0].properties.text);
// Validate composition
const errors = validateComposition(composition);
if (errors.length > 0) {
console.error("Composition errors:", errors);
} else {
console.log("Composition is valid");
}
// Delete element
composition = deleteElement(composition, videoId);
console.log(composition.elements.length);
```
--------------------------------
### Composition IR Type Definitions
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
TypeScript type definitions for the Composition Intermediate Representation (IR). This structure defines elements, animations, patches, and selectors used to describe video compositions before compilation.
```typescript
export type CompositionIR = { /* ... */ }
export type CompositionElement = { /* ... */ }
export type Animation = { /* ... */ }
export type Patch = { /* ... */ }
export type ElementSelector = { /* ... */ }
```
--------------------------------
### Execute Edit Plan on Composition
Source: https://context7.com/taikuun/chatkut/llms.txt
Applies edit operations to a composition's intermediate representation (IR) with automatic disambiguation and validation. It uses Convex's `useAction` hook and requires the `compositionId` and an `editPlan`. The `editPlan` specifies operations, selectors, and changes, including properties and animations. The function returns a result object indicating success, failure, or the need for disambiguation. Dependencies include '@convex-dev/convex-react'.
```typescript
import { api } from "./_generated/api";
import { useAction } from "convex/react";
const executeEdit = useAction(api.compositions.executeEditPlan);
// Execute a validated edit plan
const result = await executeEdit({
compositionId: "c2x3y4z5..." as Id<"compositions">
editPlan: {
operation: "update",
selector: { type: "byId", id: "el_abc123" },
changes: {
properties: { volume: 0.8 },
animation: {
property: "scale",
keyframes: [
{ frame: 0, value: 1.0 },
{ frame: 90, value: 1.2 }
],
easing: "ease-in-out"
}
}
}
});
if (result.success) {
console.log("Edit applied:", result.receipt);
// "Updated video clip 'Intro': volume adjusted to 0.8, added zoom animation"
console.log("Affected elements:", result.affectedElements);
// ["el_abc123"]
} else if (result.needsDisambiguation) {
// Multiple elements matched - show user options
console.log("Ambiguous selector. Choose element:");
result.disambiguationOptions.forEach((option, i) => {
console.log(`${i + 1}. ${option.label} at ${option.timecode}`);
});
// Re-execute with resolved element ID
const resolved = await executeEdit({
compositionId: "c2x3y4z5..." as Id<"compositions">
editPlan: { ...editPlan },
resolvedElementId: disambiguationOptions[0].elementId
});
} else {
console.error("Edit failed:", result.error);
}
```
--------------------------------
### Compile Composition IR to Remotion Code
Source: https://github.com/taikuun/chatkut/blob/master/IMPLEMENTATION_PLAN.md
TypeScript function to compile the Composition IR into executable Remotion React code. This compiler generates JSX, handles animations using `interpolate()`, and formats the output using Prettier.
```typescript
import { CompositionIR } from '@/types/composition-ir';
export function compileIRToCode(ir: CompositionIR): string {
// Generate imports (Remotion, assets)
// Generate composition metadata (width, height, fps, duration)
// Convert elements to JSX (with `data-element-id` attributes)
// Handle nested sequences
// Generate animations using `interpolate()`
// Generate text styles
// Format with Prettier
return '// Generated Remotion code will go here';
}
```