0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Constela v0.8.0: AI時代のUI開発を加速する5つの新機能

Last updated at Posted at 2026-01-13

はじめに

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 では以下の機能を追加しました:

  1. エラー提案 - 「Did you mean?」で修正を容易に
  2. Style System - CVAライクなバリアント管理
  3. Builder API - AIツール向けのTypeScript API
  4. CLI強化 - validate, inspect, --json, --watch, --verbose, --debug
  5. AI連携 - 構造化エラー出力

JSONだけでUIを書く新しいアプローチに興味があれば、ぜひ試してみてください。

リンク:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?