Skip to content

Start Here

AIVI is a purely functional, reactive, statically typed language designed for one purpose: building native Linux desktop applications that are correct by construction.

If you have used JavaScript, Python, Rust, React, Elm, or SwiftUI, some ideas will feel familiar and some will not. This page is the first-pass orientation for readers who may be new to functional programming: it gives you the shape of the language before the tutorial asks you to build anything substantial.

What you need to know up front

AIVI does not have if/else, for loops, mutable variables, or null. Instead:

Familiar conceptAIVI equivalent
if/elsePattern matching with ||>, T|>, F|>
for loopsCollection combinators: map, filter, reduce
Mutable variablesSignals — reactive values in a dependency graph
NullOption — explicit presence or absence
Callbacks / event handlersSources and signal merge

If this sounds unusual, Thinking in AIVI explains the mental model shift in detail.

A tiny first example

This is a complete, valid AIVI module:

aivi
type Text -> Text
func formatGreeting = name =>
    "Hello, {name}!"

value greeting = formatGreeting "Ada"

It already shows the two most common top-level forms:

  • func for a named pure function
  • value for a named constant

A first signal

Signals represent values that participate in the reactive graph:

aivi
type Int -> Int
func double = n =>
    n * 2

signal count = 21

signal doubledCount = count
  |> double

The important idea is that doubledCount is defined from count, not assigned later. When count changes, doubledCount recomputes automatically. You declare the relationship once; the runtime handles the rest.

A first UI

AIVI markup is an ordinary expression that describes GTK widgets:

aivi
signal count = 42

signal label = count
  |> "Count: {.}"

value main =
    <Window title="My App">
        <Label text={label} />
    </Window>

export main

The <Label> attribute text={label} binds to the label signal. When count changes, the label updates. No manual subscriptions, no setState, no render loop.

Key concepts

ConceptWhat it isLearn more
valueA named constant expressionValues & Functions
funcA named pure functionValues & Functions
signalA reactive value in the dependency graphSignals
@sourceAn external data feed (timer, keyboard, HTTP, etc.)Sources
typeAn alias, record, or tagged unionTypes
domainA branded type with its own operatorsDomains
|>Pipe — sends a value into a functionPipes & Operators
||>Pattern match — branches on a valuePattern Matching

Why it feels different

Most reactive systems add dataflow on top of an imperative host language. AIVI makes dataflow the default shape of the program, so dependencies stay visible in the source.

That is why the language leans so heavily on named declarations and pipes: the reactive graph is meant to be readable. You should be able to look at any signal and trace where its value comes from, without searching for mutation sites or callback registrations.

Where to go next

Choose the path that matches your goal:


See also: If you are new to functional programming — a plain-language bridge from imperative habits to AIVI's model

(c) 2026 by Andreas Herd