Skip to content

Latest commit

 

History

History
233 lines (179 loc) · 9.33 KB

File metadata and controls

233 lines (179 loc) · 9.33 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build & Development Commands

npm run dev      # Start Next.js dev server at http://localhost:3000
npm run build    # Build for production
npm run start    # Start production server
npm run lint     # Run Next.js linting
npm run test     # Run all tests with Vitest (watch mode)
npm run test:run # Run all tests once (CI mode)

Environment Setup

Create .env.local in the root directory:

GEMINI_API_KEY=your_gemini_api_key
OPENAI_API_KEY=your_openai_api_key  # Optional, for OpenAI LLM provider
KIE_API_KEY=your_kie_api_key        # Optional, for Kie.ai models (Sora, Veo, Kling, etc.)

Architecture Overview

Node Banana is a node-based visual workflow editor for AI image generation. Users drag nodes onto a React Flow canvas, connect them via typed handles, and execute pipelines that call AI APIs.

Core Stack

  • Next.js 16 (App Router) with TypeScript
  • @xyflow/react (React Flow) for the node editor canvas
  • Konva.js / react-konva for canvas annotation drawing
  • Zustand for state management (single store pattern)

Key Files

Purpose Location
Central workflow state & execution logic src/store/workflowStore.ts
All TypeScript type definitions src/types/index.ts
Main canvas component & connection validation src/components/WorkflowCanvas.tsx
Base node component (shared by all nodes) src/components/nodes/BaseNode.tsx
Image generation API route src/app/api/generate/route.ts
LLM text generation API route src/app/api/llm/route.ts
Cost calculations src/utils/costCalculator.ts
Grid splitting utility src/utils/gridSplitter.ts

State Management

All application state lives in workflowStore.ts using Zustand. Key patterns:

  • useWorkflowStore() hook provides access to nodes, edges, and all actions
  • executeWorkflow(startFromNodeId?) runs the pipeline via topological sort
  • getConnectedInputs(nodeId) retrieves upstream data for a node
  • updateNodeData(nodeId, partialData) updates node state
  • Auto-save runs every 90 seconds when enabled

Execution Flow

  1. User clicks Run or presses Cmd/Ctrl+Enter
  2. executeWorkflow() performs topological sort on node graph
  3. Nodes execute in dependency order, calling APIs as needed
  4. getConnectedInputs() provides upstream images/text to each node
  5. Locked groups are skipped; pause edges halt execution

AI Models

Image generation models (these exist and are recently released):

  • gemini-2.5-flash-image → internal name: nano-banana
  • gemini-3-pro-image-preview → internal name: nano-banana-pro

LLM models:

  • Google: gemini-2.5-flash, gemini-3-flash-preview, gemini-3-pro-preview
  • OpenAI: gpt-4.1-mini, gpt-4.1-nano

Node Types

Type Purpose Inputs Outputs
imageInput Load/upload images reference image
annotation Draw on images (Konva) image image
prompt Text prompt input none text
nanoBanana AI image generation image, text image
llmGenerate AI text generation text, image text
splitGrid Split image into grid cells image reference
generateAudio AI audio/TTS generation text audio
audioInput Load/upload audio files audio audio
glbViewer Load/display 3D GLB models none image
output Display final result image none

Node Connection System

Handle Types

Handle Type Data Format Description
image Base64 data URL Visual content
text String Text content
audio Base64 data URL Audio content

Connection Rules

  1. Type Matching: Handles only connect to matching types (imageimage, texttext)
  2. Direction: Connections flow from source (output) to target (input)
  3. Multiplicity: Image inputs accept multiple connections; text inputs accept one

Data Flow in getConnectedInputs

Returns { images: string[], text: string | null }.

Image data extracted from:

  • imageInputdata.image
  • annotationdata.outputImage
  • nanoBananadata.outputImage

Text data extracted from:

  • promptdata.prompt
  • llmGeneratedata.outputText

Audio data extracted from:

  • audioInputdata.audioFile
  • generateAudiodata.outputAudio

Keyboard Shortcuts

  • Cmd/Ctrl + Enter - Run workflow
  • Cmd/Ctrl + C/V - Copy/paste nodes
  • Shift + P - Add prompt node at center
  • Shift + I - Add image input node
  • Shift + G - Add generate (nanoBanana) node
  • Shift + V - Add video (generateVideo) node
  • Shift + L - Add LLM node
  • Shift + A - Add annotation node
  • Shift + T - Add audio (generateAudio) node
  • H - Stack selected nodes horizontally
  • V - Stack selected nodes vertically
  • G - Arrange selected nodes in grid
  • ? - Show keyboard shortcuts

Adding New Node Types

  1. Define the data interface in src/types/index.ts
  2. Add to NodeType union in src/types/index.ts
  3. Create default data in createDefaultNodeData() in workflowStore.ts
  4. Add dimensions to defaultDimensions in workflowStore.ts
  5. Create the component in src/components/nodes/
  6. Export from src/components/nodes/index.ts
  7. Register in nodeTypes in WorkflowCanvas.tsx
  8. Add minimap color in WorkflowCanvas.tsx
  9. Update getConnectedInputs() if the node produces consumable output
  10. Add execution logic in executeWorkflow() if the node requires processing
  11. Update ConnectionDropMenu.tsx to include the node in source/target lists

Handle Naming Convention

Use descriptive handle IDs matching the data type:

  • id="image" for image data
  • id="text" for text data

Validation

  • Connection validation: isValidConnection() in WorkflowCanvas.tsx
  • Workflow validation: validateWorkflow() in workflowStore.ts

Adding New Kie.ai Models (SOP)

Reference docs: https://docs.kie.ai/llms.txt lists all available model API pages.

Step 1: Gather API Details

Visit the model's doc page on https://docs.kie.ai/ and collect:

  • Model ID(s) (the model param sent to the API)
  • Capabilities: text-to-image, image-to-image, text-to-video, image-to-video
  • API endpoint (standard: /api/v1/jobs/createTask, or model-specific like Veo's /api/v1/veo/generate)
  • All input parameters: name, type, enum values, defaults, required status
  • Image/video input parameter name (e.g., image_urls, imageUrls, input_urls)
  • Polling endpoint (standard: /api/v1/jobs/recordInfo, or model-specific)
  • Response format and status field names
  • Pricing (per-run cost if available)

Step 2: Add Model Registry Entry

File: src/app/api/models/route.ts — Add to KIE_MODELS array. Each model entry needs: id, name, description, provider: "kie", capabilities, pricing, pageUrl. Use separate entries for each capability variant (e.g., model/text-to-video and model/image-to-video).

Step 3: Add Parameter Schema

File: src/app/api/models/[modelId]/route.ts — Add to getKieSchema(). Define parameters (user-configurable settings) and inputs (connectable handles like prompt, images).

Step 4: Add Default Parameters

File: src/app/api/generate/route.ts — Add case to getKieModelDefaults(). Provide required defaults that must be present even if the user doesn't set them.

Step 5: Add Image Input Key Mapping

File: src/app/api/generate/route.ts — Add to getKieImageInputKey(). Map the model to its correct image parameter name if it differs from the default image_urls.

Step 6: Handle Non-Standard API (if applicable)

If the model uses different endpoints than /api/v1/jobs/createTask and /api/v1/jobs/recordInfo:

  • Add a detection function (e.g., isVeoModel())
  • Add a model-ID-to-API-model mapping function
  • Add a custom polling function for the model's status endpoint
  • Add a branch in generateWithKie() for the custom request format

API Routes

All routes in src/app/api/:

Route Timeout Purpose
/api/generate 5 min Image generation via Gemini
/api/llm 1 min Text generation (Google/OpenAI)
/api/workflow default Save/load workflow files
/api/save-generation default Auto-save generated images
/api/logs default Session logging

localStorage Keys

  • node-banana-workflow-configs - Project metadata (paths)
  • node-banana-workflow-costs - Cost tracking per workflow
  • node-banana-nanoBanana-defaults - Sticky generation settings

Git Workflow

  • The primary development branch is develop, NOT main or master
  • Always checkout develop before creating feature branches: git checkout develop
  • Create feature branches from develop using: feature/<short-description> or fix/<short-description>
  • All PRs MUST target develop: use gh pr create --base develop
  • Never push directly to main, master, or develop

Commits

  • Commit after each logical task or unit of work is complete. When implementing a multi-task plan, commit after finishing each task — do NOT batch all tasks into a single commit at the end.
  • Each commit should be atomic and self-contained: one task = one commit.
  • The .planning directory is untracked, do not attempt to commit any changes to the files in this directory.