はじめに
Constela は「コンパイラファースト」のプログラミング言語です。JavaScript/TypeScriptを書かずに、JSONだけでUIを定義できます。コンパイラが検証・最適化してからブラウザで実行します。
今回の v0.8.0 では、AI時代のUI開発を見据えた大幅なアップデートを行いました。この記事では、新しく追加された5つの機能を紹介します。
1. 「Did you mean?」エラー提案
タイポをしたとき、Constelaが正しい名前を提案してくれるようになりました。
Error [UNDEFINED_STATE] at /view/children/0/value/name
Undefined state reference: 'count'
Did you mean 'counter'?
Levenshtein距離を使って類似名を検出しています。AIがコードを生成する際にも、コンパイル時のエラーからの修正が容易になります。
2. Style System - CVAライクなスタイル管理
Tailwind CSSユーザーにはおなじみの CVA (Class Variance Authority) に似たスタイルシステムを導入しました。
スタイルプリセットの定義
{
"styles": {
"button": {
"base": "px-4 py-2 rounded font-medium transition-colors",
"variants": {
"variant": {
"primary": "bg-blue-500 text-white hover:bg-blue-600",
"secondary": "bg-gray-200 text-gray-800 hover:bg-gray-300",
"ghost": "bg-transparent hover:bg-gray-100"
},
"size": {
"sm": "text-sm h-8",
"md": "text-base h-10",
"lg": "text-lg h-12"
}
},
"defaultVariants": {
"variant": "primary",
"size": "md"
}
}
}
}
スタイルの参照
{
"kind": "element",
"tag": "button",
"props": {
"className": {
"expr": "style",
"name": "button",
"variants": {
"variant": { "expr": "state", "name": "buttonVariant" },
"size": { "expr": "lit", "value": "lg" }
}
}
},
"children": [
{ "kind": "text", "value": { "expr": "lit", "value": "Click me" } }
]
}
ポイント:
- バリアントを state で動的に切り替え可能
- コンパイル時に未定義のスタイル・バリアントを検出
- 既存の Tailwind CSS クラスとそのまま使える
3. @constela/builder - TypeScriptでも書ける
「JSONを直接書くのはちょっと…」という方向けに、TypeScriptで書けるBuilder APIも用意しました。
カウンターアプリの例
import {
createProgram, numberField, action, increment,
button, text, state, onClick
} from '@constela/builder';
const counter = createProgram({
state: { count: numberField(0) },
actions: [action('increment', [increment('count')])],
view: button({ onClick: onClick('increment') }, [text(state('count'))])
});
40以上のビルダー関数
DSLのすべての要素をカバーしています:
| カテゴリ | 関数 |
|---|---|
| Expression |
lit, state, variable, bin, cond, get, add, eq, and, or など |
| State |
numberField, stringField, booleanField, listField, objectField
|
| Action |
action, set, update, increment, push, fetch, navigate など |
| View |
element, div, button, text, ifNode, each, component, slot
|
| Event |
onClick, onInput, onChange, onSubmit
|
JSONと同じメリットを享受
TypeScriptで書いても、最終的にはJSONに変換されます。つまり:
- コンパイル時エラー検出 - 未定義のstateやactionを参照していたらエラー
- 「Did you mean?」提案 - タイポしても正しい名前を教えてくれる
-
構造化されたエラー出力 -
--jsonフラグでAI連携もそのまま可能
4. CLI の大幅強化
validate コマンド
コンパイルせずに高速バリデーションできます。
# 単一ファイル
constela validate app.json
# ディレクトリ全体
constela validate --all src/routes/
inspect コマンド
プログラムの構造を可視化できます。
$ constela inspect app.json
State (2 fields):
count: number = 0
items: list = []
Actions (2):
increment: update count +1
addItem: push to items
View Tree:
element<div>
text: state.count
element<button> onClick=increment
新しいフラグ
| フラグ | 説明 |
|---|---|
--json |
JSON出力(AIツール連携向け) |
--watch |
ファイル監視して自動再コンパイル |
--verbose |
各パスのタイミング表示 |
--debug |
内部デバッグ情報 |
--watch で開発効率アップ
constela compile app.json --watch
ファイルを保存するたびに自動でコンパイルされます。
--verbose で詳細表示
$ constela compile app.json --verbose
[1/3] Validating schema... OK (2ms)
[2/3] Analyzing semantics... OK (1ms)
[3/3] Transforming AST... OK (0ms)
Summary:
States: 2
Actions: 3
View nodes: 12
Compilation successful (5ms total)
5. AI/LLM連携のための設計
今回の更新は「AIがUIを生成する時代」を見据えています。
| 機能 | AIにとってのメリット |
|---|---|
--json 出力 |
構造化されたエラー情報を受け取れる |
| エラー提案 | 修正箇所を特定しやすい |
| Style System | 一貫したスタイル定義を再利用 |
| JSON DSL | AIが生成しやすいフォーマット |
例えば、LLMが生成したJSONにエラーがあった場合:
$ constela compile app.json --json
{
"success": false,
"errors": [{
"code": "UNDEFINED_STATE",
"message": "Undefined state reference: 'count'",
"path": "/view/children/0/value/name",
"suggestion": "Did you mean 'counter'?",
"context": { "availableNames": ["counter", "items"] }
}],
"diagnostics": { "duration": 5 }
}
この情報をLLMにフィードバックすれば、自動で修正できます。
完全なTodoリストの例
JSONだけで完全なTodoリストアプリが作れます:
{
"version": "1.0",
"styles": {
"todoItem": {
"base": "flex items-center gap-2 p-2",
"variants": {
"done": {
"true": "opacity-50 line-through",
"false": ""
}
}
}
},
"state": {
"todos": { "type": "list", "initial": [] },
"newTodo": { "type": "string", "initial": "" }
},
"actions": [
{
"name": "setNewTodo",
"steps": [
{ "do": "set", "target": "newTodo", "value": { "expr": "var", "name": "value" } }
]
},
{
"name": "addTodo",
"steps": [
{
"do": "update",
"target": "todos",
"operation": "push",
"value": {
"expr": "lit",
"value": { "text": "", "done": false }
}
},
{ "do": "set", "target": "newTodo", "value": { "expr": "lit", "value": "" } }
]
},
{
"name": "toggleTodo",
"steps": [
{
"do": "update",
"target": "todos",
"operation": "replaceAt",
"index": { "expr": "var", "name": "index" },
"value": { "expr": "var", "name": "updated" }
}
]
}
],
"view": {
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "p-4 max-w-md mx-auto" } },
"children": [
{
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "flex gap-2 mb-4" } },
"children": [
{
"kind": "element",
"tag": "input",
"props": {
"type": { "expr": "lit", "value": "text" },
"value": { "expr": "state", "name": "newTodo" },
"placeholder": { "expr": "lit", "value": "Add a todo..." },
"className": { "expr": "lit", "value": "flex-1 border rounded px-2 py-1" },
"onInput": { "event": "input", "action": "setNewTodo", "payload": { "expr": "var", "name": "value" } }
}
},
{
"kind": "element",
"tag": "button",
"props": {
"className": { "expr": "style", "name": "button" },
"onClick": { "event": "click", "action": "addTodo" }
},
"children": [
{ "kind": "text", "value": { "expr": "lit", "value": "Add" } }
]
}
]
},
{
"kind": "each",
"items": { "expr": "state", "name": "todos" },
"as": "todo",
"index": "i",
"body": {
"kind": "element",
"tag": "div",
"props": {
"className": {
"expr": "style",
"name": "todoItem",
"variants": {
"done": { "expr": "get", "base": { "expr": "var", "name": "todo" }, "path": "done" }
}
}
},
"children": [
{ "kind": "text", "value": { "expr": "get", "base": { "expr": "var", "name": "todo" }, "path": "text" } }
]
}
}
]
}
}
JavaScript/TypeScriptは一切書いていません。 JSONだけで状態管理、イベント処理、条件付きスタイリングがすべて実現できます。
インストール
npm install @constela/start
まとめ
Constela v0.8.0 では以下の機能を追加しました:
- エラー提案 - 「Did you mean?」で修正を容易に
- Style System - CVAライクなバリアント管理
- Builder API - AIツール向けのTypeScript API
- CLI強化 - validate, inspect, --json, --watch, --verbose, --debug
- AI連携 - 構造化エラー出力
JSONだけでUIを書く新しいアプローチに興味があれば、ぜひ試してみてください。
リンク: