Written by: ekwoster.dev on Tue Aug 19

๐Ÿ”ฅ From Arduino to Mars: Why You Should Be Using TinyGo for Embedded Web Development

๐Ÿ”ฅ From Arduino to Mars: Why You Should Be Using TinyGo for Embedded Web Development

Cover image for ๐Ÿ”ฅ From Arduino to Mars: Why You Should Be Using TinyGo for Embedded Web Development

๐Ÿ”ฅ From Arduino to Mars: Why You Should Be Using TinyGo for Embedded Web Development

If youโ€™ve ever attempted to build something that lives at the intersection of embedded systems and the modern web โ€” say, a microcontroller that serves a WASM-powered control dashboard over HTTP โ€” youโ€™ve probably run into some harsh realities:

  • C is painful.
  • Rust is powerful, but finding embedded libraries that just work is a chore.
  • JavaScript, while king of the browser, isnโ€™t welcome on your $2 MCU.

Is there a better way? What if you could use Go, a modern compiled systems language with safe memory handling and a thriving toolset, to build for microcontrollers AND compile to WebAssembly (WASM)?

Let me introduce you to TinyGo โ€” the smallest, fiercest, and most fun way to build projects that live somewhere between the clouds and your breadboard.


๐Ÿš€ What is TinyGo?

TinyGo is a Go compiler for small places โ€” literally. It allows you to run Go programs on microcontrollers like the Arduino Nano 33, Raspberry Pi Pico, or even run WASM blobs in no_std environments.

Key features:

  • โœจ Drop-in Go syntax (not all of it, but enough)
  • ๐Ÿ“ฆ Cross-compilation to many MCUs (AVR, ARM Cortex-M0+, RISCV)
  • ๐Ÿ•ธ Compiles to WASM โ€” and the output is small (weโ€™re talking kilobytes)
  • ๐Ÿ”ฅ Integrates with Visual Studio Code and common Go tooling

๐Ÿงช The Experiment: Live Dashboard + Sensor on the Same Microcontroller

Let me show you a crazy-cool idea: what if a single microcontroller could both read sensor data and serve a WASM web UI to visualize it in real time?

Imagine a soil moisture sensor that hosts its own dashboard. No Raspberry Pi. No external web server. Just one board.

We'll build:

  1. A TinyGo app that:

    • Reads values from a DHT11 sensor (humidity + temperature)
    • Hosts a tiny HTTP server when connected via USB serial or WiFi (ESP32 anyone?)
    • Serves a WASM + HTML dashboard built from the same Go source
  2. A frontend dashboard written using syscall/js in Go and compiled to WASM


๐Ÿ“ฆ Setting Up TinyGo

brew tap tinygo-org/tools
brew install tinygo

# OR install via Go:
go install github.com/tinygo-org/tinygo@latest

To target a device:

tinygo flash -target=arduino-nano33 path/to/main.go

To target WASM:

tinygo build -o static/main.wasm -target=wasm ./wasm-ui

๐Ÿ”Œ Reading the Sensor (main.go)

package main

import (
  "machine"
  "time"
  "fmt"
)

func main() {
  sensor := machine.D2  // digital pin 2
  sensor.Configure(machine.PinConfig{Mode: machine.PinInput})

  for {
    reading := sensor.Get()  // fake reading; insert actual DHT11 logic here
    fmt.Printf("Sensor reading: %t\n", reading)
    time.Sleep(time.Second * 2)
  }
}

Weโ€™re keeping it simple, but you can connect I2C or SPI sensors and use libraries like tinygo-org/drivers.


๐ŸŒ Serving the WASM UI from the MCU

Using a minimal HTTP server (WiFi or serial-over-USB):

import (
  "net/http"
  "embed"
)

//go:embed static/*
var static embed.FS

func main() {
  http.Handle("/", http.FileServer(http.FS(static)))
  http.ListenAndServe(":8080", nil)
}

Note: This is pseudo-code. Not all boards support Go's net/http. For truly tiny devices, youโ€™d embed the HTTP binary with a lightweight TCP server or make the browser request data over serial.


๐Ÿ–ฅ Building the WASM Dashboard

Structure:

wasm-ui/
โ”œโ”€โ”€ main.go
โ””โ”€โ”€ index.html

main.go (WASM)

package main

import (
  "syscall/js"
)

func renderData(this js.Value, args []js.Value) interface{} {
  document := js.Global().Get("document")
  div := document.Call("getElementById", "sensor")
  div.Set("innerText", "Temperature: 24ยฐC\nHumidity: 60%")
  return nil
}

func main() {
  js.Global().Set("renderData", js.FuncOf(renderData))

  // Call once on load
  renderData(js.Null(), nil)

  // Keep it alive
  select {}
}

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="wasm_exec.js"></script>
</head>
<body>
  <h1>๐Ÿ“ˆ Sensor Dashboard</h1>
  <div id="sensor"></div>

  <script>
    const go = new Go();
    WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
      go.run(result.instance);
      window.renderData();
    });
  </script>
</body>
</html>

๐Ÿง  Why This Is A Game Changer

  • Traditionally, embedded devices are data slaves โ€” sending sensor data elsewhere for visualization.
  • But with TinyGo + WASM, your device owns the whole stack.
  • This pattern is incredibly useful for remote sensors, pop-up local networks, event-driven instruments, and hackathon hardware!

๐Ÿงฑ Real World Uses

  • ๐Ÿ• Off-grid weather stations that host their own progressive web apps
  • ๐Ÿซ Classroom science kits that broadcast dashboards over local WiFi
  • ๐Ÿ‘จโ€๐Ÿš€ Remote devices serving diagnostics in space or on edge networks
  • ๐Ÿ’ก Smart IoT devices with no back-end reliance

๐Ÿšง Gotchas & Caveats

  • TinyGo still doesnโ€™t support Go 1.22 fully โ€” check compatibility
  • Performance is great on fast boards, shaky on tiny AVR 8-bit ones
  • syscall/js is verbose, but Goโ€™s generics and structs donโ€™t yet work fully in WASM mode

๐Ÿ”ฎ Conclusion

TinyGo is a secret weapon for developers who dream of merging hardware and the web with one elegant system. Programming microcontrollers used to require learning archaic C, vendor-specific SDKs, and crossing your fingers on every flash.

But now? You get modern tooling, great readability, and the power of Go in the smallest places โ€” or even straight into your browser.

So try it. Grab a $4 board, install TinyGo, and go build your next project that lives between copper and cloud โ˜๏ธโšก.


๐Ÿ“š Resources


๐Ÿ› ๏ธ If you're looking to prototype hardware + web apps fast and smart โ€” we offer just the kind of embedded fullstack help you need.