llux-website

Llux Language Reference

Status: Pre-release specification


Overview

Llux is a tool for independent creators. It turns interface intent into native software that runs anywhere—without platform lock-in, hidden dependencies, or surprises.

This document specifies the Llux language syntax and file structure. It is organized to match the creator’s workflow: from initial brainstorming through to production-ready implementation.


Core Principles

  1. Plain names, clear intention. Keywords use ordinary words.
  2. Explicit scope. State is addressed through scopes such as app.count, session.user, or component.value.
  3. Four core constructs. The language centers on state, bind, action, and view.
  4. One language everywhere. .llux carries implementation; .llux.md can reference Llux expressions with @.
  5. Kind errors. Errors should identify the root cause, location, and likely fix.

The Wirth Principle

Llux follows Niklaus Wirth’s principle that language constructs should have single, clear meanings.

Construct Single Meaning
@ “This component property is live and reactive”
= “This is static configuration”
<- “Data flows from source to target”
<-> “Data flows both ways”
-> “Data flows from target to source”

No construct is overloaded. Every symbol has one job.


The Four-Stage Workflow

Stage What Happens Artifact Format
1. Brainstorming Free-form exploration, notes, sketches, intent capture .intent.md Plain Markdown (no Llux syntax required)
2. Ideation Structured intent, layout decisions, component identification .llux.md Markdown with Llux extensions
3. Implementation Formal logic, state, actions, and bindings .llux Llux logic syntax
4. Production Compiled binary, header, and integration artifacts .so + .h Generated by compiler

File Types

Extension Purpose Author Stage
.intent.md Brainstorming, free-form notes, sketches, and intent capture Anyone (designer, founder, product) 1. Brainstorming
.llux.md Structured intent, layout, semantics, and design decisions Designer 2. Ideation
.llux Formal logic, state, actions, and bindings Designer + Compiler 3. Implementation
.lmd Short extension for Llux Layout Markdown (equivalent to .llux.md) Designer 2. Ideation

I will incorporate the frontmatter specification into the language reference, placing it after the File Types table and before the workflow stages, with the clear rule that no properties are required and everything is optional.


Frontmatter (YAML)

All Llux Markdown files (.llux.md, .lmd, .intent.md) MAY include a YAML frontmatter block at the top of the file, delimited by --- lines.

Nothing Is Required

No property is required. A file with no frontmatter is still valid.

The $schema directive is optional. It exists to enable editor validation and autocompletion—not to enforce a rigid structure.

Property Type Description
$schema string (URI) Reference endpoint for machine-validation
title string Human-readable name of the module/page
type string (enum) component, layout, view, guide, intent, contract, idea, note
version string Semantic versioning (^[0-9]+\.[0-9]+\.[0-9]+$)
author string Creator of the document
created string (ISO 8601) Creation timestamp
modified string (ISO 8601) Last modification timestamp
status string (enum) draft, review, published, archived
ai_optimized boolean Defaults to true if omitted

Additional Properties

Any other properties are permitted and will not cause validation errors. Tools may use them for their own purposes.

Vendor Extensions

Custom properties for distinct tooling environments SHOULD be prefixed with x- to prevent collisions with future core specification updates.

x-llux-compiler:
  target_architecture: "wasm32-unknown-unknown"

Examples

# Formal document
---
$schema: https://llux.org/frontmatter.schema.json
title: "Button Component"
type: "component"
version: "1.0.0"
author: "Your Name"
status: "published"
---
# Quick sketch (minimal)
---
title: "Counter App Idea"
type: "idea"
---
# No frontmatter at all (still valid)
# Just Markdown content

Canonical Schema

The canonical JSON Schema for Llux frontmatter lives at:

https://llux.org/frontmatter.schema.json

It declares all recommended properties, allows additional properties, and requires none. Editors with YAML Language Server support can use this schema for validation and autocompletion when the $schema directive is present.


---

## Stage 1: Brainstorming (`*.intent.md`)

Brainstorming files are **pure Markdown**. They contain no Llux-specific syntax. They are for:
- Free-form notes
- Sketches (ASCII or referenced images)
- User stories
- Feature lists
- Meeting notes
- References to external resources

**Example (`app.intent.md`):**

```markdown
# Counter App

A simple counter app for demonstration purposes.

## User Stories

- As a user, I want to see the current count.
- As a user, I want to increment the count by pressing a button.
- As a user, I want to reset the count.

## Design Notes

- The count should be large and centered.
- The button should be below the count.
- Use a blue button for increment, red for reset.

Importing from Other Formats:

Brainstorming files can be imported from other formats via importers:

llux import ideas.docx --from=docx --to=intent.md
llux import sketches.fig --from=figma --to=intent.md
llux import requirements.pdf --from=pdf --to=intent.md

Stage 2: Ideation (*.llux.md)

Ideation files are Markdown with Llux extensions. They contain:

Layout Containers

All layout containers use the same pattern:

::: [type] [attributes]
  content
:::

Syntax Requirements:

Standard Types:

Type Purpose Example
flex Flex container ::: flex gap-4
grid Grid container ::: grid cols-3 gap-2
page Page boundary ::: page new
chapter Chapter marker ::: chapter introduction
section Section marker ::: section background
sidebar Sidebar ::: sidebar width=1/3
callout Highlighted block ::: callout type=warning
card Card component ::: card title="Profile"
figure Figure ::: figure src="..."
item Child item ::: item flex-1

Attributes:

Format Example Meaning
key=value gap-4 Utility or key-value attribute
.class .shadow-lg CSS class
#id #user-profile Element ID (only one)
"quoted string" title="User Profile" Attribute value with spaces

Example:

::: card #user-profile .shadow-lg bg-muted p-4 lang="en"
  This is a card with an ID, classes, and attributes.
:::

Dataflow Syntax

Llux uses streaming arrows to make dataflow explicit and directional.

Operator Role Data Flow Example
= Configuration N/A min=0 max=100
<- Inbound Stream Source → UI @text <- app.count
<-> Bi‑directional Sync Source ↔ UI @value <-> app.search_query
-> Outbound Stream UI → Target @press -> app.increment

The @ Rule: @ marks a component property as live and reactive. It belongs on the target (the component’s property key), not on the source.

Syntax Meaning
@text The text property is a live stream
@value The value property is a live stream
@press The press event is a live stream
min=0 min is static configuration (not live)

Examples:

# Configuration (static, no dataflow)
::: Slider { min=0 max=100 step=1 }

# Inbound Stream: Label's @text pulls from app.count
::: Label { @text <- app.count }

# Static text + live stream
::: Label { @text <- "Count: " + app.count }

# Bi‑directional Sync: Input's @value syncs with app.search_query
::: Input { @value <-> app.search_query placeholder="Search..." }

# Outbound Stream: Button's @press pushes to app.increment
::: Button { @press -> app.increment label="+1" }

Intent Comments

Comments capture intent without affecting rendering:

::: ! This is an intent comment. It will not be rendered.

Metadata Keys

Metadata can be attached to the parent container:

::: [timing]                    # Key only (label/definition)
::: [duration](3.5s)            # Key-value pair

Pandoc Compatibility

Llux Markdown is designed to be compatible with Pandoc’s header_attributes extension wherever possible:

Pandoc Syntax Llux Syntax Compatible?
{#identifier .class key=value} {@text <- app.count label="+1"} ✅ Yes
{#identifier .class key=value} {@text : app.count} ❌ No (colon in key)

Recommendation: Use key=value format for Pandoc compatibility.


Stage 3: Implementation (*.llux)

Implementation files contain the formal logic of the application:

State

State is mutable data, explicitly scoped.

app state {
    count: int = 0
    user: string | null = null
}

session state {
    logged_in: bool = false
    token: string | null = null
}

component state {
    expanded: bool = false
    selected: int | null = null
}

State References:

app.count          # Application-level state
session.user       # Session-level state
component.value    # Component-level state

Actions

Actions are state-modifying operations.

action Increment(amount: int = 1) {
    app.count += amount
}

action Login(username: string, password: string) -> Result {
    # Precondition: Must be logged out
    requires: session.logged_in == false
    
    # Postcondition: If successful, logged_in == true
    ensures: session.logged_in == true if result.success
    
    # Implementation
    # ...
}

Action Attributes:

Attribute Purpose Example
requires: Precondition requires: session.user != null
ensures: Postcondition ensures: count == old.count + amount
error: Error handling error: count = count

Bind

Derived data or reactive binding.

bind double = app.count * 2
bind is_logged_in = session.user != null
bind greeting = "Hello, " + session.user.name

View

Visual structure.

view RootView {
    Panel {
        Label { text: "Count: " + app.count }
        Button { press: Increment(1) label: "+1" }
    }
}

Components

Components are reusable, self-contained units.

component Button {
    # Outlets (action holes)
    outlet press: () -> void
    
    # Properties (configuration)
    prop label: string = "Button"
    prop variant: string = "primary"
    prop disabled: bool = false
    
    # State (component-local)
    state {
        hovered: bool = false
        pressed: bool = false
    }
    
    # View
    view {
        # ...
    }
}

Component Outlets:

Component Outlet Meaning
Button press: () -> void When pressed
Slider change: (value: float) -> void When value changes
Toggle flip: (state: bool) -> void When toggled
Input submit: (text: string) -> void When submitted
TabGroup select: (tab: int) -> void When tab selected

Outlets use intent-based names (press, slide, flip, submit, select) rather than developer-centric names (onClick, onChange) to align with designer language.

Services

Services are external capabilities.

service api {
    endpoint: "https://api.example.com"
    timeout: 30s
    
    method GetUser(id: int) -> User
    method SaveUser(user: User) -> Result
}

Imports

External modules can be imported:

import "components/button.llux"
import "services/api.llux"
import "design/tokens.llux" as tokens

Contextual Contracts

The contract should include intent documentation for state and actions:

app state {
    # The current count displayed to the user
    # Initially 0, increases when the user presses the button
    count: int min=0 max=100 = 0
}

action Increment(amount: int between 1 and 10 = 1) {
    # When the user presses the "+" button, this action is called
    # It increases the count by the specified amount
    # Precondition: The user must be logged in
    # Postcondition: count == old.count + amount
}

Stage 4: Production (Generated Artifacts)

The compiler generates:

Artifact Purpose Format
Binary Rendered UI + transit logic .so/.dylib/.dll
Header C API for the developer .h
Manifest Semantic description of the Contract JSON

The Complete Example

app.llux.md (Surface)

::: page
  ::: flex gap-4
    # Static: Label displays a static message
    ::: Label { text: "Welcome to the counter app" }
    
    # Inbound: Label's @text pulls from app.count
    ::: Label { @text <- "Count: " + app.count }
    
    # Configuration: Slider properties
    # Sync: Slider's @value syncs with app.count
    ::: Slider { @value <-> app.count min=0 max=100 step=1 }
    
    # Action: Button's @press pushes to app.increment
    ::: Button { @press -> app.increment label="+1" }
  :::
:::

app.llux (Contract)

app state {
    # Current count shown to the user
    count: int min=0 max=100 = 0
}

action Increment(amount: int between 1 and 10 = 1) {
    # Called when the user presses the "+" button
    requires: session.user != null
    ensures: count == old.count + amount
    app.count += amount
}

action Reset() {
    # Called when the user presses the "Reset" button
    app.count = 0
}

view RootView {
    Panel {
        Label { text: "Count: " + app.count }
        Button { press: Increment(1) label: "+1" }
        Button { press: Reset() label: "Reset" }
    }
}

Summary of Syntax

Construct Syntax Purpose
State app state { count: int = 0 } Mutable data
Action action Increment(amount: int = 1) { ... } State-modifying operation
Bind bind double = app.count * 2 Derived data
View view RootView { ... } Visual structure
Component component Button { ... } Reusable UI unit
Outlet outlet press: () -> void Action hole in a component
Prop prop label: string = "Button" Component configuration
Layout container ::: flex gap-4 Markdown layout container
Inbound stream @text <- app.count Live read‑only stream
Bi‑directional sync @value <-> app.search_query Live two‑way sync
Outbound stream @press -> app.increment Live output / action
Configuration min=0 max=100 Static property
Intent comment ::: ! This is an intent comment Non‑rendering comment
Metadata key ::: [timing] Metadata on parent
Precondition requires: session.user != null Action precondition
Postcondition ensures: count == old.count + amount Action postcondition

Extensibility

New extensions can be added without modifying the core compiler:

Extension Type Purpose Example
Layout Container New ::: type ::: carousel
Component New UI component ::: Chart
Importer New source format --from=figma
Exporter New target format --target=vue
Recipe AI-suggested pattern MQTT integration

Versioning

Changes should be additive wherever possible. If a feature must be deprecated, public docs should mark it clearly and preserve older context outside the launch-facing pages.


Historical Terminology

Older term Current direction
computed Prefer bind.
command Prefer action.
layout Prefer view for .llux; use Layout Markdown for .llux.md.
resource / effect Treat as draft design space until re-specified.

References


Llux: Tool for independent creators. Build once. Run anywhere. Own it.