Compiler & DSL v0.2.0

gapk

Go-style declarative language → Flutter & Jetpack Compose APKs

Write native Android apps with clean Go syntax and reactive state. gapk transpiles .gapk files directly into standard Flutter (lib/main.dart) or Kotlin Jetpack Compose (MainActivity.kt) projects and builds release APKs.

$ gapk init my-app && cd my-app && gapk transpile main.gapk

Widget Reference

Search any widget or action to see what it does and how to use it.

/

Search the reference

Type a widget or action name above — e.g. button, loop, http_get.

Features

Zero boilerplate, type-inferred reactivity, and full mobile UI control.

Syntax

Go-Like Syntax

Clean blocks, := reactive state inference (string, int, float, bool, list), and zero semicolon or comma clutter. State mutations automatically re-render dependent components.

username := "Developer"
count := 0
count = count + 1
Styling

Inline UI Modifiers

Style any widget inline using [key: value] attributes without deeply nested wrapper widgets. Fast to read, fast to maintain.

[padding: 16, bg: "#1E293B",
 radius: 12, size: 18, color: "#10B981"]
Compiler

Dual Target Transpiler

Output Flutter Dart (lib/main.dart) or Android Kotlin Jetpack Compose (MainActivity.kt) with a single compiler flag: --target=flutter or --target=compose.

gapk transpile --target=flutter
gapk transpile --target=compose

Full Flutter Widget Parity

Direct 1:1 mapping from gapk declarative elements to Flutter & Compose components.

Scaffold & Navigation

7 widgets
screen appbar drawer fab bottom_nav navigate navigate_back

Layout & Containers

15 widgets
column row stack container card listview list_for gridview scroll center expanded padding sizedbox spacer divider

Display & Media

7 widgets
text icon image avatar badge listtile progress

Forms & Inputs

7 widgets
input button icon_button switch_toggle checkbox slider dropdown

Reactive Actions

8 actions
state mutation (=) list_add list_remove snackbar toast dialog http_get if / else

Example

Real starter code transpiled by gapk v0.2.0.

package main

app "StarterApp" [theme: "dark", primary: "#10B981"] {
    username := "Developer"
    count := 0
    notifications := true

    screen "Dashboard" [padding: 16] {
        appbar "StarterApp" [center: true]

        column [spacing: 12] {
            card [padding: 16, radius: 12, elevation: 3] {
                text "Welcome, " + username [size: 20, weight: "bold", color: "#10B981"]
                text "Total actions: " + count [size: 14]
            }

            input username "Update Username" [icon: "person"]
            switch_toggle notifications "Enable Push Alerts"

            row [spacing: 10] {
                button "Increment" [bg: "#10B981"] {
                    count = count + 1
                    snackbar "Count updated to " + count
                }
                button "Details" [variant: "outlined"] {
                    dialog "Summary" "User " + username + " triggered " + count + " actions."
                }
            }
        }

        fab "add" {
            count = count + 1
            toast "Quick add: " + count
        }
    }
}
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

void main() {
  runApp(const StarterAppApp());
}

class StarterAppApp extends StatefulWidget {
  const StarterAppApp({super.key});

  @override
  State<StarterAppApp> createState() => _StarterAppAppState();
}

class _StarterAppAppState extends State<StarterAppApp> {
  String username = "Developer";
  int count = 0;
  bool notifications = true;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "StarterApp",
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0xFF10B981),
        brightness: Brightness.dark,
      ),
      initialRoute: "/Dashboard",
      routes: {
        "/Dashboard": (ctx) => _buildDashboardScreen(ctx),
      },
    );
  }

  Widget _buildDashboardScreen(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StarterApp"),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Card(
                elevation: 3.0,
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        "Welcome, ${username}",
                        style: TextStyle(
                          fontSize: 20.0,
                          fontWeight: FontWeight.bold,
                          color: const Color(0xFF10B981),
                        ),
                      ),
                      Text(
                        "Total actions: ${count}",
                        style: TextStyle(
                          fontSize: 14.0,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 12.0),
              TextField(
                decoration: InputDecoration(
                  labelText: "Update Username",
                  prefixIcon: const Icon(Icons.person),
                  border: const OutlineInputBorder(),
                ),
                onChanged: (val) => setState(() => username = val),
              ),
              const SizedBox(height: 12.0),
              SwitchListTile(
                title: const Text("Enable Push Alerts"),
                value: notifications,
                onChanged: (val) => setState(() => notifications = val),
              ),
              const SizedBox(height: 12.0),
              Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  ElevatedButton(
                    style: ElevatedButton.styleFrom(backgroundColor: const Color(0xFF10B981)),
                    onPressed: () {
                      setState(() { count = count + 1; });
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Count updated to ${count}")));
                    },
                    child: Text("Increment"),
                  ),
                  const SizedBox(width: 10.0),
                  OutlinedButton(
                    onPressed: () {
                      showDialog(
                        context: context,
                        builder: (ctx) => AlertDialog(
                          title: Text("Summary"),
                          content: Text("User ${username} triggered ${count} actions."),
                          actions: [TextButton(onPressed: () => Navigator.pop(ctx), child: const Text("OK"))],
                        ),
                      );
                    },
                    child: Text("Details"),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() { count = count + 1; });
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Quick add: ${count}")));
        },
        child: const Icon(Icons.add),
      ),
    );
  }

}
package com.gapk.main

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                Surface(modifier = Modifier.fillMaxSize()) {
                    StarterAppApp()
                }
            }
        }
    }
}

@Composable
fun StarterAppApp() {
    val context = LocalContext.current
    var username by remember { mutableStateOf("Developer") }
    var count by remember { mutableStateOf(0) }
    var notifications by remember { mutableStateOf(true) }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        Text(text = "Dashboard", style = MaterialTheme.typography.headlineMedium)
        Spacer(modifier = Modifier.height(12.dp))
        Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
            Card(modifier = Modifier.fillMaxWidth()) {
                Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
                    Text(text = "Welcome, ${username}")
                    Text(text = "Total actions: ${count}")
                }
            }
            OutlinedTextField(
                value = username,
                onValueChange = { username = it },
                label = { Text("Update Username") },
                modifier = Modifier.fillMaxWidth()
            )
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                Switch(checked = notifications, onCheckedChange = { notifications = it })
                Text("Enable Push Alerts")
            }
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                Button(onClick = {
                    count = count + 1
                    Toast.makeText(context, "Count updated to ${count}", Toast.LENGTH_SHORT).show()
                }) {
                    Text(text = "Increment")
                }
                Button(onClick = {
                    Toast.makeText(context, "User ${username} triggered ${count} actions.", Toast.LENGTH_SHORT).show()
                }) {
                    Text(text = "Details")
                }
            }
        }
    }
}

CLI Usage

Lightweight command-line interface for project scaffolding, transpilation, and building.

gapk help
Usage:
  gapk <command> [flags] [arguments]

Commands:
  init <dir>                        Initialize a new .gapk project
  transpile [--target=flutter] <f>  Print generated Flutter Dart or Kotlin Compose code
  build [--target=flutter] <f> [d]  Generate project scaffold and compile APK
  version                           Print compiler version
  help                              Show this help message

Flags:
  --target=flutter                  Generate Flutter (lib/main.dart) [default]
  --target=compose                  Generate Android Kotlin Jetpack Compose
01

Initialize Project

Create a new gapk project structure with a ready-to-run starter template.

gapk init my-project
02

Transpile to Stdout

Inspect generated Dart or Kotlin code instantly without triggering a full build.

gapk transpile --target=flutter main.gapk
03

Build Release APK

Scaffold full project and compile Android release APK into target directory.

gapk build --target=flutter main.gapk ./dist

Download CLI

Precompiled standalone binary for 64-bit Linux environments.

Artifact gapk-linux-amd64
Version v0.2.0
Architecture Linux x86_64 ELF (Static)
File Size 2.7 MB
SHA-256 bb383a90a50be20c53b29f74584bbd5921b83cd792a90c1e203f3cddfecb68da
Installation:
chmod +x gapk-linux-amd64
sudo mv gapk-linux-amd64 /usr/local/bin/gapk
gapk version

Prerequisites & Environment Notes

  • Standalone Transpilation: Running ./gapk transpile works independently with zero external dependencies. Neither Android SDK nor Flutter is required for code generation.
  • APK Compilation: Running ./gapk build requires the Flutter SDK and Android SDK / build-tools to compile and sign final APK binaries.
  • Building from Source: If you wish to build the compiler from source instead of using prebuilt binaries, Go 1.22+ is required (go build -o bin/gapk ./cmd/gapk).