canvas-types

Canvas Types & Patterns Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "canvas-types" with this command: npx skills add omerakben/omer-akben/omerakben-omer-akben-canvas-types

Canvas Types & Patterns Skill

When to Use

Use this skill when:

  • Defining new Canvas types

  • Working with Zod schemas

  • Adding language support

  • Creating utility functions for Canvas

Core Type Definitions

Canvas Types

// From lib/canvas/types.ts

export const CANVAS_TYPES = [ 'code', // Executable code with Monaco editor 'document', // Markdown/rich text editor 'visualization', // D3/Chart.js interactive visualizations 'quiz', // Interactive assessment 'flashcards', // Study cards with flip interaction 'diagram', // Mermaid/PlantUML diagrams 'math', // LaTeX mathematical expressions 'react', // React component preview ] as const;

export type CanvasType = (typeof CANVAS_TYPES)[number];

View Modes

export type ViewMode = 'code' | 'preview' | 'split';

Canvas State

export interface CanvasState { // Core state isOpen: boolean; content: string; type: CanvasType; title: string; language: string; viewMode: ViewMode;

// History for undo/redo history: string[]; historyIndex: number;

// Generation state generationPrompt: string; isGenerating: boolean; }

Zod Schemas

Canvas Configuration Schema

import { z } from 'zod';

export const CanvasConfigSchema = z.object({ type: z.enum(CANVAS_TYPES), title: z.string().max(100), language: z.string().optional(), initialContent: z.string().optional().default(''), generationPrompt: z.string().optional(), educationalContext: z.object({ topic: z.string().optional(), difficulty: z.enum(['beginner', 'intermediate', 'advanced']).optional(), learningObjective: z.string().optional(), }).optional(), // Artifact persistence tracking artifactId: z.string().uuid().optional(), conversationId: z.string().uuid().optional(), messageId: z.string().uuid().optional(), toolInvocationId: z.string().optional(), });

export type CanvasConfig = z.infer<typeof CanvasConfigSchema>;

Content Validation

/**

  • Maximum canvas content size (1MB)
  • Prevents memory abuse while allowing substantial code examples */ export const CANVAS_MAX_CONTENT_SIZE = 1_048_576;

export const CanvasContentSchema = z.object({ type: z.enum(CANVAS_TYPES), title: z.string().max(100), content: z.string().max(CANVAS_MAX_CONTENT_SIZE), language: z.string().optional(), metadata: z.object({ educationalObjective: z.string().optional(), difficulty: z.enum(['beginner', 'intermediate', 'advanced']).optional(), estimatedTime: z.number().optional(), prerequisites: z.array(z.string()).optional(), }).optional(), });

export type CanvasContent = z.infer<typeof CanvasContentSchema>;

Language Support

Tiered Language Support

export const SUPPORTED_LANGUAGES = { // P0 - Must have (curriculum analysis) tier1: [ { id: 'python', name: 'Python', extensions: ['.py'], monacoId: 'python' }, { id: 'javascript', name: 'JavaScript', extensions: ['.js'], monacoId: 'javascript' }, { id: 'html', name: 'HTML', extensions: ['.html'], monacoId: 'html' }, { id: 'css', name: 'CSS', extensions: ['.css'], monacoId: 'css' }, { id: 'sql', name: 'SQL', extensions: ['.sql'], monacoId: 'sql' }, { id: 'markdown', name: 'Markdown', extensions: ['.md'], monacoId: 'markdown' }, ], // P1 - High priority tier2: [ { id: 'typescript', name: 'TypeScript', extensions: ['.ts', '.tsx'], monacoId: 'typescript' }, { id: 'java', name: 'Java', extensions: ['.java'], monacoId: 'java' }, { id: 'r', name: 'R', extensions: ['.r'], monacoId: 'r' }, { id: 'latex', name: 'LaTeX', extensions: ['.tex'], monacoId: 'latex' }, ], // P2 - Secondary tier3: [ { id: 'c', name: 'C', extensions: ['.c', '.h'], monacoId: 'c' }, { id: 'cpp', name: 'C++', extensions: ['.cpp', '.hpp'], monacoId: 'cpp' }, ], } as const;

Execution Support Matrix

export const EXECUTION_SUPPORT: Record<string, 'pyodide' | 'iframe' | 'none'> = { python: 'pyodide', javascript: 'iframe', html: 'iframe', typescript: 'iframe', // Transpiled to JS react: 'iframe', css: 'iframe', sql: 'none', java: 'none', c: 'none', cpp: 'none', r: 'none', latex: 'none', markdown: 'none', mermaid: 'none', };

Utility Functions

Default Language by Canvas Type

export function getDefaultLanguage(type: CanvasType): string { const defaults: Record<CanvasType, string> = { code: 'python', visualization: 'html', react: 'typescript', document: 'markdown', diagram: 'mermaid', math: 'latex', quiz: 'json', flashcards: 'json', }; return defaults[type] || 'plaintext'; }

Monaco Language Mapping

export function getMonacoLanguage(language: string): string { const mapping: Record<string, string> = { python: 'python', javascript: 'javascript', typescript: 'typescript', tsx: 'typescript', jsx: 'javascript', html: 'html', css: 'css', markdown: 'markdown', json: 'json', sql: 'sql', java: 'java', c: 'c', cpp: 'cpp', csharp: 'csharp', go: 'go', rust: 'rust', latex: 'latex', mermaid: 'markdown', // No native mermaid support }; return mapping[language] || 'plaintext'; }

Execution Check

export function canExecute(language: string): boolean { return ( EXECUTION_SUPPORT[language] !== 'none' && EXECUTION_SUPPORT[language] !== undefined ); }

File Extension Mapping

export function getFileExtension(language: string): string { const extensions: Record<string, string> = { python: '.py', javascript: '.js', typescript: '.ts', html: '.html', css: '.css', markdown: '.md', json: '.json', sql: '.sql', java: '.java', c: '.c', cpp: '.cpp', }; return extensions[language] || '.txt'; }

Tool Result Types

Canvas Actions

export interface OpenCanvasResult { action: 'open_canvas'; canvasConfig: { type: CanvasType; title: string; language: string; initialContent: string; generationPrompt: string; educationalContext?: { topic?: string; difficulty?: 'beginner' | 'intermediate' | 'advanced'; learningObjective?: string; }; }; }

export interface UpdateCanvasResult { action: 'update_canvas'; updates: { content?: string; title?: string; language?: string; }; }

Adding New Canvas Types

Step 1: Add to Types

// In types.ts export const CANVAS_TYPES = [ // ... existing 'new_type', // Add here ] as const;

Step 2: Set Default Language

// In getDefaultLanguage() const defaults: Record<CanvasType, string> = { // ... existing new_type: 'json', // Add default };

Step 3: Update GenUI Components

// In genui renderer switch (canvasType) { // ... existing cases case 'new_type': return <NewTypeCanvas {...props} />; }

Adding New Languages

Step 1: Add to Tier

// In SUPPORTED_LANGUAGES tier2: [ // ... existing { id: 'rust', name: 'Rust', extensions: ['.rs'], monacoId: 'rust' }, ],

Step 2: Set Execution Support

// In EXECUTION_SUPPORT rust: 'none', // Or 'iframe' if you implement WASM execution

Step 3: Add Monaco Mapping

// In getMonacoLanguage() rust: 'rust',

Step 4: Add File Extension

// In getFileExtension() rust: '.rs',

Type Guards

Canvas Type Guard

export function isCanvasType(value: unknown): value is CanvasType { return typeof value === 'string' && CANVAS_TYPES.includes(value as CanvasType); }

Execution Support Guard

export function supportsExecution(language: string): language is 'python' | 'javascript' | 'typescript' | 'html' | 'react' | 'css' { return EXECUTION_SUPPORT[language] !== 'none' && EXECUTION_SUPPORT[language] !== undefined; }

Validation Patterns

Safe Parsing

import { CanvasConfigSchema } from '@/lib/canvas/types';

function parseCanvasConfig(input: unknown) { const result = CanvasConfigSchema.safeParse(input);

if (!result.success) { console.error('Invalid canvas config:', result.error.errors); return null; }

return result.data; }

Content Size Check

function isContentValid(content: string): boolean { const byteSize = new TextEncoder().encode(content).length; return byteSize <= CANVAS_MAX_CONTENT_SIZE; }

Testing Checklist

  • All Canvas types have default languages

  • All languages have Monaco mappings

  • All languages have file extensions

  • Execution support is correctly marked

  • Zod schemas validate correctly

  • Type guards work as expected

  • Max content size is enforced

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

bundle-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
General

environment-configuration

No summary provided by upstream source.

Repository SourceNeeds Review
General

educational-ui

No summary provided by upstream source.

Repository SourceNeeds Review
General

nextjs-page-creator

No summary provided by upstream source.

Repository SourceNeeds Review