Follow ideas, not threads.
traek is a Svelte 5 UI library for building spatial, tree-structured AI conversation interfaces.
traek (/traek/) comes from Danish trae (tree) and English track (path).
Most chat interfaces force complex thinking into a linear stream of messages. traek breaks that constraint by turning conversations into navigable structures -- paths you can branch, explore, and revisit.
Built for AI-native products where reasoning is not linear.
Classic chat layouts work well for simple back-and-forth messaging.
They fail when conversations become:
Important context gets buried. Alternative approaches disappear. Thinking becomes flattened.
If AI thinking branches -- your UI should too.
traek replaces the timeline with a spatial mental model:
This is not "chat with nicer bubbles." It is infrastructure for non-linear AI interaction.
Conversations in traek form a tree:
Message
+-- Reply
|-- Alternative path
|-- Deeper exploration
+-- Agent branch
Every message is a node. Every reply is a possible direction.
You don't scroll conversations.
You navigate them.
/Ctrl+F / Cmd+F to search message content with match highlighting? to show all keyboard shortcutsConversationStoresnapshotToJSON() and snapshotToMarkdown() for portable exports/ command dropdown in the inputNodeTypeRegistryThemeProvidercreateCustomTheme() from a base theme + accent color--traek-* variables scoped to the base layer for easy overridestranslations propInstall the package:
npm install traek
Create a spatial AI chat:
<script lang="ts">
import { TraekCanvas, TraekEngine, DEFAULT_TRACK_ENGINE_CONFIG, type MessageNode } from 'traek';
const engine = new TraekEngine(DEFAULT_TRACK_ENGINE_CONFIG);
function onSendMessage(input: string, _userNode: MessageNode) {
engine.addNode(input, 'user');
const assistantNode = engine.addNode('', 'assistant', {
autofocus: true
});
engine.updateNode(assistantNode.id, { status: 'streaming' });
// stream chunks
// engine.updateNode(assistantNode.id, { content });
// when finished
// engine.updateNode(assistantNode.id, { status: 'done' });
}
</script>
<TraekCanvas {engine} {onSendMessage} />
traek separates conversation structure from message rendering.
Core state management class. Manages the conversation tree: nodes, parent-child relationships, spatial layout (x/y coordinates), and operations like addNode(), branchFrom(), focusOnNode(), moveNode().
All data structures use Maps for O(1) lookups.
Main exported component. Renders the interactive canvas with pan/zoom, message nodes, connection lines, and streaming input. Accepts onSendMessage callback and a customizable component map for node types.
<TraekCanvas
{engine}
{onSendMessage}
translations={{ canvas: { emptyStateTitle: 'Your custom title' } }}
nodeActions={createDefaultNodeActions({ onRetry, onEditNode })}
componentMap={{ text: CustomTextNode }}
/>
You control:
traek keeps everything navigable and coherent.
All user-facing strings can be customized. Pass a partial translations object -- only override what you need:
<TraekCanvas
{engine}
{onSendMessage}
translations={{
canvas: {
emptyStateTitle: 'Starte eine Konversation',
emptyStateSubtitle: 'Schreibe eine Nachricht'
},
input: {
placeholder: 'Frag den Experten...'
},
search: {
placeholder: 'Suchen...'
}
}}
/>
The translations object is organized by feature area: canvas, input, zoom, search, keyboard, fuzzySearch, nodeActions, textNode, toast, onboarding, tour, breadcrumb, loading, toolbar, replay.
Import the types for full IntelliSense:
import type { TraekTranslations, PartialTraekTranslations } from 'traek';
import { DEFAULT_TRANSLATIONS, mergeTranslations } from 'traek';
traek ships with three built-in themes and a programmatic API:
<script lang="ts">
import { ThemeProvider, ThemePicker, darkTheme, lightTheme, createCustomTheme } from 'traek';
</script>
<ThemeProvider theme={darkTheme}>
<TraekCanvas {engine} {onSendMessage} />
<ThemePicker />
</ThemeProvider>
Or use CSS custom properties directly. All variables are scoped to the base layer:
:root {
--traek-canvas-bg: #050816;
--traek-node-bg: #0b1020;
--traek-node-active-border: #4ade80;
}
See the full list of --traek-* variables in the theming docs.
Save and load conversations with the built-in store:
import { ConversationStore, snapshotToJSON, snapshotToMarkdown, downloadFile } from 'traek';
const store = new ConversationStore();
// Save
await store.save(engine.snapshot());
// Load
const conversations = await store.list();
const snapshot = await store.load(conversations[0].id);
engine.restore(snapshot);
// Export
downloadFile('chat.json', snapshotToJSON(engine.snapshot()));
downloadFile('chat.md', snapshotToMarkdown(engine.snapshot()));
Step through conversation history:
<script lang="ts">
import { ReplayController, ReplayControls } from 'traek';
const replay = new ReplayController(engine);
</script>
<ReplayControls controller={replay} />
The traek MCP (Model Context Protocol) server gives AI assistants like Claude Code full knowledge of the traek API, guides, and code snippets. It helps you integrate traek faster by providing your AI assistant with component docs, integration guides, and ready-to-use scaffolding.
| Tool | Description |
|---|---|
get_component_api |
Full prop/method API for TraekCanvas, TraekEngine, etc. |
list_exports |
All traek exports grouped by category |
list_guides |
Available integration guides |
get_guide |
Full text of an integration guide |
search_docs |
Full-text search across all docs |
list_snippets |
Available code snippets |
get_snippet |
Runnable code snippet for a scenario |
scaffold_page |
Generate a complete SvelteKit page + API route |
Add to your .mcp.json (project root) or ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"traek": {
"type": "url",
"url": "https://mcp.gettraek.com"
}
}
}
{
"mcpServers": {
"traek": {
"command": "npx",
"args": ["-y", "@gettraek/mcp"]
}
}
}
npm install -D @gettraek/mcp
{
"mcpServers": {
"traek": {
"command": "node",
"args": ["node_modules/@gettraek/mcp/dist/index.js"]
}
}
}
Once configured, your AI assistant can query traek docs, generate integration code, and scaffold pages directly.
traek is ideal if you are building:
If you only need a simple message list -- traek is probably not the right tool.
The main traek package exports:
Components: TraekCanvas, TextNode, DefaultLoadingOverlay, FocusMode, ReplayControls, SaveIndicator, ChatList, HeaderBar, ToastContainer, Toast, ThemeProvider, ThemePicker, DesktopTour, ActionBadges, SlashCommandDropdown, TagBadges, TagDropdown, TagFilter
Engine: TraekEngine, DEFAULT_TRACK_ENGINE_CONFIG, wouldCreateCycle()
Actions: createDefaultNodeActions(), createDuplicateAction(), createDeleteAction(), createCopyBranchAction(), createRetryAction(), createEditAction(), createCompareAction(), ActionResolver
Persistence: ConversationStore, ReplayController, snapshotToJSON(), snapshotToMarkdown(), downloadFile()
Theming: darkTheme, lightTheme, highContrastTheme, createCustomTheme(), applyThemeToRoot()
i18n: DEFAULT_TRANSLATIONS, setTraekI18n(), getTraekI18n(), mergeTranslations()
Node Types: NodeTypeRegistry, textNodeDefinition, thoughtNodeDefinition
Tags: PREDEFINED_TAGS, getNodeTags(), getTagConfig(), matchesTagFilter()
Validation: Zod schemas for snapshots, configs, node types, and actions
traek is under active development and evolving quickly.
Feedback, ideas, and contributions are welcome.
AI conversations are not linear. Stop designing them that way.
traek helps you build interfaces that think the way AI does.
MIT