# Irgo Framework - AI Assistant Guide > This document instructs AI coding assistants on how to write applications using the Irgo framework. ## Framework Overview Irgo is a mobile application framework that uses: - **Go** as the backend runtime (compiled via gomobile) - **Datastar** for frontend interactivity (SSE-based hypermedia) - **templ** for type-safe HTML templates - **WebView** to render the UI (iOS WKWebView, Android WebView) The key insight: there's no network - SSE requests from Datastar are intercepted by the WebView and routed directly to Go handlers running in-process. ## Core Principles 1. **Hypermedia-Driven**: Return HTML fragments via SSE, not JSON. Datastar morphs HTML directly into the DOM. 2. **Server-Side State**: All state lives in Go. The WebView is a thin rendering layer. 3. **Signals for UI State**: Use Datastar signals for transient UI state (loading, modals, form inputs). 4. **Type Safety**: Use templ for compile-time template checking. ## Project Structure When working on an Irgo project, expect this structure: ``` project/ ├── main.go # Entry point, dev server ├── app/app.go # Router setup ├── handlers/ # HTTP handlers (business logic) ├── templates/ # templ files (.templ) ├── static/ # CSS, JS, images ├── mobile/mobile.go # Mobile bridge └── ios/ # Xcode project ``` ## Writing Handlers ### Handler Signatures Irgo has two types of handlers: ```go // Page handlers return (string, error) for full page renders func(ctx *router.Context) (string, error) // Datastar handlers return error and use ctx.SSE() for responses func(ctx *router.Context) error ``` ### Handler Examples ```go // Page handler - return rendered template r.GET("/", func(ctx *router.Context) (string, error) { return renderer.Render(templates.HomePage()) }) // Datastar GET handler r.DSGet("/items/{id}", func(ctx *router.Context) error { id := ctx.Param("id") item, err := getItem(id) if err != nil { return ctx.NotFound("Item not found") } return ctx.SSE().PatchTempl(templates.ItemDetail(item)) }) // Datastar POST with signals r.DSPost("/items", func(ctx *router.Context) error { var signals struct { Name string `json:"name"` } ctx.ReadSignals(&signals) item := createItem(signals.Name) sse := ctx.SSE() sse.PatchTempl(templates.ItemRow(item)) sse.PatchSignals(map[string]any{"name": ""}) // Clear input return nil }) // Datastar DELETE r.DSDelete("/items/{id}", func(ctx *router.Context) error { id := ctx.Param("id") deleteItem(id) return ctx.SSE().RemoveElements("#item-" + id) }) ``` ### Context Methods ```go ctx.Param("name") // URL path parameter: /users/{name} ctx.Query("key") // Query parameter: ?key=value ctx.FormValue("field") // Form field value ctx.Header("X-Custom") // Request header ctx.IsDatastar() // True if Datastar request ctx.ReadSignals(&v) // Parse Datastar signals into struct ctx.SSE() // Get SSE writer for responses ctx.Redirect("/path") // Redirect ``` ### SSE Response Methods ```go sse := ctx.SSE() sse.PatchTempl(component) // Morph templ component into DOM sse.PatchElements(id, html) // Morph raw HTML into element sse.PatchSignals(signals) // Update client-side signals sse.RemoveElements(selector)// Remove elements from DOM sse.Redirect(url) // Navigate to new URL sse.Console(level, msg) // Log to browser console ``` ## Writing Templates ### Template Syntax (templ) templ uses Go-like syntax with HTML: ```go package templates // Component with parameters templ Button(text string, action string) { } // Component with children templ Card(title string) {
Hello, world!
@Button("Learn More", "@get('/about')") } } } // Conditional rendering templ UserStatus(user *User) { if user != nil { Welcome, { user.Name } } else { Sign In } } // Loops templ ItemList(items []Item) {Are you sure?