A hypermedia-driven application framework that uses Go as a runtime kernel with Datastar. Build native iOS, Android, and desktop apps using Go, HTML, and Datastar - no JavaScript frameworks required.
- Go-Powered Apps: Write your backend logic in Go, compile to native mobile frameworks or desktop apps
- Datastar for Interactivity: Use Datastar's hypermedia approach with SSE instead of complex JavaScript
- Cross-Platform: Single codebase for iOS, Android, desktop (macOS, Windows, Linux), and web
- Virtual HTTP (Mobile): No network sockets - requests are intercepted and handled directly by Go
- Native Webview (Desktop): Real HTTP server with native webview window
- Type-Safe Templates: Use templ for compile-time checked HTML templates
- Hot Reload Development: Edit Go/templ code and see changes instantly
┌─────────────────────────────────────────────────────────────┐
│ Mobile App │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ WebView (Datastar) │ │
│ │ • HTML rendered by Go templates │ │
│ │ • Datastar handles interactions via irgo:// scheme │ │
│ └──────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼────────────────────────────────┐ │
│ │ Native Bridge (Swift / Kotlin) │ │
│ │ • Intercepts irgo:// requests │ │
│ │ • Routes to Go via gomobile │ │
│ └──────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼────────────────────────────────┐ │
│ │ Go Runtime (gomobile bind) │ │
│ │ • HTTP router (chi-based) │ │
│ │ • Template rendering (templ) │ │
│ │ • Business logic │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Desktop App │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Native Webview Window │ │
│ │ (System webview engine - Chromium/WebKit) │ │
│ │ Navigates to: http://localhost:PORT │ │
│ └──────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼────────────────────────────────┐ │
│ │ Go HTTP Server (localhost:PORT) │ │
│ │ • Page Routes (Templ → HTML) │ │
│ │ • API Routes (SSE responses) │ │
│ │ • Static Asset Server (/static/*) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- Go 1.21+
- templ:
go install github.com/a-h/templ/cmd/templ@latest - air:
go install github.com/air-verse/air@latest
For mobile development:
- gomobile:
go install golang.org/x/mobile/cmd/gomobile@latest && gomobile init - entr:
brew install entr(macOS) - For iOS: Xcode with iOS Simulator
- For Android: Android Studio with SDK and emulator
For desktop development:
- CGO enabled (C compiler required)
- macOS: Xcode Command Line Tools (included with Xcode)
- Windows: MinGW-w64 or similar C compiler
- Linux: GCC and WebKit2GTK dev packages (
apt install libwebkit2gtk-4.0-dev)
go install github.com/stukennedy/irgo/cmd/irgo@latestOr build from source:
git clone https://github.com/stukennedy/irgo.git
cd irgo/cmd/irgo
go install .irgo new myapp
cd myapp
go mod tidy
bun install # or: npm installirgo run desktop # Run as desktop app
irgo run desktop --dev # With devtools enabledirgo dev # Start dev server at http://localhost:8080irgo run ios --dev # Hot-reload with iOS Simulator
irgo run ios # Production build# Desktop
irgo build desktop # Build for current platform
irgo build desktop macos # Build macOS .app bundle
irgo build desktop windows # Build Windows .exe
irgo build desktop linux # Build Linux binary
# Mobile
irgo build ios # Build iOS framework
irgo build android # Build Android AARmyapp/
├── main.go # Mobile/web entry point (build tag: !desktop)
├── main_desktop.go # Desktop entry point (build tag: desktop)
├── go.mod # Go module definition
├── .air.toml # Air hot reload configuration
├── package.json # Node dependencies (Tailwind CSS)
│
├── app/
│ └── app.go # Router setup and app configuration
│
├── handlers/
│ └── handlers.go # HTTP handlers (business logic)
│
├── templates/
│ ├── layout.templ # Base HTML layout
│ ├── pages.templ # Page templates
│ └── components.templ # Reusable components
│
├── static/
│ ├── css/
│ │ ├── input.css # Tailwind source
│ │ └── output.css # Generated CSS
│ └── js/
│ └── datastar.js # Datastar library
│
├── mobile/
│ └── mobile.go # Mobile bridge setup
│
├── ios/ # iOS Xcode project
├── android/ # Android project
│
└── build/
├── ios/ # Built iOS framework
├── android/ # Built Android AAR
└── desktop/ # Built desktop apps
├── macos/ # macOS .app bundle
├── windows/ # Windows .exe
└── linux/ # Linux binary
Desktop mode uses a different architecture than mobile:
- Real HTTP Server: A Go HTTP server starts on an auto-selected localhost port
- Native Webview: A native window with an embedded browser engine opens
- Standard HTTP: The webview navigates to the localhost URL - standard HTTP requests
This means your app works identically to the web dev server, but packaged as a native desktop app.
Projects include a main_desktop.go with build tag //go:build desktop:
//go:build desktop
package main
import (
"flag"
"fmt"
"net/http"
"myapp/app"
"github.com/stukennedy/irgo/desktop"
)
func main() {
devMode := flag.Bool("dev", false, "Enable devtools")
flag.Parse()
r := app.NewRouter()
mux := http.NewServeMux()
staticDir := desktop.FindStaticDir()
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))
mux.Handle("/", r.Handler())
config := desktop.DefaultConfig()
config.Title = "My App"
config.Debug = *devMode
desktopApp := desktop.New(mux, config)
fmt.Println("Starting desktop app...")
if err := desktopApp.Run(); err != nil {
fmt.Printf("Error: %v\n", err)
}
}config := desktop.Config{
Title: "My App", // Window title
Width: 1024, // Window width
Height: 768, // Window height
Resizable: true, // Allow window resize
Debug: false, // Enable browser devtools
Port: 0, // 0 = auto-select available port
}# Run directly (compiles and runs)
irgo run desktop
# With devtools (for debugging)
irgo run desktop --dev# Build for current platform
irgo build desktop
# Build for specific platform
irgo build desktop macos # Creates build/desktop/macos/MyApp.app
irgo build desktop windows # Creates build/desktop/windows/MyApp.exe
irgo build desktop linux # Creates build/desktop/linux/MyApp| Aspect | Mobile | Desktop |
|---|---|---|
| HTTP | Virtual (no sockets) | Real localhost server |
| Bridge | gomobile + native code | None (direct HTTP) |
| Entry point | main.go |
main_desktop.go |
| Build tag | !desktop |
desktop |
| CGO | Not required | Required (webview) |
Irgo supports two types of handlers:
Return (string, error) with HTML:
r.GET("/about", func(ctx *router.Context) (string, error) {
return renderer.Render(templates.AboutPage())
})Return error and use ctx.SSE() for responses:
r.DSPost("/todos", func(ctx *router.Context) error {
var signals struct {
Title string `json:"title"`
}
ctx.ReadSignals(&signals)
todo := createTodo(signals.Title)
sse := ctx.SSE()
sse.PatchTempl(templates.TodoItem(todo))
sse.PatchSignals(map[string]any{"title": ""}) // Clear input
return nil
})Templates use templ with Datastar attributes:
// templates/pages.templ
package templates
templ HomePage() {
@Layout("Home") {
<main class="container mx-auto p-4">
<h1 class="text-2xl font-bold">Welcome to Irgo</h1>
<div data-signals="{name: ''}">
<input
type="text"
data-bind:name
placeholder="Your name"
class="border p-2 rounded"
/>
<button
data-on:click="@post('/greeting')"
class="bg-blue-500 text-white px-4 py-2 rounded"
>
Greet
</button>
<div id="greeting"></div>
</div>
</main>
}
}
templ TodoItem(todo Todo) {
<div id={ "todo-" + todo.ID } class="flex items-center gap-2 p-2">
<input
type="checkbox"
checked?={ todo.Done }
data-on:click={ fmt.Sprintf("@patch('/todos/%s')", todo.ID) }
/>
<span>{ todo.Title }</span>
<button
data-on:click={ fmt.Sprintf("@delete('/todos/%s')", todo.ID) }
class="text-red-500"
>Delete</button>
</div>
}# Create new project
irgo new myapp
irgo new . # Initialize in current directory
# Development
irgo dev # Start dev server with hot reload (web)
irgo run desktop # Run as desktop app
irgo run desktop --dev # Desktop with devtools
irgo run ios --dev # Hot reload with iOS Simulator
irgo run android --dev # Hot reload with Android Emulator
# Production builds
irgo build desktop # Build desktop app for current platform
irgo build desktop macos/windows/linux # Cross-platform builds
irgo build ios # Build iOS framework
irgo build android # Build Android AAR
irgo build all # Build all mobile platforms
irgo run ios # Build and run on iOS Simulator
irgo run android # Build and run on Android Emulator
# Utilities
irgo templ # Generate templ files
irgo install-tools # Install required dev tools
irgo version # Print version
irgo help [command] # Show helpDatastar is a lightweight (~11KB) hypermedia framework that powers Irgo's interactivity:
- SSE (Server-Sent Events): Server pushes HTML fragments to update the DOM
- Reactive Signals: Client-side state with
data-signalsand$variablesyntax - Declarative Actions:
data-on:click="@get('/api')"triggers server requests
| Attribute | Description | Example |
|---|---|---|
data-signals |
Initialize state | data-signals="{count: 0}" |
data-bind:X |
Two-way binding | data-bind:name |
data-on:event |
Event handler | data-on:click="@post('/api')" |
data-text |
Dynamic text | data-text="$count" |
data-show |
Conditional display | data-show="$visible" |
Desktop builds require CGO. Ensure you have a C compiler:
- macOS:
xcode-select --install - Windows: Install MinGW-w64
- Linux:
apt install build-essential
Check that WebKit2GTK is installed (Linux):
apt install libwebkit2gtk-4.0-devgo mod tidy- Check if air is running
- Verify
.air.tomlconfiguration - Make sure
_templ.gois NOT inexclude_regex
lsof -i :8080
kill <PID>MIT License - see LICENSE for details.