Skip to content
ONIWC
iwc 0.1.0

How IWC works

An IWC project goes through two phases: compilation, which turns your .iwc files into one checked, resolved model of the application, and the runtime, which serves that model as a web application and API. Both live in the single iwc binary.

Architecture overview

text
 your project                    iwc (one Go binary)
 ─────────────                   ─────────────────────────────────────────────
 app.iwc                         ┌──────────── compiler ────────────┐
 package.iwc            load ──▶ │ parse  →  validate  →  link       │──▶ project model
 ui/*.ui.iwc                     │ (JSON     (schema per  (cross-file │      │
 api/*.api.iwc                   │  + positions) file type) references)│      │
 database/*.schema.iwc           └───────────────────────────────────┘      │
 actions/ … tests/                                                           ▼
 styles/  assets/                ┌──────────── runtime ─────────────────────────┐
                                 │ pages: render HTML   api: validate → access → │
 iwc dev / iwc start  ─────────▶ │ operation | action | workflow → response      │
                                 │ data: SQLite / PostgreSQL · sessions · jobs    │
                                 │ live updates · uploads · integrations          │
                                 └────────────────────────────────────────────────┘
 iwc build  ──────────────────▶  dist/: manifest.json, assets, migrations SQL,
                                 openapi.json/yaml, release.json, report.json
 iwc build --android / --ios ─▶  Jetpack Compose / SwiftUI projects → APK / .app

How compilation works

Compilation runs on every iwc check, every save under iwc dev, and every iwc build.

  1. Load. The loader walks the project and picks up every file whose name ends in .<type>.iwc (plus app.iwc and package.iwc). Dot-folders, dist/, node_modules/, releases/ and backups/ are skipped. A file's type comes only from its extension, so folders are free to organise as you like. Base names must be unique per type, because files refer to each other by name ("layout": "main.layout.iwc").
  2. Parse. Each file is parsed as strict JSON into a tree that remembers the line and column of every value. Duplicate keys, trailing commas, comments and non-finite numbers are errors — a file two parsers could read differently is refused.
  3. Validate. Each file is checked against the schema of its type: required keys, allowed keys, value types, enums, patterns (identifiers, durations like 30s, ratios like 16/9). Unknown keys are errors unless they start with x-. These are the same schemas iwc schema exports for your editor.
  4. Link. Cross-file and semantic rules are checked: every referenced file exists; a form posts to a POST/PUT/PATCH/DELETE API; a binding names a column its data source loads; an expression only uses names in scope; a property applies to its element type; a link targets a route some screen has; sensitive fields are never selected for the browser; literal credentials are rejected; each native target can render what it is given.
  5. Model. The result is one resolved project model: screens with their layouts and components inlined, APIs with their implementations, schemas with their tables, actions with their steps. Diagnostics carry file:line:col and, where possible, a suggestion.

iwc dev recompiles incrementally: unchanged files are not re-parsed. iwc build writes the model to dist/manifest.json together with your assets, the SQL a fresh database would get for SQLite and PostgreSQL (for review), an OpenAPI 3.1 document, a release record and a size report.

How the runtime works

iwc dev and iwc start serve the model with Go's standard HTTP server.

Pages. A request for a route runs the screen's data sources (database queries limited to the listed columns and filtered by the table's read rule, API sources called internally with the visitor's session, the signed-in user, static items), evaluates expressions and visible conditions on the server, and writes escaped HTML. Hidden elements are never sent. CSS generated from style, responsive and states is scoped per element and emitted under a per-request nonce with a strict Content-Security-Policy.

The browser runtime. A small script adds what HTML cannot do alone: dialogs and drawers, tabs, carousels, dropdowns, form submission with field errors, client state stores, live data, and in-place navigation (the next page's content is swapped in without a full reload). Each route only loads the runtime modules its elements need.

APIs. A request to /api/... is matched by method and path, then:

  1. the body, query and path parameters are validated against the request contract — undeclared fields are rejected (no mass assignment);
  2. authentication, roles, permissions, scopes, rate limits, CSRF and idempotency keys are checked;
  3. the single implementation runs: a built-in operation (db.list, db.create, auth.login, storage.upload…), an action, or a workflow transition — with the table's access rules applied;
  4. only the fields declared in response.fields are returned.

Actions run their steps in order, inside one database transaction when declared; jobs and notifications enqueued inside a transaction exist only if it commits. Live data ("live": true) re-renders the affected fragment in open browsers over Server-Sent Events when its table changes. Jobs run in the background and on schedules with retries.

Data. SQLite is built in (.iwc/dev.db in development, the data folder in production). PostgreSQL is used when DATABASE_URL — or the variable named by app.iwc database.url — is set. Migrations are planned from the schemas on start; additive changes apply automatically and destructive ones are refused.

Development versus production

iwc deviwc start
Recompile on save, live reload, error overlayyesno
Seed rows inserted into empty tablesyesno
Simulated services and providersallowedrefused unless allowInProduction
CookiesstandardSecure, with HSTS
Database.iwc/dev.db (SQLite) unless a URL is setSQLite in --data, or PostgreSQL from the configured URL
Interactive API explorer at /_iwc/api-docsyesonly with app.iwc apiDocs.ui: "always"
OpenAPI document at /_iwc/openapi and the guide at /_iwc/docs/yesyes (apiDocs.spec can turn the document off)

Native targets

For Android and iOS, the compiler lowers screens to platform code: Jetpack Compose (Kotlin) and SwiftUI (Swift) projects are generated under .iwc/native/ and built with Gradle and Xcode. Client state stores run in a small native runtime with the same rules as the web. A project can instead make an app server-driven: the app asks the server for each screen as a view tree (/_iwc/view) and draws it natively, which gives it forms, records, sign-in and expressions. See Android & iOS apps.

Read on: the compiler & runtime architecture page goes through the source packages; Performance & budgets explains what each route sends.

Source: apps/marketing/content/docs/how-iwc-works.md