Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Rikitav/Terminality/llms.txt

Use this file to discover all available pages before exploring further.

This page walks you through building a minimal but complete Terminality application. You will import the module, create a StackPanel with a centered label and an exit button, hand the widget tree to HostApplication, and run the UI loop. By the end you will have a working terminal UI and understand the pattern used in every Terminality application.
Complete the installation steps before starting. You need Terminality built and linked into your project.

Build your first app

1

Import the module and open the namespace

Terminality ships as a C++23 named module. Add these two lines at the top of your source file — no headers required.
import terminality;
using namespace terminality;
The single import terminality; statement makes the entire public API available: all controls, the layout engine, the event system, and HostApplication.
2

Enter the terminal

Inside main, retrieve the HostApplication singleton and call EnterTerminal(). This switches the terminal into raw input mode and takes over the output buffer.
int main()
{
    auto& app = HostApplication::Current();
    app.EnterTerminal();
Always pair EnterTerminal() with ExitTerminal() at the end of main. Failing to call ExitTerminal() will leave the terminal in raw mode after the process exits.
3

Compose the widget tree

Use the init<T>() factory helper to build controls. Pass a lambda that receives a typed pointer to the new control and configures its properties. Nest calls to build a hierarchy.
    auto root = init<StackPanel>([](auto* panel)
    {
        panel->HorizontalAlignment = HorizaontalAllign::Stretch;
        panel->VerticalAlignment = VerticalAlign::Stretch;

        panel->AddChild(init<Label>([](auto* label)
        {
            label->Text = L"Hello, Terminality!";
            label->HorizontalAlignment = HorizaontalAllign::Center;
            label->VerticalAlignment = VerticalAlign::Center;
        }));

        panel->AddChild(init<Button>([](Button* btn)
        {
            btn->Text = L"Exit";
            btn->HorizontalAlignment = HorizontalAlign::Stretch;
            btn->VerticalAlignment = VerticalAlign::Top;

            btn->Clicked += []()
            {
                HostApplication::Current().RequestStop();
            };
        }));
    });
The StackPanel stretches to fill the screen. The Label centres itself within the available space. The Button subscribes to the Clicked event and calls RequestStop() to signal the UI loop to exit.
4

Run the UI loop and exit

Transfer ownership of the root widget to RunUILoop(). The call blocks until RequestStop() is called, then returns. Call ExitTerminal() to restore the terminal.
    app.RunUILoop(std::move(root));
    app.ExitTerminal();
    return 0;
}

Complete example

Here is the full program in one block, ready to compile:
import terminality;
using namespace terminality;

int main()
{
    auto& app = HostApplication::Current();
    app.EnterTerminal();

    auto root = init<StackPanel>([](auto* panel)
    {
        panel->HorizontalAlignment = HorizaontalAllign::Stretch;
        panel->VerticalAlignment = VerticalAlign::Stretch;

        panel->AddChild(init<Label>([](auto* label)
        {
            label->Text = L"Hello, Terminality!";
            label->HorizontalAlignment = HorizaontalAllign::Center;
            label->VerticalAlignment = VerticalAlign::Center;
        }));

        panel->AddChild(init<Button>([](Button* btn)
        {
            btn->Text = L"Exit";
            btn->HorizontalAlignment = HorizontalAlign::Stretch;
            btn->VerticalAlignment = VerticalAlign::Top;

            btn->Clicked += []()
            {
                HostApplication::Current().RequestStop();
            };
        }));
    });

    app.RunUILoop(std::move(root));
    app.ExitTerminal();
    return 0;
}

What just happened

HostApplication::Current() returns the singleton that owns the terminal lifecycle. It is the single entry and exit point for every Terminality program. EnterTerminal() puts the terminal into raw mode and sets up the output buffer. From this point, Terminality controls all output; do not write to stdout or stderr directly while the UI loop is running. init<T>(lambda) allocates a control of type T, calls the lambda with a typed pointer so you can configure properties inline, and returns a std::unique_ptr<T>. This pattern replaces constructors and separate setter calls with a single self-contained expression. AddChild() on a container control registers a child widget. The layout engine measures and arranges children automatically on every frame based on their alignment and the available space. btn->Clicked += []() { ... } subscribes a lambda to the Clicked event. Terminality’s event system is type-safe: each event carries its own signature, and subscribers are stored as std::function instances. RunUILoop(std::move(root)) takes ownership of the root widget, then runs the measure-arrange-render and input-poll loop until RequestStop() is called.

Next steps

Build and integrate

Set up the CMake build and link Terminality into your own project.

What is Terminality?

Understand the architecture, module system, and extension points in depth.

Build docs developers (and LLMs) love