cd /news/developer-tools/make-hardware-personal · home topics developer-tools article
[ARTICLE · art-135183] src=geastack.com ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Make Hardware Personal

GeaStack launched an open-source toolchain that compiles TypeScript, JSX, and CSS into C++ for embedded devices, desktop apps, and consoles, built on the Gea reactive web framework. The stack includes the geatsc TypeScript-to-C++ compiler and the gea CLI for browser previews, native builds, and flashing, and was used to build the ESP32-S3-based CoyoPedal amp and effects processor and to compile Three.js games including Aviator and SkyTail for Xbox and macOS.

by read13 min views7 publishedSep 20, 2026
Make Hardware Personal
Image: source

GeaStack Open source

Explore the source ↗

personal.

We let you write it in TypeScript, JSX, and CSS.

GeaStack brings Gea’s reactive UI to devices. Our geatsc compiler turns supported app code into C++, and the gea CLI handles browser previews, native builds, and flashing.

Build with your coding agent →

Why GeaStack

From a web framework to our own devices. #

JavaScript is enough.

We believed the language already gave us the tools to model an app. Classes keep state and behaviour together, properties hold values, methods change them, and getters calculate derived values. We built Gea for the web around that belief.

In Gea, stores are reactive classes. You change their data directly with code like this.count++ or this.users.push(user). Components describe the interface in JSX, and CSS handles its appearance. Gea analyses JSX at build time and generates the DOM update code. Its runtime observes state changes and applies those updates, taking the repetitive wiring out of application code.

Gea remains an independent web framework, with its own examples and benchmarks. Its apps run as JavaScript in the browser. We wanted to carry that way of writing apps onto our own hardware, which became the starting point for GeaStack.

Then we wanted to take it onto a guitar.

We play MIDI guitar and wanted a controller we could attach to our guitar to manage sounds while playing. We already had a way of building interfaces that we liked. We wanted to use that same approach on a small device, which meant taking Gea’s application model beyond the browser.

That guitar work also led to CoyoPedal, our open-source ESP32-S3 amp and effects processor. Its GeaStack touchscreen UI runs alongside a dedicated audio engine. You can play the browser version or read how we made NAM A2-Full fit on the chip.

The app had to run on a small chip.

On an ESP32, memory and processing time are tight. We wanted to keep writing TypeScript, JSX, and CSS while running compiled code on the device. That is where geatsc, our TypeScript-to-C++ compiler, comes in: it translates supported application code into C++, which the board’s toolchain builds into firmware.

We used that path to build touch interfaces and brought familiar web APIs to embedded devices. Some examples are fetch for network requests, Canvas 2D for drawing, and localStorage for saving state.

From a small screen to native desktop apps.

The next step was to bring the same development model to desktop and mobile platforms, so you can use the same codebase across supported targets and compile it natively where a native target is available. Each target supplies the rendering, input, and platform APIs the app needs.

On macOS, that includes real AppKit controls. Our Notes demo uses native views and a toolbar, with application state and interface code written in TypeScript and JSX. Gea still manages the reactive UI; the target connects it to the operating system.

Then we took a Three.js game to Xbox.

We also wanted to bring browser game development to native targets. We compiled Three.js games for Xbox, including Aviator and SkyTail, the game featuring our coyote mascot. The launch walkthrough shows SkyTail running on both Xbox and macOS.

The compiler opened another direction: native HTTP services. We could compile supported Node-style server code and measure it against the same code running in Node.js. The benchmarks show throughput, memory, startup, and latency together.

Xbox support is experimental and the repo is private. Watch the Xbox and SkyTail walkthrough →

And we ended up building GeaStack.

What started with a guitar controller became a way to build native applications in TypeScript, from an ESP32 to an Xbox. We brought the framework, compiler, and device targets together as GeaStack, so you can use them to build your own apps.

We invite all of you to build cool stuff with it. Our public repositories are open source, each under its own licence, and we’d love to see your contributions. Share what you’re building in our Discord, report an issue, or send a pull request.

We believe in PERSONALIZED

HARDWARE.

Code

From app state to native code. #

With GeaStack, we write the app in TypeScript, JSX, and CSS, then compile it for the device.

Store

counter-store.ts

import { Store } from '@geastack/core'

class CounterStore extends Store {
  count = 0

  increment() {
    this.count = this.count + 1
  }
}

export const counter = new CounterStore()

We use a Store when several components need the same state. If only App needs the count, we can keep it on the ReactiveComponent itself.

Component

App.tsx

import { ReactiveComponent } from '@geastack/core'
import { counter } from './counter-store'
import './styles.css'

export class App extends ReactiveComponent {
  template() {
    return (
      <div class="screen">
        <span class="count">{counter.count}</span>
        <button onClick={() => counter.increment()}>
          +
        </button>
      </div>
    )
  }
}

Pressing + calls counter.increment(). Gea updates the displayed count when the store changes.

Shortened from the shared-store counter tutorial. Follow it for the complete app and styles.

Compiling for the device

geatsc and our Gea compiler plugin compile the supported application code and its reactive UI into C++. The target’s toolchain builds it with the renderer and device APIs. On an ESP32, the resulting firmware runs without a JavaScript engine.

  1. App source Stores, components, and CSS
  2. geatsc + Gea plugin Generate C++ and UI bindings
  3. Target toolchain Build with theruntime anddevice APIs
  4. Native app or firmware Run on the selected device

We keep layout and appearance in CSS, with Canvas 2D for custom drawing. Supported styles and APIs depend on the target.

Where would you run your app?

Compare the targets →

Targets

Choose where it runs. #

Taking the same development model from an ESP32 to a Mac or Xbox needs a connection to each platform. We call that a target: its build tools, renderer, and host APIs. Application code can be shared, while controls and device-specific features may need target-specific work.

Rendering and API support vary by target. Native compilation, browser rendering, and Android WebView are distinct execution paths.

Browse all agent skills ↗ · Set up your coding agent →

You can explore the app model before choosing hardware.

Start with a browser preview →

Get started

Build your first app. #

Full counter tutorial ↗

Build with your coding agent

Copy this prompt into your agent. Our skills cover app structure, supported APIs, styling, and the build workflow.

Or build the counter yourself

Our first embedded tutorial builds a touchscreen counter and installs it on a board over USB. We use a Waveshare ESP32-S3 Touch AMOLED 2.06 and a USB data cable. Other supported boards work with their own alias.

01### Create the projectInstall the CLI and start the project wizard:

npm install --global @geastack/cli
gea create component-counter

Choose 2, Example application , then1, Component Counter from the gallery. The CLI creates the project, selects ESP32, enables BLE updates, and runsnpm install .When it finishes, open the project folder:

cd component-counter

02### Look at the appThe project contains three source files and a font. The app extends ReactiveComponent , so changingcount updates the number on screen.

03### Register the boardConnect your board over USB and run:

gea setup

Choose 1, Known supported board , pick your board, and acceptamoled as its alias. Confirm the USB connection, leave the optional OTA host/IP empty, and save the setup.Follow the board setup prompts in the tutorial → 4. 04### Check, build and flashCheck the app and fix any type errors before building:

npm run check

Then build the firmware and flash the board:

gea build
gea flash --monitor

The first build can take a few minutes. Once flashing finishes, tap the buttons on the display to change the count. Keep the USB cable connected for the next lessons. If you have several boards registered, add --board amoled to select this one.

Keep building with the tutorial

Lessons 2 and 3 continue in the counter project. Lesson 4 starts a new app.

Examples

See what we’ve built. #

These are some of the apps we built along the way: small-screen interfaces, native desktop controls, and games. Watch a device demo and follow its source link.

Launch walkthrough · Xbox + devices

SkyTail & Xbox games

We show SkyTail running on Xbox, build and flash an ESP32 app, and walk through native macOS interfaces. The launch stream explains the compiler, framework, and idea behind GeaStack.

Canvas · maps

Maps on an ESP32

Pan and zoom OpenStreetMap tiles on a microcontroller using the Canvas API.

Native controls · macOS

Native macOS Notes

A split view, toolbar, and reactive store, written in TypeScript, JSX, and CSS.

Networking · ESP32

Weather on an AMOLED display

A weather interface with live conditions and a forecast on an ESP32 board.

CSS 3D · ESP32

CSS transforms on an ESP32

A rotating cube built with CSS 3D transforms and rendered on the microcontroller.

2D game · ESP32

Platformer on an ESP32

We run a 2D game with coins, jumps, and enemies on a microcontroller, using TypeScript, JSX, and CSS.

Touch input · ESP32

Smart AC dial

We use touch input and reactive state to build a draggable climate-control dial on an ESP32.

Adaptive UI · e-paper

Colour and e-paper displays

We adapt one app to a colour panel and an e-paper display using CSS media queries.

Benchmarks

Measure the native path. #

Native compilation also gave us a way to build server applications. We tested a supported node:http app in Node.js and compiled with geatsc, alongside Rust and C++ servers handling the same request. These results measure that HTTP workload on one host.

Eight workers per server. Memory is peak proportional set size (PSS), which apportions shared memory across processes.

2.25× Raw HTTP throughput vs Node

6.6 MiB Peak PSS · Node: 303.0 MiB

6 ms Startup · Node: 143 ms, 8 workers

GET / · 8 workers · published npm packages · September 20, 2026
Server Requests / sec Peak PSS p99 latency
--- --- --- ---
node:http / Gea 265,873 6.6 MiB 3.96 ms
node:http / Node 118,142 303.0 MiB 3.38 ms
Rust / axum 215,753 4.2 MiB 1.49 ms
C++ / Drogon 267,832 8.0 MiB 3.05 ms

p99 is the time within which 99% of requests completed, measured in the last round. Lower is better.

Linux · Xeon E3-1231 v3 · Node 24.21.0 · compiler 1.0.15 / node-compat 1.0.11. wrk -t4 -c64, two 8-second rounds after warmup. Server and load generator share CPUs at 8 workers; these are host-limited HTTP results, not application-wide speedups.

Latency tradeoff: p99 was 3.96 ms native versus 3.38 ms on Node. Higher throughput did not produce lower tail latency in this run.

Full methodology, latency, controls, and raw results →

Embedded UI benchmarks

We’re also working on benchmarks comparing GeaStack’s performance with other embedded UI frameworks.

FAQ

Frequently asked questions. #

What can I build with it? #

We provide the pieces for screen-based apps such as weather displays, touch controls, notes apps, and games. We also have a native HTTP server path. The Examples tab shows concrete apps and their code.

Do I need to know C++ or electronics? #

We write app code in TypeScript; the compiler generates C++ for native builds. You can start in the browser without wiring a device. Working with hardware later involves choosing a supported board and following its setup. Custom drivers and target integrations may require C++ and platform SDK work.

Can I compile any TypeScript project? #

Support depends on the language features, packages, and APIs your app uses. See the compatibility limits and how to check your code with the compiler.

Is the UI running in a browser? #

It depends on the target. Embedded and native desktop builds render on the device; the browser and Android targets use a browser engine. See how each target renders the UI.

Do I need a board to start? #

You can start with the browser simulator. A physical device is still needed to check hardware-specific behaviour such as touch input, sensors, display timing, and flashing. The embedded tutorials cover the first USB flash, state, Bluetooth updates, and network requests.

What about Node compatibility? #

We compare supported HTTP behaviour with Node byte for byte: parsing, bodies, keep-alive, framing, streaming, and malformed input. Check our parity suite for what is covered.

Which licence applies? #

Licences differ by package. We list them on the limits and licence page, with links to the licence files and commercial licensing enquiries.

Repos & packages

Find the pieces. Read the source. #

We publish the tools and target integrations on npm. Start with @geastack/cli to create an app, then follow the setup for your target. Below, we’ve grouped the packages with their source repos so you can find what to install and where to contribute.

Compiler & framework

Targets & runtimes

targets

Embedded boards, build and flash support, and OTA clients.

apple

AppKit and UIKit targets and Apple SDK bindings.

windows

Win32 controls and Windows SDK bindings.

linux

Gea raster rendering on Linux, focused on Raspberry Pi OS.

android

Android packaging for web-rendered Gea apps.

simulator

Browser development loop and the web target.

node-compat

Native runtime support for Node-style HTTP services.

native-webgl-angle

WebGL through ANGLE and Metal for the Three.js path.

Examples & community

If something fails, open an issue in the relevant repo with the smallest example you can share, your target, package versions, and the build output.

── more in #developer-tools 4 stories · sorted by recency
── more on @geastack 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/make-hardware-person…] indexed:0 read:13min 2026-09-20 ·