The useGeneration hook provides a complete interface for generating, applying, and managing AI-generated code with real-time streaming updates.
Hook signature
function useGeneration(): GenerationHookReturn
Return value
The hook returns an object containing state properties and methods:
Whether code generation is currently in progress
Whether generated code is being applied to the sandbox
Whether diagnostics are currently running
Whether code is actively streaming from the AI
Current progress message describing the generation state
Accumulated streamed code content
The file currently being streamed (incomplete)
Array of completed generated files
Array of files that have been streamed and completed
Array of package names required by the generated code
Error message if generation failed
generate
(options: GenerateOptions) => Promise<void>
Method to start code generation
apply
(files: GeneratedFile[], packages: string[], sandboxId?: string) => Promise<boolean>
Method to apply generated code to a sandbox
Method to cancel ongoing generation
Method to reset all state to initial values
checkDiagnostics
(sandboxId?: string) => Promise<DiagnosticsResult>
Method to run diagnostics on the generated code
Types
GenerateOptions
The user prompt describing what to generate
Whether this is an edit to existing code or a new generation
ID of the sandbox to generate code for (required for edits)
Callback fired when new content is streamed
onFile
(file: GeneratedFile) => void
Callback fired when a complete file is generated
Callback fired when a package dependency is detected
onComplete
(files: GeneratedFile[], packages: string[]) => void
Callback fired when generation completes successfully
Callback fired when an error occurs
StreamingFile
File path relative to project root
File content (may be partial if not completed)
type
'javascript' | 'css' | 'json' | 'html' | 'text'
Detected file type based on extension
Whether the file has finished streaming
GenerationState
Generation is in progress
Code is being applied to sandbox
Code is actively streaming
File currently being streamed
Usage examples
Basic generation
import { useGeneration } from '@/lib/hooks/use-generation';
function CodeGenerator() {
const generation = useGeneration();
const handleGenerate = async () => {
await generation.generate({
prompt: 'Create a React counter component',
isEdit: false,
});
};
return (
<div>
<button onClick={handleGenerate} disabled={generation.isGenerating}>
{generation.isGenerating ? 'Generating...' : 'Generate Code'}
</button>
{generation.progress && (
<p className="status">{generation.progress}</p>
)}
{generation.error && (
<p className="error">{generation.error}</p>
)}
</div>
);
}
With streaming callbacks
import { useGeneration } from '@/lib/hooks/use-generation';
import { useState } from 'react';
function StreamingGenerator() {
const generation = useGeneration();
const [streamedFiles, setStreamedFiles] = useState<string[]>([]);
const handleGenerate = async () => {
await generation.generate({
prompt: 'Build a todo app with React',
isEdit: false,
onFile: (file) => {
console.log('File generated:', file.path);
setStreamedFiles((prev) => [...prev, file.path]);
},
onPackage: (pkg) => {
console.log('Package required:', pkg);
},
onComplete: (files, packages) => {
console.log('Generation complete!');
console.log('Files:', files.length);
console.log('Packages:', packages);
},
});
};
return (
<div>
<button onClick={handleGenerate}>
Generate
</button>
{generation.isStreaming && generation.currentFile && (
<div className="streaming">
<p>Streaming: {generation.currentFile.path}</p>
</div>
)}
<ul>
{streamedFiles.map((path) => (
<li key={path}>{path}</li>
))}
</ul>
</div>
);
}
Editing existing code
import { useGeneration } from '@/lib/hooks/use-generation';
function CodeEditor({ sandboxId }: { sandboxId: string }) {
const generation = useGeneration();
const handleEdit = async () => {
await generation.generate({
prompt: 'Add a reset button to the counter',
isEdit: true,
sandboxId,
});
};
return (
<div>
<button onClick={handleEdit} disabled={generation.isGenerating}>
Make Changes
</button>
{generation.isGenerating && (
<div className="progress">
<p>{generation.progress}</p>
<p>Files: {generation.streamingFiles.length}</p>
</div>
)}
</div>
);
}
Apply and validate
import { useGeneration } from '@/lib/hooks/use-generation';
function GenerateAndApply({ sandboxId }: { sandboxId: string }) {
const generation = useGeneration();
const handleGenerateAndApply = async () => {
await generation.generate({
prompt: 'Create a login form',
isEdit: false,
onComplete: async (files, packages) => {
// Apply generated code
const success = await generation.apply(
files,
packages,
sandboxId
);
if (success) {
// Run diagnostics
const result = await generation.checkDiagnostics(sandboxId);
if (result.success) {
console.log('Code applied and validated!');
} else {
console.error('Diagnostics failed:', result.output);
}
}
},
});
};
return (
<div>
<button onClick={handleGenerateAndApply}>
Generate and Apply
</button>
{generation.isApplying && (
<p>Applying code to sandbox...</p>
)}
{generation.isChecking && (
<p>Running diagnostics...</p>
)}
</div>
);
}
Full builder integration
import { useGeneration } from '@/lib/hooks/use-generation';
import { useSandbox } from '@/lib/hooks/use-sandbox';
import { useCallback, useEffect } from 'react';
function BuilderPage() {
const sandbox = useSandbox();
const generation = useGeneration();
const handleGenerate = useCallback(
async (options: Parameters<typeof generation.generate>[0]) => {
await generation.generate(options);
},
[generation]
);
useEffect(() => {
if (!sandbox.isReady && !sandbox.isCreating && !sandbox.error) {
sandbox.createSandbox();
}
}, [sandbox]);
return (
<div className="builder">
<div className="controls">
<button
onClick={() => handleGenerate({
prompt: 'Build a dashboard',
isEdit: false,
})}
disabled={!sandbox.isReady || generation.isGenerating}
>
Generate
</button>
{generation.isGenerating && (
<button onClick={generation.cancel}>
Cancel
</button>
)}
</div>
<div className="status">
<p>{generation.progress}</p>
{generation.isStreaming && (
<p>Streaming: {generation.streamingFiles.length} files</p>
)}
</div>
</div>
);
}
State management
The hook manages complex state transitions:
- Idle -
isGenerating: false, isStreaming: false
- Generating -
isGenerating: true, starts with progress: "Starting generation..."
- Streaming -
isStreaming: true, files appear in streamingFiles and currentFile
- Applying -
isApplying: true, code being written to sandbox
- Checking -
isChecking: true, diagnostics running
- Error -
error is set, generation stops
Audio feedback
The hook automatically plays a keyboard typing sound (/keyboard.mp3) while isStreaming is true at 25% volume.
Cancellation
Generation can be cancelled at any time using the cancel() method, which aborts the fetch request and updates state.
Error handling
Errors are captured in the error field and passed to the onError callback if provided. The hook handles:
- Network failures
- Server errors
- Abort errors (from cancellation)
- Stream parsing errors