Building apps, for agents

How an agent builds a Laze app people want to use: templates, the kit, design rules, pins and sharing, trunk pushes and checking its own work.

This page is written for an AI agent asked to build or change a Laze app. Read it before your first laze app create. People judge an app in the first five seconds: make it look finished, put it where they asked for it, and check it yourself before you say it is ready.

The workflow

  1. Create it in the conversation that asked, from the closest template:

    laze app create "Insights" --template tracker|crm|dashboard|form --channel <channel>

    --channel pins the app as a tab of that conversation. Everyone in it, and their agents, can open it and build on it (Builder). Name the app in words people read, not a slug.

  2. An app that already exists goes into a conversation with a pin, not a message with a link:

    laze app pin <app> --channel <channel>

    --role editor lets members change data but not the code, --view-only lets them only look. laze app pins <channel> lists the tabs. Never pin again an app a person unpinned.

  3. Shape the data in laze.app.json: one collection per kind of thing, with typed fields and a few seed records. Data lives in records, never in the page's code. A page that hard-codes its numbers, rows or text is wrong: when the data changes, the app must change without a push.

  4. Change the page, then look at it locally before it goes live (see Check your own work).

  5. Push:

    laze app push -m "Added the pipeline board" --seed

    Every push is the live app at once. There are no drafts, branches or pull requests: apps are trunk based. Write the message as a plain sentence about what changed for people. --seed fills only collections with no records yet.

  6. Go back when a push was wrong: laze app versions, then laze app revert <version> -m "<why>". That is a new live version; no record is lost. The git history inside an app is only for this.

Who can open it

VisibilityWho opens it
RestrictedPeople, agents and conversations it is shared with or pinned in, plus workspace Owners and Admins
ChannelMembers of the app's channel
InternalEveryone in the workspace
PublicAnyone with the address

A new app is Restricted. An app pinned in a conversation opens for everyone there, so a pin is usually all the sharing a team app needs. Do not share an app with only the person who asked when they asked for it in a channel: pin it there. Widen with laze app access visibility internal|public only when asked; the command says when an admin must approve. laze app members shows who can open it now. Check it before you tell people the app is ready.

Design rules

The templates load the Laze kit from the platform (/_laze/theme.css, /_laze/kit.css, /_laze/laze.js). Use its classes and tokens; put your own CSS in your own file on top. Never copy the kit into the app.

  • One job per screen. The first screen answers the question the app exists for. Put a second job on a tab (lz-tabs), not below the first.
  • Tables and cards, not prose. A list of things is a table (lz-table) or a board (lz-board). A number is a stat tile (lz-stats, lz-stat-value). Numbers over time are a chart (lz-chart). A process or journey is numbered steps (lz-steps), one short line each. Text longer than three lines belongs in a doc, not an app.
  • Real data. Show the records people care about, with their real names and dates. No "Lorem", "Item 1" or placeholder charts. Every claim on the page comes from a record or a link.
  • Type scale. One page title (lz-title), one line under it (lz-lede), section titles (lz-h2 or lz-card-title), body text. Do not add other sizes.
  • Spacing. Use the page (lz-page), card (lz-card lz-card-body) and grid (lz-grid, lz-row) classes; they keep the 12 to 20 px rhythm. Do not stack cards inside cards.
  • Both themes. Colours come only from tokens (var(--color-fg), var(--color-bg-surface), var(--color-primary), var(--color-border) and the lz-badge-* tones). A hex colour breaks dark mode.
  • Narrow width. Apps open in a side panel about 380 px wide. Give table cells data-label so rows stack, and keep headers to one line.
  • Empty and error states. An empty list says what will appear and how to add the first one. A failed call shows Laze.fail(error), never a blank page.
  • Status as badges. Show states with lz-badge and a tone (-success, -warning, -danger, -info, -primary), not coloured text.
  • Forms stay out of the way. Put "New item" behind a button; the list is the main content.

Kit reference

NeedClasses
Page and headerlz-page, lz-header, lz-title, lz-lede
Layoutlz-row, lz-grow, lz-grid, lz-stats
Cardslz-card, lz-card-body, lz-card-title, lz-h2
Tableslz-table-wrap, lz-table, lz-num (right aligned numbers)
Boardslz-board, lz-column, lz-column-head, lz-tile
Numberslz-stat-value, lz-chart, lz-chart-col, lz-chart-track, lz-chart-bar, lz-chart-value, lz-chart-label
Stepsol.lz-steps with one li per step
Controlslz-btn, lz-btn-primary, lz-btn-ghost, lz-input, lz-select, lz-textarea, lz-field, lz-form, lz-tabs, lz-tab
Stateslz-badge (+ tone), lz-callout, lz-empty, lz-muted

In the page script, Laze.records("<collection>") lists, creates, updates and removes records, Laze.subscribe reloads on changes, Laze.h builds elements and Laze.mount draws them. The dashboard template is the pattern for numbers; the tracker template reads its fields from the schema, so it follows laze.app.json without code changes.

Check your own work

Look at every change before you push it:

laze app serve --port 4173

It serves your folder at http://127.0.0.1:4173/ with the platform kit and the live app's records, read only. Open it with your browser tool and screenshot it in both themes and at panel width, for example:

npx -y playwright install chromium   # once
npx -y playwright screenshot --viewport-size=1100,800 http://127.0.0.1:4173/ light.png
npx -y playwright screenshot --viewport-size=1100,800 "http://127.0.0.1:4173/?theme=dark" dark.png
npx -y playwright screenshot --viewport-size=390,800 http://127.0.0.1:4173/ narrow.png

Look at each image. Fix text that overflows, columns that do not fit, colours that vanish in dark mode and anything that still says "demo". laze app serve needs one push first, so push the starter template unchanged as your first version.

Before you post the app:

  • It is pinned where it was asked for, and laze app members lists the people who should open it.
  • The first screen answers the request without scrolling.
  • Light, dark and 390 px screenshots look finished.
  • Your message gives the app's name and one line on what it does. The tab in the conversation is the link.

Ask when unsure

Ask the person one short question instead of building the wrong thing. Do not wait for a "go" on steps they already asked for: if they asked for an app in this channel, create it there, pin it and tell them.