Skip to main content

Overview

Code artifacts render syntax-highlighted code with live preview and execution.

Supported Languages

Code Previews

LanguageCode BlockFeatures
HTML```htmlLive preview in iframe
React/JSX```jsxLive component preview
Vue```vueSFC with preview
JSON```jsonTree view, formatting
SVG```svgLive preview
CSV```csvSpreadsheet viewer
TSV```tsvSpreadsheet viewer
Smart Diff```smartdiffLanguage-aware side-by-side diff

Code Runtime

LanguageCode BlockFeatures
JavaScript```javascriptExecution, console output
Python```pythonPyodide 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.
FieldTypeDescription
oldCodestringOriginal code
newCodestringUpdated code
languagestringLanguage 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:
OptionTypeDescription
titlestringDisplay title (defaults to filename for openFile)
tabsstring[]Visible tabs: 'preview', 'code', 'split', 'edit'
viewModestringInitial view mode
languagestringOverride language detection (openFile only)
panelUrlstringCustom iframe URL (bypasses panel registry)
externalPreviewbooleanShow “Open in new tab” button in panel header
consolePanelbooleanShow 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 KeyPackageLanguages
langJavascript@codemirror/lang-javascriptJavaScript, JSX, TypeScript, TSX
langPython@codemirror/lang-pythonPython
langHtml@codemirror/lang-htmlHTML
langCss@codemirror/lang-cssCSS
langJson@codemirror/lang-jsonJSON
langMarkdown@codemirror/lang-markdownMarkdown
langXml@codemirror/lang-xmlXML
langYaml@codemirror/lang-yamlYAML
langSql@codemirror/lang-sqlSQL
langJava@codemirror/lang-javaJava
langCpp@codemirror/lang-cppC, C++
langGo@codemirror/lang-goGo
langRust@codemirror/lang-rustRust
langPhp@codemirror/lang-phpPHP
langVue@codemirror/lang-vueVue SFC
langAngular@codemirror/lang-angularAngular templates
langLess@codemirror/lang-lessLess
langSass@codemirror/lang-sassSass, 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>

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:
ValueDescription
'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.