Skip to main content

Platform Guides

Zylix runs on eight platforms, including embedded systems, each using native UI frameworks for authentic user experiences. This section provides platform-specific setup, integration patterns, and best practices.

Platform status definitions follow the Compatibility Reference.

Supported Platforms
#

PlatformUI FrameworkBindingBuild Command
Web/WASMHTML/JavaScriptWebAssemblyzig build wasm
iOSSwiftUIC ABIzig build ios
watchOSSwiftUIC ABIzig build watchos
AndroidJetpack ComposeJNIzig build android
macOSSwiftUIC ABIzig build
LinuxGTK4C ABIzig build linux
WindowsWinUI 3P/Invokezig build windows-x64
M5StackCustom Zig UIDirectzig build -Dtarget=xtensa-esp32s3

Platform Comparison
#

FeatureWebiOSwatchOSAndroidmacOSLinuxWindowsM5Stack
UI FrameworkHTML/JSSwiftUISwiftUIComposeSwiftUIGTK4WinUI 3Zig UI
LanguageJavaScriptSwiftSwiftKotlinSwiftCC#Zig
BindingWASMC ABIC ABIJNIC ABIC ABIP/InvokeDirect
Min VersionModern browsersiOS 15+watchOS 10+API 26+macOS 12+GTK 4.0+Win 10+ESP-IDF 5.0+
Bundle Size~50 KB~100 KB~80 KB~150 KB~100 KB~80 KB~120 KB~200 KB
Hot Reload

Architecture Per Platform
#

Web/WASM Architecture
#

flowchart TB
    subgraph Browser["Browser"]
        subgraph JS["JavaScript (zylix.js)"]
            Load["Load WASM module"]
            DOM["DOM manipulation"]
            Events["Event forwarding"]
        end

        subgraph WASM["WebAssembly (zylix.wasm)"]
            VDOM1["Virtual DOM"]
            State1["State management"]
            Diff1["Diff algorithm"]
        end

        JS --> WASM
    end

Native Platforms Architecture
#

flowchart TB
    subgraph App["Native App"]
        subgraph UI["Platform UI Framework<br/>(SwiftUI / Compose / GTK4 / WinUI)"]
            Render["Native rendering"]
            PlatformEvents["Platform events"]
            A11y["Accessibility"]
        end

        subgraph Bind["Binding Layer<br/>(C ABI / JNI / P/Invoke)"]
            Calls["Function calls"]
            Marshal["Data marshaling"]
        end

        subgraph Core["Zylix Core (libzylix.a)"]
            VDOM2["Virtual DOM"]
            State2["State management"]
            Diff2["Diff algorithm"]
        end

        UI --> Bind
        Bind --> Core
    end

Embedded Systems Architecture (M5Stack)
#

flowchart TB
    subgraph Device["M5Stack CoreS3"]
        subgraph Hardware["Hardware Layer"]
            SPI["SPI Bus"]
            I2C["I2C Bus"]
            GPIO["GPIO"]
        end

        subgraph HAL["Hardware Abstraction Layer"]
            Display["ILI9342C Display Driver"]
            Touch["FT6336U Touch Controller"]
            Power["AXP2101 PMIC"]
            Expander["AW9523B GPIO Expander"]
        end

        subgraph Core["Zylix Core"]
            VDOM3["Virtual DOM"]
            State3["State Management"]
            Renderer["RGB565 Renderer"]
            Gestures["Gesture Recognition"]
        end

        subgraph UI3["UI Components"]
            Widgets["Widgets"]
            Layout["Layout System"]
            Styles["Styling"]
        end

        Hardware --> HAL
        HAL --> Core
        Core --> UI3
    end

Binding Strategies
#

WebAssembly (Web)
#

Direct compilation to WASM with JavaScript glue code:

// Load WASM module
const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
    env: {
        js_log: (ptr, len) => console.log(readString(ptr, len)),
        js_create_element: (tag, parent) => createElement(tag, parent),
        js_set_text: (el, ptr, len) => setTextContent(el, ptr, len),
    }
});

// Initialize
wasmModule.exports.zylix_init();

// Dispatch events
function onClick(callbackId) {
    wasmModule.exports.zylix_dispatch(callbackId, 0, 0);
    render();
}

C ABI (iOS, macOS, Linux)
#

Static library linking with direct function calls:

// Swift binding
@_silgen_name("zylix_init")
func zylix_init() -> Int32

@_silgen_name("zylix_dispatch")
func zylix_dispatch(_ eventType: UInt32, _ payload: UnsafeRawPointer?, _ len: Int) -> Int32

@_silgen_name("zylix_get_state")
func zylix_get_state() -> UnsafePointer<ZylixState>?

// Usage
zylix_init()
zylix_dispatch(EVENT_INCREMENT, nil, 0)
let state = zylix_get_state()?.pointee

JNI (Android)
#

Java Native Interface for Kotlin/Java interop:

// Kotlin binding
object ZylixLib {
    init {
        System.loadLibrary("zylix")
    }

    external fun init(): Int
    external fun deinit(): Int
    external fun dispatch(eventType: Int, payload: ByteArray?, len: Int): Int
    external fun getState(): ZylixState
}

// Usage
ZylixLib.init()
ZylixLib.dispatch(EVENT_INCREMENT, null, 0)
val state = ZylixLib.getState()

P/Invoke (Windows)
#

.NET source-generated interop:

// C# binding
public static partial class ZylixInterop
{
    [LibraryImport("zylix", EntryPoint = "zylix_init")]
    public static partial int Init();

    [LibraryImport("zylix", EntryPoint = "zylix_dispatch")]
    public static partial int Dispatch(uint eventType, IntPtr payload, nuint len);

    [LibraryImport("zylix", EntryPoint = "zylix_get_state")]
    public static partial IntPtr GetState();
}

// Usage
ZylixInterop.Init();
ZylixInterop.Dispatch(EVENT_INCREMENT, IntPtr.Zero, 0);
var statePtr = ZylixInterop.GetState();

Common Patterns
#

State Observation
#

Each platform implements state observation differently:

// SwiftUI with ObservableObject
class ZylixStore: ObservableObject {
    @Published var state: ZylixState

    init() {
        zylix_init()
        state = zylix_get_state()!.pointee
    }

    func dispatch(_ event: UInt32) {
        zylix_dispatch(event, nil, 0)
        state = zylix_get_state()!.pointee
    }
}
// Compose with MutableState
class ZylixStore {
    var state by mutableStateOf(ZylixLib.getState())
        private set

    fun dispatch(event: Int) {
        ZylixLib.dispatch(event, null, 0)
        state = ZylixLib.getState()
    }
}
// Reactive state wrapper
class ZylixStore {
    constructor() {
        this.listeners = [];
        this.state = zylix.getState();
    }

    dispatch(event) {
        zylix.dispatch(event, null, 0);
        this.state = zylix.getState();
        this.listeners.forEach(fn => fn(this.state));
    }

    subscribe(listener) {
        this.listeners.push(listener);
        return () => this.listeners = this.listeners.filter(l => l !== listener);
    }
}
// MVVM with INotifyPropertyChanged
public class ZylixStore : INotifyPropertyChanged
{
    private ZylixState _state;

    public ZylixState State
    {
        get => _state;
        private set { _state = value; OnPropertyChanged(); }
    }

    public void Dispatch(uint eventType)
    {
        ZylixInterop.Dispatch(eventType, IntPtr.Zero, 0);
        State = Marshal.PtrToStructure<ZylixState>(ZylixInterop.GetState());
    }
}

Event Handling
#

Converting native events to Zylix events:

Button("Increment") {
    store.dispatch(EVENT_INCREMENT)
}
.buttonStyle(.borderedProminent)

TextField("Enter text", text: $inputText)
    .onChange(of: inputText) { newValue in
        newValue.withCString { ptr in
            zylix_dispatch(EVENT_TEXT_INPUT, ptr, newValue.count)
        }
    }
Button(onClick = { store.dispatch(EVENT_INCREMENT) }) {
    Text("Increment")
}

TextField(
    value = inputText,
    onValueChange = { text ->
        ZylixLib.dispatch(EVENT_TEXT_INPUT, text.toByteArray(), text.length)
        inputText = text
    }
)
button.addEventListener('click', () => {
    store.dispatch(EVENT_INCREMENT);
});

input.addEventListener('input', (e) => {
    const text = e.target.value;
    const bytes = new TextEncoder().encode(text);
    const ptr = zylix.alloc(bytes.length);
    zylix.memory.set(bytes, ptr);
    zylix.dispatch(EVENT_TEXT_INPUT, ptr, bytes.length);
    zylix.free(ptr, bytes.length);
});
private void OnIncrementClick(object sender, RoutedEventArgs e)
{
    Store.Dispatch(EVENT_INCREMENT);
}

private void OnTextChanged(object sender, TextChangedEventArgs e)
{
    var text = ((TextBox)sender).Text;
    var bytes = Encoding.UTF8.GetBytes(text);
    fixed (byte* ptr = bytes)
    {
        ZylixInterop.Dispatch(EVENT_TEXT_INPUT, (IntPtr)ptr, (nuint)bytes.Length);
    }
}

Build Configuration
#

Cross-Platform Build Script
#

#!/bin/bash
# build-all.sh

# Build core for all platforms
cd core

# Web/WASM
zig build wasm -Doptimize=ReleaseSmall
cp zig-out/lib/zylix.wasm ../platforms/web/

# iOS (arm64)
zig build -Dtarget=aarch64-ios -Doptimize=ReleaseFast
cp zig-out/lib/libzylix.a ../platforms/ios/

# Android (multiple ABIs)
for abi in aarch64-linux-android armv7a-linux-androideabi x86_64-linux-android; do
    zig build -Dtarget=$abi -Doptimize=ReleaseFast
    cp zig-out/lib/libzylix.a ../platforms/android/app/src/main/jniLibs/${abi}/
done

# macOS (universal binary)
zig build -Dtarget=aarch64-macos -Doptimize=ReleaseFast
zig build -Dtarget=x86_64-macos -Doptimize=ReleaseFast
lipo -create zig-out/lib/libzylix-arm64.a zig-out/lib/libzylix-x64.a -output ../platforms/macos/libzylix.a

# Linux (x64)
zig build -Dtarget=x86_64-linux-gnu -Doptimize=ReleaseFast
cp zig-out/lib/libzylix.a ../platforms/linux/

# Windows (x64)
zig build -Dtarget=x86_64-windows -Doptimize=ReleaseFast
cp zig-out/lib/zylix.dll ../platforms/windows/

Performance Tips
#

All Platforms
#

  1. Minimize state changes: Batch related updates
  2. Use keys for lists: Enable efficient reconciliation
  3. Lazy loading: Load data on demand
  4. Memoization: Cache expensive computations

Platform-Specific
#

PlatformTip
WebEnable WASM streaming compilation
iOSUse @State over @ObservedObject for local state
AndroidUse remember for expensive calculations
macOSPrefer native controls over custom drawing
LinuxUse CSS classes over inline styles
WindowsEnable compiled bindings for performance
M5StackUse dirty rectangle rendering, minimize full redraws

Debugging
#

All Platforms
#

// Enable debug logging in Zig
pub const log_level: std.log.Level = .debug;

// Log state changes
pub fn logStateChange(event: Event) void {
    std.log.debug("Event: {s}, Version: {d}", .{
        @tagName(event),
        state.getVersion()
    });
}

Platform-Specific Tools
#

PlatformTools
WebBrowser DevTools, WASM debugging
iOSXcode Instruments, View Debugger
AndroidAndroid Studio Profiler, Layout Inspector
macOSXcode Instruments
LinuxGTK Inspector, Valgrind
WindowsVisual Studio Profiler, WinDbg
M5StackESP-IDF monitor, JTAG debugging, Serial output

Next Steps
#

Web/WASM

·6 mins
Build and deploy Zylix applications to the web using WebAssembly. This guide covers project setup, WASM compilation, JavaScript integration, and deployment strategies. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: Zig 0.15.0 or later installed Node.js 18+ (for development server) A modern web browser with WASM support Basic knowledge of JavaScript and HTML # Verify Zig installation zig version # Verify Node.js installation node --version Project Structure # A typical Zylix web project has this structure:

iOS

·6 mins
Build native iOS applications with Zylix using SwiftUI. This guide covers Xcode project setup, C ABI integration, and App Store deployment. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: macOS 13.0 or later Xcode 15.0 or later Zig 0.15.0 or later Apple Developer account (for device testing and deployment) Basic knowledge of Swift and SwiftUI # Verify installations zig version xcodebuild -version Architecture Overview # flowchart TB subgraph iOS["iOS App"] subgraph Swift["SwiftUI Layer"] Views["Views"] Store["ZylixStore"] Binding["Swift Bindings"] end subgraph Zig["Zylix Core (libzylix.a)"] VDOM["Virtual DOM"] State["State Management"] Events["Event Handlers"] end Views --> Store Store --> Binding Binding --> Zig end Project Setup # Step 1: Create Xcode Project # Open Xcode → File → New → Project Select iOS → App Configure: Product Name: ZylixApp Interface: SwiftUI Language: Swift Step 2: Build Zylix Static Library # Build libzylix.a for iOS:

Android

·7 mins
Build native Android applications with Zylix using Jetpack Compose. This guide covers Android Studio setup, JNI integration, and Google Play deployment. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: Android Studio Hedgehog (2023.1.1) or later Android NDK r25 or later Zig 0.15.0 or later JDK 17 or later Basic knowledge of Kotlin and Jetpack Compose # Verify Zig installation zig version # Verify Java installation java -version Architecture Overview # flowchart TB subgraph Android["Android App"] subgraph Kotlin["Kotlin/Compose Layer"] UI["Composable UI"] ViewModel["ViewModel"] JNI["JNI Bindings"] end subgraph Native["Native Layer (libzylix.so)"] VDOM["Virtual DOM"] State["State Management"] Events["Event Handlers"] end UI --> ViewModel ViewModel --> JNI JNI --> Native end Project Setup # Step 1: Create Android Project # Open Android Studio → New Project Select Empty Activity (Compose) Configure: Name: ZylixApp Package: com.example.zylixapp Minimum SDK: API 26 (Android 8.0) Build configuration language: Kotlin DSL Step 2: Configure NDK # Add to local.properties:

watchOS

·2 mins
Build watchOS apps with Zylix using SwiftUI. This guide matches the current counter PoC implementation. Platform status definitions follow the Compatibility Reference. Status # In Development — minimal counter implementation with C ABI bridge. Prerequisites # macOS 13.0 or later Xcode 15.0 or later with watchOS SDK Zig 0.15.0 or later # Verify installations zig version xcodebuild -version xcrun simctl list devices | grep -i watch Architecture Overview # flowchart TB subgraph Watch["watchOS App"] subgraph WatchSwift["SwiftUI Layer"] WatchViews["Views"] WatchStore["ZylixBridge"] WatchBinding["C ABI"] end subgraph WatchZig["Zylix Core (libzylix.a)"] WatchVDOM["Virtual DOM"] WatchState["State Management"] WatchEvents["Event Handlers"] end WatchViews --> WatchStore WatchStore --> WatchBinding WatchBinding --> WatchZig end subgraph iOS["iOS Companion (optional)"] CompanionApp["Companion App"] end Project Setup # Step 1: Build Zylix Core for watchOS # cd core # For watchOS Simulator (recommended for development) zig build watchos-sim # For watchOS Device zig build watchos Outputs:

macOS

·6 mins
Build native macOS applications with Zylix using SwiftUI. This guide covers Xcode project setup, C ABI integration, and Mac App Store deployment. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: macOS 13.0 (Ventura) or later Xcode 15.0 or later Zig 0.15.0 or later Apple Developer account (for distribution) Basic knowledge of Swift and SwiftUI # Verify installations zig version xcodebuild -version swift --version Architecture Overview # flowchart TB subgraph macOS["macOS App"] subgraph Swift["SwiftUI Layer"] Views["Views & Windows"] Store["ZylixStore"] Menu["Menu Bar"] end subgraph Zig["Zylix Core (libzylix.a)"] VDOM["Virtual DOM"] State["State Management"] Events["Event Handlers"] end Views --> Store Store --> Zig Menu --> Store end Project Setup # Step 1: Create Xcode Project # Open Xcode → File → New → Project Select macOS → App Configure: Product Name: ZylixMacApp Interface: SwiftUI Language: Swift Uncheck “Include Tests” (add later if needed) Step 2: Build Universal Binary # Build libzylix.a for both Apple Silicon and Intel:

Linux

·6 mins
Build native Linux applications with Zylix using GTK4. This guide covers development environment setup, C ABI integration, and distribution packaging. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: Linux distribution (Ubuntu 22.04+, Fedora 38+, or similar) Zig 0.15.0 or later GTK4 development libraries pkg-config and build tools Basic knowledge of C and GTK Install Dependencies # # Update package list sudo apt update # Install build tools sudo apt install build-essential pkg-config # Install GTK4 development libraries sudo apt install libgtk-4-dev # Verify installation pkg-config --modversion gtk4 # Install build tools sudo dnf groupinstall "Development Tools" # Install GTK4 development libraries sudo dnf install gtk4-devel # Verify installation pkg-config --modversion gtk4 # Install build tools sudo pacman -S base-devel # Install GTK4 development libraries sudo pacman -S gtk4 # Verify installation pkg-config --modversion gtk4 Architecture Overview # flowchart TB subgraph Linux["Linux Application"] subgraph GTK["GTK4 Layer"] Window["GtkWindow"] Widgets["Widgets"] Signals["Signal Handlers"] end subgraph Zig["Zylix Core (libzylix.a)"] VDOM["Virtual DOM"] State["State Management"] Events["Event Handlers"] end Window --> Widgets Widgets --> Signals Signals --> Zig end Project Setup # Step 1: Project Structure # zylix-linux-app/ ├── core/ # Zylix core (Zig) │ ├── src/ │ │ └── main.zig │ └── build.zig ├── src/ # GTK application (C) │ ├── main.c │ ├── zylix_bindings.h │ └── app_window.c ├── resources/ │ ├── app.gresource.xml │ └── window.ui ├── Makefile └── meson.build # Alternative build system Step 2: Build Zylix Static Library # cd core # Build for Linux x86_64 zig build -Dtarget=x86_64-linux-gnu -Doptimize=ReleaseFast # Output: zig-out/lib/libzylix.a cp zig-out/lib/libzylix.a ../lib/ Step 3: Create C Bindings Header # Create src/zylix_bindings.h:

Windows

·7 mins
Build native Windows applications with Zylix using WinUI 3. This guide covers Visual Studio setup, P/Invoke integration, and Microsoft Store deployment. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: Windows 10 version 1809 (build 17763) or later Visual Studio 2022 with: .NET Desktop Development workload Windows App SDK Zig 0.15.0 or later .NET 8 SDK or later Basic knowledge of C# and XAML # Verify Zig installation zig version # Verify .NET installation dotnet --version Architecture Overview # flowchart TB subgraph Windows["Windows App"] subgraph CSharp["C# / WinUI Layer"] XAML["XAML Views"] ViewModel["ViewModel"] PInvoke["P/Invoke"] end subgraph Native["Native Layer (zylix.dll)"] VDOM["Virtual DOM"] State["State Management"] Events["Event Handlers"] end XAML --> ViewModel ViewModel --> PInvoke PInvoke --> Native end Project Setup # Step 1: Create WinUI 3 Project # Open Visual Studio 2022 Create new project → Blank App, Packaged (WinUI 3 in Desktop) Configure: Project name: ZylixWindowsApp Target Framework: .NET 8.0 Step 2: Build Zylix DLL # Build zylix.dll for Windows:

M5Stack CoreS3

·11 mins
Build embedded applications with Zylix for M5Stack CoreS3 SE using native Zig. This guide covers ESP32-S3 setup, hardware driver integration, and IoT deployment. Platform status definitions follow the Compatibility Reference. Prerequisites # Before you begin, ensure you have: Zig 0.15.0 or later (with Xtensa support) ESP-IDF 5.1 or later M5Stack CoreS3 SE device USB-C cable for flashing Basic knowledge of embedded systems # Verify installations zig version idf.py --version Hardware Overview # M5Stack CoreS3 SE Specifications # Component Chip Interface Specifications MCU ESP32-S3 - Dual-core Xtensa LX7, 240MHz Display ILI9342C SPI (40MHz) 320x240 IPS LCD, RGB565 Touch FT6336U I2C (0x38) Capacitive, 2-point multi-touch PMIC AXP2101 I2C (0x34) Battery management, LDO/DC-DC GPIO Expander AW9523B I2C (0x58) 16-bit I/O, LED driver Memory - - 8MB PSRAM, 16MB Flash Pin Assignments # Display (SPI) # Pin GPIO Function SCLK GPIO36 SPI Clock MOSI GPIO37 SPI Data Out CS GPIO3 Chip Select D/C GPIO35 Data/Command RST AW9523B P1_1 Reset (via I/O expander) Touch & I2C # Pin GPIO Function SDA GPIO12 I2C Data SCL GPIO11 I2C Clock INT GPIO21 Touch Interrupt RST AW9523B P1_0 Touch Reset Architecture Overview # flowchart TB subgraph M5Stack["M5Stack CoreS3"] subgraph App["Application Layer"] UI["UI Components"] Logic["App Logic"] end subgraph Platform["Zylix Platform"] VDOM["Virtual DOM"] Renderer["Renderer"] Touch["Touch Handler"] Gesture["Gesture Recognition"] end subgraph HAL["Hardware Abstraction"] SPI["SPI Driver"] I2C["I2C Driver"] GPIO["GPIO/Interrupt"] end subgraph Drivers["Device Drivers"] ILI["ILI9342C<br/>Display"] FT6["FT6336U<br/>Touch"] AXP["AXP2101<br/>Power"] AW9["AW9523B<br/>GPIO"] end App --> Platform Platform --> HAL HAL --> Drivers end Project Setup # Step 1: Install ESP-IDF # # Clone ESP-IDF git clone --recursive https://github.com/espressif/esp-idf.git cd esp-idf git checkout v5.1 # Install toolchain ./install.sh esp32s3 # Set up environment . ./export.sh Step 2: Install Zig with Xtensa Support # # Download Zig with Xtensa backend # (Standard Zig builds include Xtensa support since 0.12) curl -LO https://ziglang.org/download/0.15.2/zig-macos-aarch64-0.15.2.tar.xz tar xf zig-macos-aarch64-0.15.2.tar.xz export PATH=$PWD/zig-macos-aarch64-0.15.2:$PATH Step 3: Build Zylix for M5Stack # # Navigate to M5Stack shell cd shells/m5stack # Build for host (testing) zig build # Build for ESP32-S3 zig build -Dtarget=xtensa-esp32s3-none # Run tests zig build test Step 4: Flash to Device # # Using ESP-IDF tools idf.py -p /dev/tty.usbserial-* flash monitor Driver Implementation # Display Driver (ILI9342C) # The ILI9342C driver provides complete LCD control: