utm-dev: Deep Improvement Analysis & Roadmap#
Executive Summary#
After comprehensive testing, utm-dev successfully builds hybrid apps for macOS, iOS, and Android. However, several areas need improvement to make it production-grade and developer-friendly.
Current State: What Works ✅#
- Core functionality: Builds work for macOS, iOS, Android
- Hybrid apps: Webviewer integration works on all tested platforms
- Icon generation: Automatic platform-specific icons
- SDK management: Caching works, downloads once
- Workspace management: Multi-module support
- Pure Go: No platform-specific code required from users
Critical Improvement Areas#
1. Developer Experience (DX) 🎯 HIGH PRIORITY#
Current Pain Points:#
No visual feedback during long operations
- NDK download (600MB+) shows only percentage
- Build processes are silent until completion
- No ETA, download speed, or file size information
Error messages are cryptic
- “gogio build failed: exit status 1” - what went wrong?
- No actionable guidance on how to fix issues
- Stack traces instead of user-friendly messages
No progress visibility
- Multi-platform builds: which platform is building?
- Icon generation: which files being created?
- No way to cancel long operations gracefully
Proposed Solutions:#
A. Rich Terminal UI
// Use charmbracelet/bubbletea for interactive TUI
type BuildProgress struct {
Platform string
Stage string // "Dependencies", "Compilation", "Packaging"
Progress float64
CurrentFile string
Speed string // "15 MB/s"
ETA time.Duration
}
// Example output:
// ╭─ Building gio-plugin-webviewer ─────────────────╮
// │ Platform: Android │
// │ Stage: Compiling Go code │
// │ Progress: [████████████░░░░░░] 65% │
// │ File: webview_android.go │
// │ ETA: 45 seconds │
// ╰──────────────────────────────────────────────────╯B. Structured Logging
// Use zerolog or similar for structured logging
log.Info().
Str("platform", "android").
Str("app", "webviewer").
Str("stage", "icons").
Msg("Generating platform icons")
// With --verbose flag, show detailed info
// Without it, show clean progress barsC. Error Recovery Suggestions
type BuildError struct {
Phase string
Error error
Suggestions []string
DocsURL string
}
// Example:
// ❌ Build failed: NDK compiler not found
//
// Suggestions:
// 1. Install Android NDK: utm-dev install ndk-bundle
// 2. Check SDK path: utm-dev config
// 3. Verify NDK version >= r19c
//
// More info: https://docs.utm-dev.dev/errors/ndk-not-found2. Build Performance ⚡ HIGH PRIORITY#
Current Issues:#
- No incremental builds - rebuilds everything every time
- No build caching - same code compiled repeatedly
- Sequential icon generation - could be parallel
- No concurrent platform builds -
build allis sequential
Proposed Solutions:#
A. Smart Dependency Tracking
// Hash-based build cache
type BuildCache struct {
SourceHash string // Hash of all .go files
DepsHash string // Hash of go.mod + go.sum
IconHash string // Hash of icon-source.png
Binary string // Path to cached binary
BuildTime time.Time
}
// Skip rebuild if hashes match
if cache.IsValid() && !forceRebuild {
log.Info("Using cached build from", cache.BuildTime)
return cache.Binary
}B. Parallel Builds
// Build multiple platforms concurrently
func buildAll(platforms []string) error {
results := make(chan BuildResult, len(platforms))
for _, platform := range platforms {
go func(p string) {
results <- buildPlatform(p)
}(platform)
}
// Collect results and show progress
return collectResults(results, len(platforms))
}
// Parallel icon generation
func generateIcons(platform string) error {
var wg sync.WaitGroup
sizes := getIconSizes(platform)
for _, size := range sizes {
wg.Add(1)
go func(s IconSize) {
defer wg.Done()
generateIcon(s)
}(size)
}
wg.Wait()
}C. Docker-Based Build Cache
# .goup-cache/
# ├── go-build/ # Go build cache
# ├── go-mod/ # Module cache
# ├── binaries/ # Built binaries
# └── icons/ # Generated icons
# Mount these in Docker builds for consistency
volumes:
- .goup-cache/go-build:/go/pkg
- .goup-cache/go-mod:/go/pkg/mod3. Configuration & Customization ⚙️ MEDIUM PRIORITY#
Current Limitations:#
- No project-specific config file
- Can’t customize build flags per platform
- No way to set app metadata (version, bundle ID, etc.)
- Icons hardcoded to icon-source.png
Proposed Solutions:#
A. Project Configuration File
# goup.yaml (or .utm-dev.yaml)
project:
name: my-hybrid-app
version: 1.0.0
description: "A cross-platform hybrid app"
build:
# Global build settings
parallel: true
cache: true
verbose: false
# Platform-specific settings
platforms:
android:
package: com.example.myapp
minSDK: 24
targetSDK: 34
permissions:
- INTERNET
- ACCESS_NETWORK_STATE
signing:
keystore: ./release.keystore
alias: myapp
ios:
bundleID: com.example.myapp
team: ABCDEFG123
minVersion: 14.0
capabilities:
- Push Notifications
- WebView
macos:
bundleID: com.example.myapp
category: public.app-category.productivity
minVersion: 11.0
windows:
publisher: "My Company"
displayName: "My Hybrid App"
capabilities:
- internetClient
# Custom build flags
flags:
ldflags: "-s -w" # Strip debug info
tags: "release"
assets:
icons:
source: "./assets/icon.png"
foreground: "./assets/icon-fg.png" # Android adaptive
background: "./assets/icon-bg.png"
splash:
source: "./assets/splash.png"
dependencies:
go: "1.25"
gio: "v0.8.0"
gio-plugins: "v0.8.0"B. CLI Overrides
# Override config from command line
utm-dev build android \
--package com.test.myapp \
--min-sdk 26 \
--signing-key ./debug.keystore \
--verbose
# Profile-based builds
utm-dev build android --profile debug
utm-dev build android --profile release
utm-dev build android --profile staging4. Testing & Deployment 🚀 MEDIUM PRIORITY#
Missing Features:#
- No automated testing on target platforms
- No deployment helpers
- No CI/CD integration examples
- No simulator/emulator automation
Proposed Solutions:#
A. Automated Testing
# Run on simulators/emulators
utm-dev test ios --simulator "iPhone 15 Pro"
utm-dev test android --emulator "Pixel_8_API_34"
# Screenshot testing
utm-dev test --screenshots ./screenshots/
# Integration with standard Go tests
utm-dev test --platform all --coverageB. Deployment Commands
# Install to connected device
utm-dev deploy ios --device "John's iPhone"
utm-dev deploy android --device adb-device-id
# Upload to stores
utm-dev deploy appstore --testflight
utm-dev deploy playstore --internal-testing
# Generate store assets
utm-dev assets screenshots --platforms ios,android
utm-dev assets store-listingC. CI/CD Templates
# .github/workflows/build.yml (generated)
name: Build Multi-Platform
on: [push]
jobs:
build:
strategy:
matrix:
platform: [ios, android, macos, windows]
runs-on: ${{ matrix.platform == 'ios' && 'macos-latest' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
- uses: utm-dev/setup@v1
- run: utm-dev build ${{ matrix.platform }}
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-build
path: .bin/5. Documentation & Discoverability 📚 HIGH PRIORITY#
Current Gaps:#
- No interactive getting started
- Examples are minimal
- No cookbook/recipes
- Hard to discover features
Proposed Solutions:#
A. Interactive Setup
# New project wizard
$ utm-dev init
Welcome to utm-dev! Let's create your hybrid app.
? Project name: my-awesome-app
? Description: A cross-platform hybrid application
? Target platforms: (use space to select)
[x] iOS
[x] Android
[x] macOS
[ ] Windows
[ ] Linux
[x] Web
? Use webview for content? Yes
? Include example code? Yes
? Initialize git repository? Yes
✓ Created project structure
✓ Generated goup.yaml
✓ Created example code
✓ Initialized git repository
Next steps:
cd my-awesome-app
utm-dev build ios
utm-dev dev # Start development serverB. Rich Examples
examples/
├── hello-world/ # Minimal Gio app
├── webview-browser/ # ✓ Already exists
├── hybrid-dashboard/ # NEW: Gio UI + web charts
├── native-webview-comm/ # NEW: Go ↔ JS bridge patterns
├── offline-first/ # NEW: IndexedDB + Go backend
├── camera-integration/ # NEW: Native camera + Go
├── push-notifications/ # NEW: FCM/APNs integration
└── oauth-flow/ # NEW: OAuth with webviewC. Command Discoverability
# Smart suggestions
$ utm-dev buidl ios # typo
Did you mean: build ios?
# Contextual help
$ utm-dev build
Error: missing platform argument
Available platforms:
ios Build for iOS devices
android Build for Android
macos Build for macOS
windows Build for Windows
all Build for all platforms
Examples:
utm-dev build ios ./my-app
utm-dev build android --release
Run 'utm-dev build --help' for more information.6. Webview Integration Improvements 🌐 HIGH PRIORITY#
This is THE core feature - needs to be bulletproof.
Current Limitations:#
- No Go ↔ JavaScript bridge examples
- No debugging tools
- Platform differences not documented
- No TypeScript definitions for bridge
Proposed Solutions:#
A. Declarative Bridge API
// Expose Go functions to JavaScript
bridge := webview.NewBridge()
// Type-safe function exposure
bridge.Expose("getUserProfile", func(userID string) (*UserProfile, error) {
return db.GetUser(userID)
})
bridge.Expose("saveData", func(data map[string]interface{}) error {
return db.Save(data)
})
// JavaScript can now call:
// const profile = await window.goup.getUserProfile("user123")
// await window.goup.saveData({foo: "bar"})B. TypeScript Definitions Generator
# Generate TypeScript definitions from Go code
$ utm-dev bridge generate-types
# Generates: ./web/src/goup-bridge.d.ts
declare namespace Goup {
function getUserProfile(userID: string): Promise<UserProfile>
function saveData(data: Record<string, any>): Promise<void>
interface UserProfile {
id: string
name: string
email: string
}
}C. DevTools Integration
// Enable Chrome DevTools for webview
if debug {
webview.EnableDevTools(true)
webview.EnableNetworkInspection(true)
webview.EnableConsoleForwarding(true)
}
// Forward console.log to Go logger
webview.OnConsoleMessage(func(level, message string) {
log.Debug().Str("source", "webview").Str("level", level).Msg(message)
})D. Hot Reload for Web Content
# Development mode with hot reload
$ utm-dev dev --platform macos
✓ Building app...
✓ Starting file watcher...
✓ App launched
✓ Web content server running on http://localhost:3000
# When HTML/CSS/JS changes:
✓ Detected change: index.html
✓ Reloading webview...7. Cross-Compilation & Builds 🏗️ MEDIUM PRIORITY#
Current Issues:#
- Linux cross-compile from macOS fails (CGo)
- Windows cross-compile not tested
- No Docker build support
- No remote build service
Proposed Solutions:#
A. Docker-Based Builds
# Build in Docker for consistent environment
utm-dev build linux --docker
utm-dev build windows --docker
# Uses official build containers:
# - golang:1.25-bullseye for Linux
# - golang:1.25-windowsservercore for WindowsB. Remote Build Service (Future)
# Use cloud builders for platforms you don't have
utm-dev build ios --remote
utm-dev build windows --remote
# Uses:
# - GitHub Actions
# - CircleCI
# - Or self-hosted build farmC. Better CGo Handling
# Detect CGo issues early
utm-dev check --platform linux
⚠ Warning: Cross-compiling to Linux from macOS requires Docker
Reason: CGo dependencies cannot be cross-compiled
Options:
1. Use Docker: utm-dev build linux --docker
2. Build on Linux: Use CI/CD or remote build
3. Disable CGo: Set CGO_ENABLED=0 (may lose some features)8. Plugin System 🔌 LOW PRIORITY (Future)#
Allow extending utm-dev with custom commands and hooks.
// ~/.utm-dev/plugins/my-plugin/plugin.go
package main
import "github.com/joeblew999/utm-dev/sdk/plugin"
type MyPlugin struct{}
func (p *MyPlugin) Commands() []plugin.Command {
return []plugin.Command{
{
Name: "deploy-firebase",
Run: func(args []string) error {
// Custom deployment logic
},
},
}
}
func (p *MyPlugin) Hooks() []plugin.Hook {
return []plugin.Hook{
{
Event: "post-build",
Run: func(ctx plugin.Context) error {
// Run after every build
},
},
}
}
func main() {
plugin.Serve(&MyPlugin{})
}9. Analytics & Telemetry 📊 LOW PRIORITY#
Opt-in telemetry to improve tool development.
# Opt-in to anonymous usage analytics
utm-dev telemetry enable
# Helps us understand:
# - Which platforms are most used
# - Build times and failure rates
# - Feature usage
# - Error patterns
# Always opt-in, always anonymous
utm-dev telemetry status
utm-dev telemetry disableImplementation Roadmap#
Phase 1: Developer Experience (Q1 2025)#
Goal: Make utm-dev delightful to use
- ✅ Rich terminal UI with progress bars
- ✅ Better error messages with suggestions
- ✅ Project config file (goup.yaml)
- ✅ Interactive
utm-dev init - ✅ Command improvements and discoverability
Impact: 10x better developer experience
Phase 2: Performance & Reliability (Q2 2025)#
Goal: Make builds fast and reliable
- ✅ Incremental builds with caching
- ✅ Parallel platform builds
- ✅ Parallel icon generation
- ✅ Docker build support
- ✅ Better cross-compilation
Impact: 5-10x faster builds
Phase 3: Webview Excellence (Q3 2025)#
Goal: Best-in-class hybrid app support
- ✅ Go ↔ JavaScript bridge API
- ✅ TypeScript definitions generator
- ✅ DevTools integration
- ✅ Hot reload for web content
- ✅ Comprehensive examples
Impact: Production-ready hybrid apps
Phase 4: Testing & Deployment (Q4 2025)#
Goal: End-to-end workflow
- ✅ Automated testing on simulators
- ✅ Deployment commands
- ✅ CI/CD templates
- ✅ Screenshot automation
- ✅ Store submission helpers
Impact: Complete development workflow
Phase 5: Ecosystem (2026)#
Goal: Community-driven growth
- ✅ Plugin system
- ✅ Community plugins
- ✅ Plugin marketplace
- ✅ Template library
- ✅ Analytics (opt-in)
Impact: Thriving ecosystem
Quick Wins (Implement First)#
Week 1: Better Feedback#
// Replace silent builds with rich output
import "github.com/charmbracelet/bubbletea"
import "github.com/schollz/progressbar/v3"
// Show download progress with size, speed, ETA
bar := progressbar.NewOptions(downloadSize,
progressbar.OptionSetDescription("Downloading NDK"),
progressbar.OptionShowBytes(true),
progressbar.OptionShowCount(),
progressbar.OptionSetPredictTime(true),
)Week 2: Config File#
// Add goup.yaml support
type Config struct {
Project ProjectConfig
Build BuildConfig
Assets AssetsConfig
}
// Read and merge with CLI flags
config := LoadConfig("goup.yaml")
config = MergeWithFlags(config, cliFlags)Week 3: Better Errors#
// Structured errors with context
type BuildError struct {
Phase string
Platform string
Error error
Suggestions []string
DocsURL string
}
// User sees:
// ❌ Build failed during: Compilation
// Platform: android
// Error: NDK compiler not found
//
// Try:
// utm-dev install ndk-bundle
// utm-dev config # verify SDK pathWeek 4: Parallel Builds#
// Build icons in parallel
var wg sync.WaitGroup
for _, size := range iconSizes {
wg.Add(1)
go generateIcon(size, &wg)
}
wg.Wait()
// 5-10x faster icon generationMetrics for Success#
Developer Experience#
- ⏱️ Time to first successful build < 5 minutes
- 📝 Documentation clarity score > 9/10
- 😊 User satisfaction > 90%
Performance#
- 🚀 Build time reduction: 50%+
- 💾 Cache hit rate: > 80%
- ⚡ Icon generation: < 1 second
Adoption#
- 👥 Active users: 1000+ in year 1
- ⭐ GitHub stars: 500+
- 🐛 Issue resolution time: < 7 days
Conclusion#
utm-dev has proven the concept: Pure Go hybrid apps ARE possible and work on real devices.
The next step: Transform from “it works” to “it’s amazing to use”.
Priority order:
- Developer Experience - make it delightful
- Webview Integration - make it powerful
- Performance - make it fast
- Testing/Deployment - make it complete
- Ecosystem - make it extensible
This is achievable. Each phase builds on the previous, and quick wins can be implemented immediately while planning larger features.
The vision: The best way to build cross-platform hybrid applications in Go.