Yuuichi EguchiIntroduction We're excited to announce new features for Constela, with 7 major new...
We're excited to announce new features for Constela, with 7 major new capabilities that significantly improve performance and developer experience:
We've introduced a CSS variable-based theme system with support for light/dark/system modes and shadcn/ui-compatible color tokens.
{
"theme": {
"mode": "system",
"colors": {
"primary": "hsl(220 90% 56%)",
"primary-foreground": "hsl(0 0% 100%)",
"background": "hsl(0 0% 100%)",
"foreground": "hsl(222 47% 11%)",
"muted": "hsl(210 40% 96%)",
"border": "hsl(214 32% 91%)"
},
"darkColors": {
"background": "hsl(222 47% 11%)",
"foreground": "hsl(210 40% 98%)",
"muted": "hsl(217 33% 17%)",
"border": "hsl(217 33% 17%)"
},
"fonts": {
"sans": "Inter, system-ui, sans-serif",
"mono": "JetBrains Mono, monospace"
},
"cssPrefix": "app"
}
}
prefers-color-scheme detection--app-primary to :root
dark class on document.documentElement
We've implemented Islands Architecture for partial hydration. Choose from 6 hydration strategies to drastically reduce your initial JS bundle.
{
"kind": "island",
"id": "interactive-chart",
"strategy": "visible",
"strategyOptions": {
"threshold": 0.5,
"rootMargin": "100px"
},
"content": {
"kind": "component",
"name": "Chart",
"props": { "data": { "expr": "state", "name": "chartData" } }
},
"state": {
"chartData": { "type": "list", "initial": [] }
},
"actions": [
{
"name": "loadData",
"steps": [
{ "do": "fetch", "url": { "expr": "lit", "value": "/api/chart-data" }, "result": "data", "onSuccess": [
{ "do": "set", "target": "chartData", "value": { "expr": "var", "name": "data" } }
]}
]
}
]
}
| Strategy | Description | Use Case |
|---|---|---|
load |
Hydrate immediately on page load | Critical interactive elements |
idle |
Hydrate when browser is idle | Non-urgent interactions |
visible |
Hydrate when element enters viewport | Below-the-fold content |
interaction |
Hydrate on first user interaction | Lazy-loaded widgets |
media |
Hydrate when media query matches | Responsive components |
never |
Never hydrate | Static content only |
Islands are automatically code-split:
dist/
_islands/
interactive-chart.js # Island-specific bundle
sidebar-menu.js
client.js # Main bundle
We've added SSE (Server-Sent Events) connections, optimistic updates, and state binding.
{
"do": "sseConnect",
"connection": "notifications",
"url": { "expr": "lit", "value": "/api/events" },
"eventTypes": ["message", "update"],
"reconnect": {
"enabled": true,
"strategy": "exponential",
"maxRetries": 5,
"baseDelay": 1000
},
"onMessage": [
{ "do": "update", "target": "messages", "operation": "push", "value": { "expr": "var", "name": "payload" } }
]
}
Update UI immediately with automatic rollback on server error:
{
"name": "likePost",
"steps": [
{
"do": "optimistic",
"target": "posts",
"path": { "expr": "var", "name": "index" },
"value": { "expr": "lit", "value": { "liked": true } },
"result": "updateId",
"timeout": 5000
},
{
"do": "fetch",
"url": { "expr": "concat", "items": [
{ "expr": "lit", "value": "/api/posts/" },
{ "expr": "var", "name": "postId" },
{ "expr": "lit", "value": "/like" }
]},
"method": "POST",
"onSuccess": [
{ "do": "confirm", "id": { "expr": "var", "name": "updateId" } }
],
"onError": [
{ "do": "reject", "id": { "expr": "var", "name": "updateId" } }
]
}
]
}
We've implemented ReadableStream-based streaming SSR with Edge Runtime support for significantly reduced TTFB. Just enable it in your config - no TypeScript required.
{
"streaming": {
"enabled": true,
"flushStrategy": "batched"
}
}
| Strategy | Description |
|---|---|
immediate |
Flush each chunk immediately |
batched |
Batch flush at 1KB threshold (default) |
manual |
Flush only at the end (small pages) |
Use suspense nodes for async content with loading states:
{
"kind": "suspense",
"id": "user-profile",
"fallback": {
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "skeleton" } }
},
"content": {
"kind": "component",
"name": "UserProfile"
}
}
The server renders the fallback immediately, then streams the actual content when ready - all configured declaratively in JSON.
{
"kind": "component",
"name": "DatePicker",
"props": {
"value": { "expr": "state", "name": "selectedDate" },
"onChange": { "event": "change", "action": "updateDate" },
"format": { "expr": "lit", "value": "yyyy-MM-dd" },
"locale": { "expr": "lit", "value": "en-US" }
}
}
{
"kind": "component",
"name": "Tree",
"props": {
"items": { "expr": "state", "name": "treeData" },
"onSelect": { "event": "select", "action": "handleSelect" },
"expandedKeys": { "expr": "state", "name": "expanded" }
}
}
Full-featured table with sorting, filtering, and pagination:
{
"kind": "component",
"name": "DataTable",
"props": {
"data": { "expr": "state", "name": "users" },
"columns": { "expr": "lit", "value": [
{ "key": "name", "title": "Name", "sortable": true },
{ "key": "email", "title": "Email", "filterable": true },
{ "key": "status", "title": "Status" }
]},
"pageSize": { "expr": "lit", "value": 10 },
"sortable": { "expr": "lit", "value": true },
"filterable": { "expr": "lit", "value": true }
}
}
{
"kind": "component",
"name": "VirtualScroll",
"props": {
"items": { "expr": "state", "name": "largeList" },
"itemHeight": { "expr": "lit", "value": 50 },
"containerHeight": { "expr": "lit", "value": 400 },
"overscan": { "expr": "lit", "value": 5 }
}
}
{
"kind": "component",
"name": "BarChart",
"props": {
"data": { "expr": "state", "name": "chartData" },
"valueKey": { "expr": "lit", "value": "value" },
"labelKey": { "expr": "lit", "value": "label" },
"showGrid": { "expr": "lit", "value": true }
}
}
Supported chart types: bar, line, pie, donut, area, radar, scatter
This update brings significant enhancements for modern web application development:
Try it out today!