/// import { Cell, compileAndRun, computed, Default, generateText, handler, ifElse, NAME, navigateTo, pattern, UI, } from "commontools"; // Template for the AI to reference const TEMPLATE = `/// import { Cell, computed, handler, Default, NAME, pattern, UI } from "commontools"; interface Input { value: Default; } const increment = handler }>( (_, { value }) => value.set(value.get() + 1) ); const decrement = handler }>( (_, { value }) => value.set(value.get() - 1) ); export default pattern(({ value }) => { return { [NAME]: computed(() => \`Counter: \${value}\`), [UI]: (
- {value} +
), value, }; });`; const SYSTEM_PROMPT = `You are a CommonTools pattern generator. Given a user request, generate a complete TypeScript pattern file. IMPORTANT RULES: 1. Start with: /// 2. Import from "commontools": Cell, Default, computed, handler, NAME, pattern, UI, ifElse 3. Use the pattern() or pattern() API 4. For arrays that need mutation, use Cell in the interface 5. Use $checked, $value for bidirectional binding on ct-checkbox, ct-input 6. Use inline handlers for simple operations, handler() for complex ones 7. Always return [NAME] and [UI] from the pattern 8. Use computed() for derived values and data transformations TEMPLATE FOR REFERENCE: ${TEMPLATE} Generate ONLY the TypeScript code, no explanations or markdown.`; interface Input { prompt: Default; } interface Output { prompt: Cell; } const updatePrompt = handler< { detail: { message: string } }, { prompt: Cell } >((event, { prompt }) => { const newPrompt = event.detail?.message?.trim(); if (newPrompt) { prompt.set(newPrompt); } }); const visit = handler }>((_, { result }) => { return navigateTo(result); }); export default pattern(({ prompt }) => { // Step 1: Generate pattern source code from prompt const generated = generateText({ system: SYSTEM_PROMPT, prompt, model: "anthropic:claude-sonnet-4-5", }); const processedResult = computed(() => { const result = generated?.result ?? ""; // Remove wrapping ```typescript``` if it exists return result.replace(/^```typescript\n?/, "").replace(/\n?```$/, ""); }); // Step 2: Compile the generated code when ready const compileParams = computed(() => ({ files: processedResult ? [{ name: "/main.tsx", contents: processedResult }] : [], main: processedResult ? "/main.tsx" : "", })); const compiled = compileAndRun(compileParams); // Compute states const isGenerating = generated.pending; const hasCode = computed(() => !!generated.result); const hasError = computed(() => !!compiled.error); const isReady = computed(() => !compiled.pending && !!compiled.result && !compiled.error ); return { [NAME]: "Write and Run", [UI]: (

Write and Run

Describe a pattern and I'll generate, compile, and run it.

{ifElse( isGenerating, Generating code..., ifElse( hasError,
Compile error: {compiled.error}
, ifElse( isReady, Open Generated Pattern , Enter a prompt to generate a pattern , ), ), )}
{ifElse( isReady,

Generated Pattern

{compiled.result}
, , )} {ifElse( hasCode,

Generated Code

, , )}
), prompt, generatedCode: generated.result, compiledCharm: compiled.result, error: compiled.error, }; });