What is Constela?
Constela is a compiler-first UI framework where you describe UI behavior as JSON instead of JavaScript. No JSX, no hooks, no JavaScript in your components.
{
"version": "1.0",
"state": {
"count": { "type": "number", "initial": 0 }
},
"actions": [
{
"name": "increment",
"steps": [{ "do": "update", "target": "count", "operation": "increment" }]
}
],
"view": {
"kind": "element",
"tag": "button",
"props": { "onClick": { "event": "click", "action": "increment" } },
"children": [{ "kind": "text", "value": { "expr": "state", "name": "count" } }]
}
}
The JSON is validated, analyzed, and compiled into minimal runtime code. We added Hot Module Replacement (HMR) to make the development experience even better.
The Problem: Full Reloads Are Painful
Before HMR, every time you saved a JSON file:
- The entire page reloaded
- Form inputs were cleared
- Counter values reset to initial
- Scroll position jumped to top
When you're tweaking styles or adjusting text, re-entering test data over and over is frustrating.
The Solution: Edit JSON, Keep Your State
With HMR, you edit JSON and save. That's it. The browser updates instantly while preserving your application state.
| Before HMR | After HMR |
|---|---|
| ~500ms (full reload) | ~50ms (hot update) |
| State lost | State preserved |
| Scroll position lost | Scroll preserved |
| Form inputs cleared | Form inputs kept |
How to Use It
No configuration required. Just start the dev server:
npx constela dev
You'll see:
[Constela] Dev server started at http://localhost:3000
[Constela] HMR server started at ws://localhost:24678
Now edit any JSON file and save. Changes appear instantly.
Real-World Examples
Example 1: Updating Button Text
You have a counter at 10. You want to change the button label.
Before:
{
"children": [
{ "kind": "text", "value": { "expr": "lit", "value": "Count: " } },
{ "kind": "text", "value": { "expr": "state", "name": "count" } }
]
}
After:
{
"children": [
{ "kind": "text", "value": { "expr": "lit", "value": "Clicks: " } },
{ "kind": "text", "value": { "expr": "state", "name": "count" } }
]
}
Save the file. The button now shows "Clicks: 10". The count wasn't reset.
Example 2: Adding New State
You can add new state fields without losing existing values.
Before:
{
"state": {
"count": { "type": "number", "initial": 0 }
}
}
After:
{
"state": {
"count": { "type": "number", "initial": 0 },
"message": { "type": "string", "initial": "Hello!" }
}
}
The count value is preserved. The new message field gets its initial value.
Example 3: Changing State Types
What if you change a field's type?
{
"state": {
"count": { "type": "string", "initial": "" }
}
}
Constela detects the type mismatch and shows a warning:
[HMR] Type mismatch for state 'count': number -> string. Using new initial value.
The old number value can't be used as a string, so the new initial value is used instead. This prevents bugs from incompatible types.
Error Handling
If you make a mistake in your JSON, Constela shows a clear error overlay:
┌────────────────────────────────────────────┐
│ Compilation Error │
│ │
│ /src/routes/index.json │
│ │
│ ┌────────────────────────────────────┐ │
│ │ UNDEFINED_STATE │ │
│ │ Undefined state reference: 'cont' │ │
│ │ at view.children[0].value.name │ │
│ │ │ │
│ │ Did you mean 'count'? │ │
│ └────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────┘
The overlay shows:
- File path: Which file has the error
-
Error code:
UNDEFINED_STATE,SCHEMA_INVALID, etc. - Error message: What went wrong
- JSON path: Where in the JSON structure
- Suggestion: "Did you mean 'count'?" when applicable
Fix the error and save. The overlay disappears and your app is back.
How It Works (Brief Overview)
Under the hood, HMR uses a WebSocket connection between the dev server and browser:
- File watcher detects changes to JSON files
- Server recompiles the JSON to a program
- WebSocket sends the new program to the browser
- Browser saves current state, swaps in new program, restores state
The key insight: since Constela programs are pure JSON with explicit state declarations, we can safely serialize and restore state across updates.
What Triggers HMR
HMR works for:
- Route JSON files (
src/routes/**/*.json) - Component JSON files
- Layout JSON files (
src/layouts/**/*.json)
These require a full reload:
- TypeScript files (API routes, middleware)
- Configuration files
- Adding new route files
Summary
Constela brings HMR that just works:
-
Zero config:
npx constela devand you're done - State preserved: Form inputs, counters, scroll positions survive updates
- Instant feedback: Changes appear in ~50ms
- Clear errors: Overlay shows exactly what's wrong and how to fix it
- Auto-reconnect: Connection loss is handled gracefully
The philosophy of Constela is "build websites with JSON, not JavaScript". HMR makes that workflow even smoother.
Top comments (0)