Use cases

Four ways to use the same Blocks.

You write the model once. Read it as documentation, edit it with an LLM, derive any companion from it, or produce a view only when someone asks.

01
Better Markdown

Prose and the model share one file.

A Markdown file can say that a lamp’s brightness is 80. The Block says the same thing in prose, and also as an Integer, with a reference a tool can follow. Documentation stays Markdown. It is a member of the Block, next to the model.

documentation

Markdown prose, inside the file.

properties

Brightness is an Integer.

references

SeeAlso names another Block.

Lamp.md markdown
# Lamp

A lamp with a brightness of 80.

See also: the shade.
Lamp.bml blockml
<ex:Lamp xmlns="http://blockml.org/bml"
  xmlns:core="org.blockml.bml.core"
  xmlns:ex="com.example.bml">

  <baseType>
    core:Block
  </baseType>
  <is>
    A lamp with a brightness
  </is>
  <documentation>
    # Lamp

    Brightness runs from 0 to 100.
    The value below is the same fact, typed.
  </documentation>
  <properties>
    <brightness type="Integer">
      <value>80</value>
    </brightness>
  </properties>
  <references>
    <see type="ex:Shade" relation="SeeAlso" />
  </references>
</ex:Lamp>
02
AI workspace

Humans and LLMs edit the same model.

The workspace is the Blocks. People and models search, inspect, extend, and validate them. Intermediate states stay in the files. A renderer publishes the current state.

DocGen

A DocSet is the document. ValidatePublishReady checks that it can be published. AssembleSite renders each page, wraps the layout and the theme, and writes HTML. Those files are the manifestation of that run.

  1. DocSet The document model
  2. ValidatePublishReady Publish gate
  3. AssembleSite Pages, layout, theme
  4. HTML Files from this run

Transformation pipeline

A multi-stage change is a ModelTransformation. transform apply runs one execution against the model, and that execution is itself a Block. One transform runs at a time, on a clean worktree.

terminal transform
npx blockml transform apply com.example.bml._meta.transform.AddProduct

Knowledge model

A catalog is ordinary Blocks: compositions, types, references. An LLM finds them with search and inspect, edits the file, then validate checks the result. The file is the record.

Catalog.bml blockml
<ex:Catalog xmlns="http://blockml.org/bml"
  xmlns:core="org.blockml.bml.core"
  xmlns:ex="com.example.bml">

  <baseType>
    core:Block
  </baseType>
  <is>
    The products an assistant may answer from
  </is>
  <aggregations>
    <products type="ex:Product">
      <composition>
        <ex:Lamp />
        <ex:Shade />
      </composition>
    </products>
  </aggregations>
  <references>
    <see type="ex:Lamp" relation="SeeAlso" />
  </references>
</ex:Catalog>
03
Companion

A companion is whatever you derive.

The Block stays the source of truth. A renderer writes a companion in the form the target needs: a document, a schema, application code, a CAD model, a service, or any other native form. There is no fixed companion language. A fix belongs in the Block. Rendering writes the companion again.

HTML

Pages and documents

XSD

Schemas

TypeScript

Libraries and services

OpenSCAD

Parts you can print

Example

The same screen as React and Angular

InboxScreen.bml names the title and the two actions. One renderer writes a React function. Another writes an Angular component. Both are companions of this Block. A different target writes a different artifact from the same file.

InboxScreen.bml source of truth
<app:InboxScreen xmlns="http://blockml.org/bml"
  xmlns:core="org.blockml.bml.core"
  xmlns:app="com.example.bml">

  <baseType>
    core:Block
  </baseType>
  <is>
    The inbox screen
  </is>
  <properties>
    <title type="Text">
      <value>Inbox</value>
    </title>
  </properties>
  <aggregations>
    <actions type="app:Action">
      <composition>
        <app:Compose />
        <app:Archive />
      </composition>
    </actions>
  </aggregations>
</app:InboxScreen>
InboxScreen.tsx React
export function InboxScreen() {
  return (
    <section>
      <h1>Inbox</h1>
      <Compose />
      <Archive />
    </section>
  );
}
inbox.component.ts Angular
@Component({
  selector: "app-inbox",
  template: `
    <section>
      <h1>Inbox</h1>
      <app-compose />
      <app-archive />
    </section>
  `
})
export class InboxComponent {}
04
Just-in-time software

The view appears when someone opens it.

A companion can be written into the repository and kept. Just-in-time software runs that render when a request arrives. OpenOrders.bml stays. The HTML below exists for the response.

  1. Request Someone opens Open orders
  2. Resolve OpenOrders.bml is the spec
  3. Render Only this report is emitted
  4. Respond HTML for this caller
OpenOrders.bml kept
<ex:OpenOrders xmlns="http://blockml.org/bml"
  xmlns:core="org.blockml.bml.core"
  xmlns:ex="com.example.bml">

  <baseType>
    core:Block
  </baseType>
  <is>
    A report of orders that are still open
  </is>
  <properties>
    <title type="Text">
      <value>Open orders</value>
    </title>
  </properties>
  <aggregations>
    <columns type="ex:Column">
      <composition>
        <ex:OrderId />
        <ex:Customer />
        <ex:DueDate />
      </composition>
    </columns>
  </aggregations>
</ex:OpenOrders>
response.html this request
<article>
  <h1>Open orders</h1>
  <table>
    <thead>
      <tr>
        <th>Order</th>
        <th>Customer</th>
        <th>Due</th>
      </tr>
    </thead>
  </table>
</article>

Produced for the request. The repository keeps OpenOrders.bml.

Next

Write the Block these four uses share.

Init a package, then open the folder in Cursor or Claude Code. The same file can be documentation, a workspace, a companion source, or a view rendered on demand.