Skip to content

Custom Node Types

Custom node components receive node, engine, and isActive props (type these with the exported TraekNodeComponentProps):

MyCustomNode.svelte
<script lang="ts">
import type { TraekNodeComponentProps } from 'traek'
let { node, engine, isActive }: TraekNodeComponentProps = $props()
</script>
<div class="custom-node" class:active={isActive}>
<p>{node.data ? JSON.stringify(node.data) : node.id}</p>
</div>

Pass a componentMap that maps node.type strings to components. Built-in types are lowercase ('text', 'thought'); you can also invent your own type strings:

<script>
import { TraekCanvas, TraekEngine } from 'traek'
import MyCustomNode from './MyCustomNode.svelte'
const engine = new TraekEngine()
const componentMap = {
myCustomType: MyCustomNode
}
function handleSend(input, userNode) {
// Create a node rendered by MyCustomNode
engine.addNode('', 'assistant', {
type: 'myCustomType',
parentIds: [userNode.id],
data: { answer: 42 }
})
}
</script>
<TraekCanvas {engine} {componentMap} onSendMessage={handleSend} />

To replace the default text renderer, map the 'text' type: { text: MyCustomNode }.

For a single ad-hoc node you can skip the map and pass a component directly:

import MyCustomNode from './MyCustomNode.svelte'
engine.addCustomNode(MyCustomNode, { someProp: 'value' }, 'assistant', {
parentIds: [parent.id]
})