Documentation
v1.0.0
Core Primitive
🧱

Block System

Core abstraction for prompt components and data structures

Overview

The Block System is the foundational primitive of vibecoding. It provides a type-safe, serializable abstraction for representing prompt components with their associated data, metadata, and relationships.

Key Features
  • Type Safety: Full TypeScript support with strict typing
  • Serializable: JSON-compatible data structures
  • Extensible: Easy to add custom block types
  • Composable: Blocks can contain other blocks
  • Unique IDs: Every block has a unique identifier

Core Interfaces

Block Interface
The fundamental data structure for all prompt blocks
TypeScript
interface Block {
  id: string;
  type: BlockType;
  content: string | Record<string, any>;
  metadata?: Record<string, any>;
  children?: Block[];
}
idstringrequired

Unique identifier for the block (generated using nanoid)

typeBlockTyperequired

The block type (role, goal, instructions, etc.)

contentstring | Record<string, any>required

The block's data - can be simple string or complex object

metadataRecord<string, any>optional

Additional metadata (timestamps, versions, tags, etc.)

childrenBlock[]optional

Nested child blocks for hierarchical structures

Usage Examples

Creating Blocks
How to create and manipulate blocks programmatically
TypeScript
import { nanoid } from 'nanoid';
import type { Block, BlockType } from '@/types/prompt-blocks';

// Create a simple text block
const createTextBlock = (content: string): Block => ({
  id: nanoid(),
  type: 'text',
  content
});

// Create a role block with default content
const createRoleBlock = (content?: string): Block => ({
  id: nanoid(),
  type: 'role',
  content: content || 'You are a helpful AI assistant...',
  metadata: {
    createdAt: new Date().toISOString(),
    version: '1.0'
  }
});

// Create a variable block with structured content
const createVariableBlock = (name: string, type: string, required = false): Block => ({
  id: nanoid(),
  type: 'variable',
  content: {
    name,
    type,
    required,
    description: `Variable: ${name}`
  }
});

// Create a complex block with children
const createInstructionBlock = (steps: string[]): Block => ({
  id: nanoid(),
  type: 'instructions',
  content: { steps },
  children: steps.map(step => createTextBlock(step))
});
Block Operations
Common operations for working with blocks
TypeScript
// Find block by ID
const findBlockById = (blocks: Block[], id: string): Block | undefined => {
  for (const block of blocks) {
    if (block.id === id) return block;
    if (block.children) {
      const found = findBlockById(block.children, id);
      if (found) return found;
    }
  }
  return undefined;
};

// Filter blocks by type
const filterBlocksByType = (blocks: Block[], type: BlockType): Block[] => {
  return blocks.filter(block => block.type === type);
};

// Update block content
const updateBlockContent = (blocks: Block[], id: string, newContent: any): Block[] => {
  return blocks.map(block => {
    if (block.id === id) {
      return { ...block, content: newContent };
    }
    if (block.children) {
      return {
        ...block,
        children: updateBlockContent(block.children, id, newContent)
      };
    }
    return block;
  });
};

// Validate block structure
const validateBlock = (block: Block): boolean => {
  if (!block.id || !block.type || block.content === undefined) {
    return false;
  }
  if (block.children) {
    return block.children.every(child => validateBlock(child));
  }
  return true;
};

Creating Custom Block Types

Adding New Block Types
Step-by-step guide for extending the block system

1. Define the Block Type


| 'my-custom-block'

2. Add Block Configuration

'my-custom-block': {
  icon: '🎨',
  name: 'My Custom Block',
  description: 'Custom functionality',
  color: 'purple',
  category: 'custom'
}

3. Create Content Interface (Optional)

interface CustomBlockContent {
  title: string;
  data: any[];
}

4. Add Editor Component