programmati.ca Open Studio

Examples · Office suite

An office workspace: 12 lines of AppSPEC

A three-screen office suite with a rich document editor, a full-span recalculating spreadsheet and a presentation workspace, plus local persistence and CSV export.

Running live in the sandbox with fixed demo data. Anything you add is saved in this browser; nothing leaves your device.

The state graph

3 screens, 0 wires

Screens are nodes and WIRE labels are edges. Screens in blue appear in the navigation; orange edges write a record on the way.

documentspreadsheetpresentation

How it works

Walking through the spec

01Screens are states

3 screens, each a <STATE>. document, spreadsheet, presentation appear in the navigation because they carry a NAV label. Children lay themselves out by containment: ROW, COL and GRID arrange them, and everything else stacks.

<STATE ID="document" NAV="Document" ICON="file-text">
…
<STATE ID="spreadsheet" NAV="Spreadsheet" ICON="table-2">
…
<STATE ID="presentation" NAV="Presentation" ICON="presentation">

02Screens connect by label

This app needs no <WIRE>: navigation comes from NAV labels, and its buttons call component actions directly, such as player.play({id}) or paint.keep(sketches).

03Data flows through the key-value pipe

Every input publishes its value into the pipe under its ID, and every screen can read the pipe with {placeholders}. The pipe drives filtering and display; no wire writes a record.

04One attribute sets the look

THEME="paper-indigo" sets every colour, radius and typeface. Change the word and the whole app restyles; all 31 themes work with every component.

<APP ID="meridian-office" NAME="Meridian Office" THEME="paper-indigo" LAYOUT="desktop">

Convention over configuration

What the engine infers

Every attribute this spec leaves out has a default inferred from names, data and context. These are the ones this app relies on; writing any of them out would override it.

    What this would typically take

    The pieces a conventional stack needs

    A typical implementation of the same app assembles these parts, each with its own code, libraries and configuration. The size depends on the team and the tools, so we do not quote a number for it.

    Here the same app is one 12-line document built from general-purpose components: DOCUMENT-EDITOR, PRESENTATION, SPREADSHEET.

    Document editingA writing surface, shared formatting toolbar and saved local content.
    SpreadsheetCell navigation, formulas, formatting and CSV export.
    PresentationSlide creation, editing and presentation mode.
    Build toolingDesktop menus, persistent state and responsive workspace layouts.
    The full specmeridian-office.appspec · 12 lines
    The same spec with every inferred attribute written out (20 lines)
    <?xml version="1.0" encoding="UTF-8"?>
    <APP ID="meridian-office" NAME="Meridian Office" THEME="paper-indigo" LAYOUT="desktop">
      <STATE ID="document" NAV="Document" ICON="file-text">
        <DOCUMENT-EDITOR ID="field-notes" TITLE="Field notes" VALUE="Field research &amp; production notes&#10;&#10;Objective&#10;Document the decisions, open questions and evidence behind the next production milestone.&#10;&#10;Working plan&#10;Review the research brief, prototype the riskiest workflow and verify the result with a real browser journey.&#10;&#10;Next checkpoint&#10;Thursday at 10:30 — bring the annotated outline and the updated budget." />
      </STATE>
      <STATE ID="spreadsheet" NAV="Spreadsheet" ICON="table-2">
        <SPREADSHEET ID="production-budget-v2" TITLE="Production budget" ROWS="50" COLS="12" VALUE="{&quot;A1&quot;:&quot;Item&quot;,&quot;B1&quot;:&quot;Quantity&quot;,&quot;C1&quot;:&quot;Unit cost&quot;,&quot;D1&quot;:&quot;Total&quot;,&quot;A2&quot;:&quot;Studio&quot;,&quot;B2&quot;:&quot;2&quot;,&quot;C2&quot;:&quot;450&quot;,&quot;D2&quot;:&quot;=B2*C2&quot;,&quot;A3&quot;:&quot;Edit&quot;,&quot;B3&quot;:&quot;3&quot;,&quot;C3&quot;:&quot;180&quot;,&quot;D3&quot;:&quot;=B3*C3&quot;,&quot;A4&quot;:&quot;Mix&quot;,&quot;B4&quot;:&quot;1&quot;,&quot;C4&quot;:&quot;240&quot;,&quot;D4&quot;:&quot;=B4*C4&quot;,&quot;A5&quot;:&quot;Total&quot;,&quot;D5&quot;:&quot;=SUM(D2:D4)&quot;}" />
      </STATE>
      <STATE ID="presentation" NAV="Presentation" ICON="presentation">
        <PRESENTATION ID="project-review" TITLE="From idea to working system" />
      </STATE>
    </APP>