Overview
Code artifacts render syntax-highlighted code with live preview and execution.
Supported Languages
Code Previews
| Language | Code Block | Features |
|---|
| HTML | ```html | Live preview in iframe |
| React/JSX | ```jsx | Live component preview |
| Vue | ```vue | SFC with preview |
| JSON | ```json | Tree view, formatting |
| SVG | ```svg | Live preview |
| CSV | ```csv | Spreadsheet viewer |
| TSV | ```tsv | Spreadsheet viewer |
| Smart Diff | ```smartdiff | Language-aware side-by-side diff |
Code Runtime
| Language | Code Block | Features |
|---|
| JavaScript | ```javascript | Execution, console output |
| Python | ```python | Pyodide execution |
HTML
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui; padding: 2rem; }
h1 { color: #6366f1; }
</style>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Renders in a sandboxed iframe. External CDNs allowed (Tailwind, etc.).
React / JSX
function Counter() {
const [count, setCount] = useState(0)
return (
<div className="p-4 text-center">
<div className="text-4xl mb-4">{count}</div>
<button
onClick={() => setCount(c => c + 1)}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
Increment
</button>
</div>
)
}
Available: React hooks, Tailwind CSS, Lucide icons, Recharts.
Vue
<template>
<div class="counter">
<button @click="count++">Count: {{ count }}</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<style scoped>
.counter { padding: 1rem; }
</style>
JavaScript
async function fetchData() {
const response = await fetch('https://api.example.com/data')
const data = await response.json()
console.log(data)
}
fetchData()
Console output (log, warn, error) is captured and displayed.
Python
import numpy as np
import pandas as pd
data = {'name': ['Alice', 'Bob'], 'age': [25, 30]}
df = pd.DataFrame(data)
print(df)
Runs via Pyodide. Available: numpy, pandas, scipy, scikit-learn, matplotlib.
JSON
{
"user": {
"id": 12345,
"name": "Jane Smith",
"roles": ["admin", "editor"]
}
}
Features: tree view, collapse/expand, search, JSONPath.
SVG
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="80" fill="#6366f1"/>
<text x="100" y="110" text-anchor="middle" fill="white" font-size="24">SVG</text>
</svg>
CSV / TSV
Name,Department,Salary,Start Date,City
Alice Johnson,Engineering,95000,2023-01-15,San Francisco
Bob Smith,Marketing,72000,2022-06-01,New York
Carol Williams,Engineering,105000,2021-03-22,Seattle
Renders in an interactive spreadsheet. Auto-detects delimiter (comma, tab, pipe, semicolon). Cells are editable — changes are saved back to the artifact automatically.
Use tsv for tab-separated data:
Name Score Grade
Alice 95 A
Bob 82 B
Carol 91 A
Smart Diff
Use smartdiff for structured diffs with language-aware syntax highlighting:
{
"oldCode": "function greet(name) {\n return 'Hello ' + name;\n}",
"newCode": "function greet(name) {\n return `Hello ${name}!`;\n}",
"language": "javascript"
}
Each line is highlighted using the actual language grammar (e.g., JavaScript keywords, strings) with red/green backgrounds for deleted/inserted lines. The diff panel shows side-by-side or unified view.
| Field | Type | Description |
|---|
oldCode | string | Original code |
newCode | string | Updated code |
language | string | Language for syntax highlighting (e.g., javascript, python) |
Plain Text
Files with unknown extensions automatically fall back to plain text rendering in the code panel:
key = value
host = localhost
port = 3000
[section]
enabled = true
Supported via the txt panel type. This means any file type can be opened — if no specific panel exists for the language, it renders as plain text with the code viewer.
Programmatic API
Open code artifacts directly without processing AI message content.
openFile
Auto-detects language from the file extension:
const { openFile } = useArtifactuse()
// Opens as JSX (React panel)
openFile('App.jsx', reactCode)
// Opens as Python (code panel)
openFile('utils.py', pythonCode, { title: 'My Utils' })
// Opens as plain text (unknown extension)
openFile('config.ini', configContent)
openCode
Specify the language explicitly:
const { openCode } = useArtifactuse()
openCode(jsCode, 'javascript')
openCode(htmlCode, 'html', { title: 'My Page' })
updateFile
Updates an existing artifact’s code and refreshes the panel without creating a duplicate tab:
const { openFile, updateFile } = useArtifactuse()
const artifact = openFile('app.html', code, { panelUrl: '...' })
// Later — update in place
updateFile(artifact, newCode)
updateFile(artifact.id, newCode, { panelUrl: newUrl })
Options
Both methods accept an options object:
| Option | Type | Description |
|---|
title | string | Display title (defaults to filename for openFile) |
tabs | string[] | Visible tabs: 'preview', 'code', 'split', 'edit' |
viewMode | string | Initial view mode |
language | string | Override language detection (openFile only) |
panelUrl | string | Custom iframe URL (bypasses panel registry) |
externalPreview | boolean | Show “Open in new tab” button in panel header |
consolePanel | boolean | Show console footer for runtime logs/errors (default: true) |
// Show only the code editor
openFile('app.js', code, { tabs: ['edit'] })
// Start in code view, allow preview and code tabs
openFile('page.html', html, { tabs: ['preview', 'code'], viewMode: 'code' })
// Load a custom panel URL in the iframe
openFile('data.csv', csvContent, {
panelUrl: 'https://my-cdn.com/csv-viewer'
})
clearArtifacts
Remove all artifacts and close the panel:
const { clearArtifacts } = useArtifactuse()
clearArtifacts()
Edit Tab
The edit tab provides an in-panel code editor powered by CodeMirror 6. It’s optional — you must provide CodeMirror modules via config to enable it.
Setup
Install the required CodeMirror packages plus any language packages you need:
# Required
npm install @codemirror/state @codemirror/view @codemirror/commands \
@codemirror/language @codemirror/autocomplete @lezer/highlight
# Language packages (add only the ones you need)
npm install @codemirror/lang-javascript @codemirror/lang-python \
@codemirror/lang-html @codemirror/lang-css @codemirror/lang-json
Supported Language Packages
| Module Key | Package | Languages |
|---|
langJavascript | @codemirror/lang-javascript | JavaScript, JSX, TypeScript, TSX |
langPython | @codemirror/lang-python | Python |
langHtml | @codemirror/lang-html | HTML |
langCss | @codemirror/lang-css | CSS |
langJson | @codemirror/lang-json | JSON |
langMarkdown | @codemirror/lang-markdown | Markdown |
langXml | @codemirror/lang-xml | XML |
langYaml | @codemirror/lang-yaml | YAML |
langSql | @codemirror/lang-sql | SQL |
langJava | @codemirror/lang-java | Java |
langCpp | @codemirror/lang-cpp | C, C++ |
langGo | @codemirror/lang-go | Go |
langRust | @codemirror/lang-rust | Rust |
langPhp | @codemirror/lang-php | PHP |
langVue | @codemirror/lang-vue | Vue SFC |
langAngular | @codemirror/lang-angular | Angular templates |
langLess | @codemirror/lang-less | Less |
langSass | @codemirror/lang-sass | Sass, SCSS |
Pass the modules in your SDK config:
<script setup>
import { provideArtifactuse } from 'artifactuse/vue'
import * as cmState from '@codemirror/state'
import * as cmView from '@codemirror/view'
import * as cmCommands from '@codemirror/commands'
import * as cmLanguage from '@codemirror/language'
import * as cmAutocomplete from '@codemirror/autocomplete'
import * as lezerHighlight from '@lezer/highlight'
// Import only the languages you need
import * as cmLangJavascript from '@codemirror/lang-javascript'
import * as cmLangPython from '@codemirror/lang-python'
import * as cmLangHtml from '@codemirror/lang-html'
import * as cmLangCss from '@codemirror/lang-css'
import * as cmLangJson from '@codemirror/lang-json'
provideArtifactuse({
theme: 'dark',
editor: {
modules: {
state: cmState,
view: cmView,
commands: cmCommands,
language: cmLanguage,
autocomplete: cmAutocomplete,
lezerHighlight: lezerHighlight,
langJavascript: cmLangJavascript,
langPython: cmLangPython,
langHtml: cmLangHtml,
langCss: cmLangCss,
langJson: cmLangJson,
},
theme: 'dark', // 'dark' | 'light' | 'auto'
},
})
</script>
import { ArtifactuseProvider } from 'artifactuse/react'
import * as cmState from '@codemirror/state'
import * as cmView from '@codemirror/view'
import * as cmCommands from '@codemirror/commands'
import * as cmLanguage from '@codemirror/language'
import * as cmAutocomplete from '@codemirror/autocomplete'
import * as lezerHighlight from '@lezer/highlight'
// Import only the languages you need
import * as cmLangJavascript from '@codemirror/lang-javascript'
import * as cmLangPython from '@codemirror/lang-python'
import * as cmLangHtml from '@codemirror/lang-html'
import * as cmLangCss from '@codemirror/lang-css'
import * as cmLangJson from '@codemirror/lang-json'
<ArtifactuseProvider config={{
theme: 'dark',
editor: {
modules: {
state: cmState,
view: cmView,
commands: cmCommands,
language: cmLanguage,
autocomplete: cmAutocomplete,
lezerHighlight: lezerHighlight,
langJavascript: cmLangJavascript,
langPython: cmLangPython,
langHtml: cmLangHtml,
langCss: cmLangCss,
langJson: cmLangJson,
},
theme: 'dark',
},
}}>
<YourApp />
</ArtifactuseProvider>
Using the Edit Tab
Once configured, include 'edit' in the tabs array:
const { openFile } = useArtifactuse()
// Open with only the edit tab
openFile('app.js', code, { tabs: ['edit'] })
// Open with all tabs including edit
openFile('page.html', html, { tabs: ['preview', 'code', 'edit'] })
Handling Saves
When the user clicks the Save button in the edit tab, an edit:save event fires:
const { on } = useArtifactuse()
on('edit:save', ({ artifactId, artifact, code }) => {
console.log('Updated code:', code)
// Send back to your AI, save to database, etc.
})
Console Output
HTML artifacts capture console.log, console.warn, console.error, console.info, and uncaught exceptions from user code. A collapsible console footer appears in the panel when entries exist, auto-expanding on errors.
The console header includes filter toggles for each log type (error, warn, info, log). Click a filter to hide/show entries of that type. Filters only appear when entries of that type exist.
Listen for console events to send errors back to your AI agent:
const { on } = useArtifactuse()
on('console:log', ({ artifactId, entry }) => {
// entry: { type: 'log'|'warn'|'error'|'info', content: string, timestamp: number, stack?: string }
if (entry.type === 'error') {
// Send error back to AI for auto-fix
}
})
Set consolePanel: false in config or per-artifact options to hide the footer UI while still receiving events.
Editor Theme
The editor theme is independent of the SDK theme and controlled via editor.theme:
| Value | Description |
|---|
'dark' | Dark background (#1e1e1e) with light text (default) |
'light' | White background with dark text |
'auto' | Follows the SDK theme setting |
Without the editor config, the edit tab button won’t appear — the feature degrades gracefully. Language modules (e.g. langJavascript, langPython, langHtml) and lezerHighlight are optional but recommended for syntax highlighting. Only include the language packages you need — languages without a matching module fall back to plain text editing.