実装

10行で最初の画面を出す

著者: makemind · 2026年1月9日

待合室の番号板を作る。大きな数字ひとつ、待ち人数の一行、ボタン二つ。

これを作るのに普通は何が要るか。プロジェクトを作り、ウィジェットツリーを組み、ビルドし、パネルにインストールする。数字を大きくしたければ、その四段をもう一周する。

ここでは 画面がサーバーにあるファイル一枚だ。 接続すればそのファイルが来る。

画面

これで全部だ。

{ "type": "page", "title": "Front Desk",
  "content": { "type": "center",
    "child": { "type": "linear", "direction": "vertical", "spacing": 16, "alignment": "center", "children": [
      { "type": "text", "text": "NOW SERVING", "style": { "fontSize": 18, "letterSpacing": 4, "color": "#6b7280" } },
      { "type": "text", "text": "{{now}}", "style": { "fontSize": 96, "fontWeight": "bold", "color": "#111827" } },
      { "type": "text", "text": "{{waiting}} waiting · issued {{issued}}", "style": { "fontSize": 20, "color": "#6b7280" } },
      { "type": "linear", "direction": "horizontal", "spacing": 12, "children": [
        { "type": "button", "label": "Call next", "onTap": { "type": "tool", "tool": "queue.next" } },
        { "type": "button", "label": "Take a ticket", "onTap": { "type": "tool", "tool": "queue.take" } } ] } ] } } }

題は十行と付けたが、実際には 九行、848 バイトで終わった。

{{now}} のところに番号が入る。ボタンの onTap は道具の名を呼ぶ — この記事ではまだ押しても何も起きない。それは次の記事だ。

その九行はサーバーにある

サーバー側のコードはこれだけだ。

server.addResource(
  uri: 'ui://app',
  name: 'Front Desk screen',
  description: 'The screen definition, served as a file',
  mimeType: 'application/json',
  handler: (uri, params) async => ReadResourceResult(contents: [
    ResourceContentInfo(
      uri: 'ui://app',
      mimeType: 'application/json',
      text: File(_screenPath).readAsStringSync(),
    )
  ]),
);

毎回ファイルを読み直している。 起動時に一度読んでメモリに持てば速いが、そうすると画面を直すたびにサーバーを再起動しなければならず、その瞬間このサンプルの主張 — ファイルを直せば別のアプリになる — が嘘になる。

/// Read fresh on every request, deliberately. A screen cached at boot is a
/// screen you have to restart the server to change, and then the thing this
/// sample claims — edit the file, get a new app — stops being true.

このコンテンツは開発者以上が必要です

サインインしてプランをアップグレードすると続きを読めます。

プランを見る
Twitter