Examples
Real-world examples of Grain in action.
Basic Chat
html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="chat"></div>
<script src="https://cdn.jsdelivr.net/npm/@grain.sh/web@latest/dist/index.global.js"></script>
<script>
const adapter = new GrainWeb.WebAdapter();
adapter.render(`<message role="assistant">
<stream>Hello! How can I help?</stream>
</message>`, {
container: document.getElementById('chat')
});
</script>
</body>
</html>With Tool Call
javascript
adapter.render(`<tool name="search" args='{"q": "weather"}' status="running" />`);
setTimeout(() => {
adapter.render(`<tool name="search" status="complete">
<result temperature="28" condition="sunny" />
</tool>`, { container: '#tool-result' });
}, 1500);This pattern is useful when you want to stream intent first, then append structured completion output such as <result> or <warning> after the tool finishes.
Interactive Chat
javascript
const chat = document.getElementById('chat');
function addMessage(role, content) {
adapter.render(`<message role="${role}">
<stream>${content}</stream>
</message>`, {
container: chat,
position: 'append'
});
}
adapter.on('action', (e) => {
if (e.action === 'regenerate') {
// Handle regenerate
}
});Because Grain is declarative, the same interaction can later be rendered in another surface, such as the CLI, without redesigning the document structure.
Custom Theme
javascript
const adapter = new WebAdapter({
theme: {
'--grain-primary': '#6366f1',
'--grain-secondary': '#8b5cf6',
'--grain-background': '#0f0f0f',
'--grain-surface': '#1a1a1a',
'--grain-radius': '12px'
}
});Next Moves
- Use Quick Start to scaffold a minimal integration.
- Use Playground to verify snippets against the current parser and renderer.
- Use API Reference when you need programmatic control instead of copy-paste examples.