{"slug": "make-hardware-personal", "title": "Make Hardware Personal", "summary": "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.", "body_md": "GeaStack Open source\n\n[Explore the source ↗](https://github.com/geastack)\n\n# Make hardware\n\npersonal.\n\nWe let you write it in TypeScript, JSX, and CSS.\n\nGeaStack brings [Gea’s reactive UI](https://geajs.com/) to devices. Our [geatsc compiler](https://github.com/geastack/compiler) turns supported app code into C++, and the [gea CLI](https://github.com/geastack/cli) handles browser previews, native builds, and flashing.\n\n[Build with your coding agent →](#op-agent-label)\n\nWhy GeaStack\n\n## From a web framework to our own devices.\n\n### JavaScript is enough.\n\nWe 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](https://geajs.com/) for the web around that belief.\n\nIn 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.\n\nGea remains an independent web framework, with its own [examples and benchmarks](https://geajs.com/). 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.\n\n### Then we wanted to take it onto a guitar.\n\nWe 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.\n\nThat guitar work also led to [CoyoPedal](https://github.com/dashersw/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](https://coyopedal.playtaurus.com/) or [read how we made NAM A2-Full fit on the chip](https://playtaurus.com/blog/running-nam-a2-full-natively-on-an-esp32-s3).\n\n### The app had to run on a small chip.\n\nOn 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](https://github.com/geastack/compiler)**, our TypeScript-to-C++ compiler, comes in: it translates supported application code into C++, which the board’s toolchain builds into firmware.\n\nWe used that path to build touch interfaces and brought familiar web APIs to embedded devices. Some examples are [`fetch`](https://geastack.com/docs-tutorials-esp32-04-network-request.html) for network requests, [Canvas 2D](https://geastack.com/docs-concepts-canvas.html) for drawing, and [`localStorage`](https://geastack.com/docs-concepts-components-and-state.html#persisting-state) for saving state.\n\n### From a small screen to native desktop apps.\n\nThe 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.\n\nOn macOS, that includes real [AppKit controls](https://github.com/geastack/apple). Our [Notes demo](https://github.com/geastack/examples/tree/main/apps/notes-native) 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.\n\n### Then we took a Three.js game to Xbox.\n\nWe also wanted to bring browser game development to native targets. We compiled [Three.js](https://threejs.org/) games for Xbox, including [Aviator and SkyTail](#example-xbox), the game featuring our coyote mascot. The launch walkthrough shows SkyTail running on both Xbox and macOS.\n\nThe compiler opened another direction: [native HTTP services](https://github.com/geastack/node-compat). We could compile supported Node-style server code and measure it against the same code running in Node.js. The [benchmarks](#op-bench) show throughput, memory, startup, and latency together.\n\nXbox support is experimental and the repo is private. [Watch the Xbox and SkyTail walkthrough →](#example-xbox)\n\n### And we ended up building GeaStack.\n\nWhat started with a guitar controller became a way to build native applications in TypeScript, from an ESP32 to an Xbox. We brought the [framework](https://github.com/geastack/core), [compiler](https://github.com/geastack/compiler), and [device targets](#op-targets) together as GeaStack, so you can use them to build your own apps.\n\nWe invite all of you to build cool stuff with it. Our [public repositories](https://github.com/geastack) are open source, each under its own [licence](https://geastack.com/license.html#licences), and we’d love to see your contributions. Share what you’re building in our [Discord](https://discord.gg/aKNbDU7hW), report an issue, or send a pull request.\n\n### We believe in PERSONALIZED\n\nHARDWARE.\n\nCode\n\n## From app state to native code.\n\nWith GeaStack, we write the app in TypeScript, JSX, and CSS, then compile it for the device.\n\n### Store\n\n#### counter-store.ts\n\n``` js\nimport { Store } from '@geastack/core'\n\nclass CounterStore extends Store {\n  count = 0\n\n  increment() {\n    this.count = this.count + 1\n  }\n}\n\nexport const counter = new CounterStore()\n```\n\nWe use a [`Store`](https://geastack.com/docs-concepts-components-and-state.html#reactivecomponent-or-store) when several components need the same state. If only `App` needs the count, we can keep it on the [`ReactiveComponent`](https://geastack.com/docs-concepts-components-and-state.html#reactivecomponent-or-store) itself.\n\n### Component\n\n#### App.tsx\n\n``` js\nimport { ReactiveComponent } from '@geastack/core'\nimport { counter } from './counter-store'\nimport './styles.css'\n\nexport class App extends ReactiveComponent {\n  template() {\n    return (\n      <div class=\"screen\">\n        <span class=\"count\">{counter.count}</span>\n        <button onClick={() => counter.increment()}>\n          +\n        </button>\n      </div>\n    )\n  }\n}\n```\n\nPressing **+** calls `counter.increment()`. Gea updates the displayed count when the store changes.\n\nShortened from [the shared-store counter tutorial](https://geastack.com/docs-tutorials-esp32-02-counter-store.html). Follow it for the complete app and styles.\n\n### Compiling for the device\n\n[geatsc](https://github.com/geastack/compiler) and our [Gea compiler plugin](https://github.com/geastack/core/tree/main/packages/geatsc-plugin-gea) 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.\n\n1. **App source** Stores, components, and CSS\n2. **[geatsc](https://github.com/geastack/compiler) + Gea plugin** Generate C++ and UI bindings\n3. **[Target toolchain](#op-targets)** Build with the[runtime](https://github.com/geastack/core) and[device APIs](https://geastack.com/docs-packages-host.html)\n4. **Native app or firmware** Run on the selected device\n\nWe keep layout and appearance in [CSS](https://geastack.com/docs-concepts-styling.html), with [Canvas 2D](https://geastack.com/docs-concepts-canvas.html) for custom drawing. Supported styles and APIs depend on the target.\n\nWhere would you run your app?\n\n[Compare the targets →](#op-targets)\n\nTargets\n\n## Choose where it runs.\n\nTaking 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.\n\n- NATIVE / EMBEDDEDEmbedded\n- [ESP32 & RP2350](https://github.com/geastack/targets) firmware with Gea rendering and board-specific input and drivers. Flash over USB; update supported boards over Bluetooth or Wi-Fi.[@geastack/targets on npm ↗](https://www.npmjs.com/package/@geastack/targets)Agent skills: [Build an app ↗](https://github.com/geastack/skills/blob/main/geastack-embedded-app-builder/SKILL.md)[Custom boards ↗](https://github.com/geastack/skills/blob/main/geastack-embedded-custom-boards/SKILL.md)[Add a target ↗](https://github.com/geastack/skills/blob/main/geastack-embedded-target-bringup/SKILL.md)[OTA updates ↗](https://github.com/geastack/skills/blob/main/geastack-embedded-ota/SKILL.md)\n- NATIVE / APPLEmacOS & iOS\n- [Native Mac and iPhone apps](https://github.com/geastack/apple) using AppKit and UIKit integrations. Requires Xcode; device builds also need signing setup.[@geastack/apple on npm ↗](https://www.npmjs.com/package/@geastack/apple)\n- NATIVE / WINDOWSWindows\n- The [Win32 target](https://github.com/geastack/windows) turns Gea components into Windows controls, such as buttons and text fields.[@geastack/windows on npm ↗](https://www.npmjs.com/package/@geastack/windows)\n- NATIVE / LINUXLinux\n- The [Linux target](https://github.com/geastack/linux) uses the shared Gea raster pipeline with SDL2. Current focus: Raspberry Pi OS on Raspberry Pi 5.[@geastack/linux on npm ↗](https://www.npmjs.com/package/@geastack/linux)\n- NATIVE / EXPERIMENTALXbox Series X/S Experimental\n- We build apps for consoles with Developer Mode enabled, including controller input and audio. We use Microsoft’s UWP app format and Direct3D graphics through ANGLE. The repo is currently private. [Watch the Xbox demo →](#example-xbox)\n- WEB / DEVELOPMENTBrowser\n- The [simulator and web target](https://github.com/geastack/simulator) let you preview an app on your computer. We test how its drawing and input compare with device behaviour.[@geastack/simulator on npm ↗](https://www.npmjs.com/package/@geastack/simulator)Agent skill: [App builder and web preview ↗](https://github.com/geastack/skills/blob/main/geastack-embedded-app-builder/SKILL.md)\n- WEBVIEW / ANDROIDAndroid\n- The [Android target](https://github.com/geastack/android) packages web-rendered Gea apps as an APK. The current renderer uses Android WebView.[@geastack/android on npm ↗](https://www.npmjs.com/package/@geastack/android)\n- NATIVE / SERVERNative services\n- [node-compat](https://github.com/geastack/node-compat) compiles supported Node-style HTTP services to native executables. We test response parity against Node.js.[@geastack/node-compat on npm ↗](https://www.npmjs.com/package/@geastack/node-compat)\n- NATIVE / GRAPHICS3D graphics\n- [native-webgl-angle](https://github.com/geastack/native-webgl-angle) connects Three.js to native graphics on macOS through ANGLE and Metal.[@geastack/native-webgl-angle on npm ↗](https://www.npmjs.com/package/@geastack/native-webgl-angle)\n\nRendering and API support vary by target. Native compilation, browser rendering, and Android WebView are distinct execution paths.\n\n[Browse all agent skills ↗](https://github.com/geastack/skills) · [Set up your coding agent →](#op-agent-label)\n\nYou can explore the app model before choosing hardware.\n\n[Start with a browser preview →](#op-start)\n\nGet started\n\n## Build your first app.\n\n[Full counter tutorial ↗](https://geastack.com/docs-tutorials-esp32-01-component-counter.html)\n\n### Build with your coding agent\n\nCopy this prompt into your agent. Our [skills](https://github.com/geastack/skills) cover app structure, supported APIs, styling, and the build workflow.\n\n### Or build the counter yourself\n\nOur [first embedded tutorial](https://geastack.com/docs-tutorials-esp32-01-component-counter.html) builds a touchscreen counter and installs it on a board over USB. We use a [Waveshare ESP32-S3 Touch AMOLED 2.06](https://geastack.com/docs-cli-boards.html) and a USB data cable. Other supported boards work with their own alias.\n\n1. \n01### Create the projectInstall the [CLI](https://www.npmjs.com/package/@geastack/cli) and start the project wizard:\n\n```\nnpm install --global @geastack/cli\ngea create component-counter\n```\n\n Choose **2, Example application** , then**1, Component Counter** from the gallery. The CLI creates the project, selects ESP32, enables BLE updates, and runs`npm install` .When it finishes, open the project folder: \n\n```\ncd component-counter\n```\n\n2. \n02### Look at the appThe project contains three source files and a font. The app extends `ReactiveComponent` , so changing`count` updates the number on screen.\n  - src/index.tsx\n  - Calls `mount(App)` to put the app on screen.\n  - src/App.tsx\n  - Holds the counter state, button handlers, and JSX.\n  - src/styles.css\n  - Defines the layout, colours, and font.\n [Read the complete component and styles in the tutorial →](https://geastack.com/docs-tutorials-esp32-01-component-counter.html)\n3. \n03### Register the boardConnect your board over USB and run: \n\n```\ngea setup\n```\n\n Choose **1, Known supported board** , pick your board, and accept`amoled` 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 →](https://geastack.com/docs-tutorials-esp32-01-component-counter.html)\n4. \n04### Check, build and flashCheck the app and fix any type errors before building: \n\n```\nnpm run check\n```\n\n Then build the firmware and flash the board: \n\n```\ngea build\ngea flash --monitor\n```\n\n 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.\n\n### Keep building with the tutorial\n\nLessons 2 and 3 continue in the counter project. Lesson 4 starts a new app.\n\nExamples\n\n## See what we’ve built.\n\nThese 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.\n\nLaunch walkthrough · Xbox + devices\n\n### SkyTail & Xbox games\n\nWe 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.\n\nCanvas · maps\n\n### Maps on an ESP32\n\nPan and zoom OpenStreetMap tiles on a microcontroller using the [Canvas API](https://geastack.com/docs-concepts-canvas.html).\n\nNative controls · macOS\n\n### Native macOS Notes\n\nA split view, toolbar, and reactive store, written in TypeScript, JSX, and CSS.\n\nNetworking · ESP32\n\n### Weather on an AMOLED display\n\nA weather interface with live conditions and a forecast on an ESP32 board.\n\nCSS 3D · ESP32\n\n### CSS transforms on an ESP32\n\nA rotating cube built with CSS 3D transforms and rendered on the microcontroller.\n\n2D game · ESP32\n\n### Platformer on an ESP32\n\nWe run a 2D game with coins, jumps, and enemies on a microcontroller, using TypeScript, JSX, and CSS.\n\nTouch input · ESP32\n\n### Smart AC dial\n\nWe use touch input and reactive state to build a draggable climate-control dial on an ESP32.\n\nAdaptive UI · e-paper\n\n### Colour and e-paper displays\n\nWe adapt one app to a colour panel and an e-paper display using CSS media queries.\n\nBenchmarks\n\n## Measure the native path.\n\nNative compilation also gave us a way to build server applications. We tested a supported node:http app in Node.js and compiled with [geatsc](https://github.com/geastack/compiler), alongside Rust and C++ servers handling the same request. These results measure that HTTP workload on one host.\n\nEight workers per server. Memory is peak proportional set size (PSS), which apportions shared memory across processes.\n\n**2.25×** Raw HTTP throughput vs Node\n\n**6.6 MiB** Peak PSS · Node: 303.0 MiB\n\n**6 ms** Startup · Node: 143 ms, 8 workers\n\n| GET / · 8 workers · published npm packages · September 20, 2026 |  |  |  | \n|---|---|---|---|\n| Server | Requests / sec | Peak PSS | p99 latency | \n|---|---|---|---|\n| node:http / Gea | 265,873 | 6.6 MiB | 3.96 ms | \n| node:http / Node | 118,142 | 303.0 MiB | 3.38 ms | \n| Rust / axum | 215,753 | 4.2 MiB | 1.49 ms | \n| C++ / Drogon | 267,832 | 8.0 MiB | 3.05 ms | \n\np99 is the time within which 99% of requests completed, measured in the last round. Lower is better.\n\nLinux · Xeon E3-1231 v3 · Node 24.21.0 · [compiler 1.0.15](https://www.npmjs.com/package/@geastack/compiler/v/1.0.15) / [node-compat 1.0.11](https://www.npmjs.com/package/@geastack/node-compat/v/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.\n\n**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.\n\n[Full methodology, latency, controls, and raw results →](https://github.com/geastack/node-compat/blob/main/BENCHMARKS.md)\n\n### Embedded UI benchmarks\n\nWe’re also working on benchmarks comparing GeaStack’s performance with other embedded UI frameworks.\n\nFAQ\n\n## Frequently asked questions.\n\n## What can I build with it?\n\nWe 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](https://github.com/geastack/node-compat). The [Examples tab](#op-examples) shows concrete apps and their code.\n\n## Do I need to know C++ or electronics?\n\nWe write app code in TypeScript; the [compiler](https://github.com/geastack/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.\n\n## Can I compile any TypeScript project?\n\nSupport depends on the language features, packages, and APIs your app uses. See the [compatibility limits](https://geastack.com/license.html#limits) and how to check your code with the compiler.\n\n## Is the UI running in a browser?\n\nIt 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](https://geastack.com/license.html#rendering).\n\n## Do I need a board to start?\n\nYou can start with the [browser simulator](https://github.com/geastack/simulator). A physical device is still needed to check hardware-specific behaviour such as touch input, sensors, display timing, and flashing. The [embedded tutorials](https://github.com/geastack/tutorials/tree/main/embedded-tutorials) cover the first USB flash, state, Bluetooth updates, and network requests.\n\n## What about Node compatibility?\n\nWe compare supported HTTP behaviour with Node byte for byte: parsing, bodies, keep-alive, framing, streaming, and malformed input. Check our [parity suite](https://github.com/geastack/node-compat/tree/main/apps/http-parity) for what is covered.\n\n## Which licence applies?\n\nLicences differ by package. We list them on the [limits and licence page](https://geastack.com/license.html#licences), with links to the licence files and commercial licensing enquiries.\n\nRepos & packages\n\n## Find the pieces. Read the source.\n\nWe publish the tools and target integrations on npm. Start with [@geastack/cli](https://www.npmjs.com/package/@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.\n\n### Compiler & framework\n\n### Targets & runtimes\n\n#### [targets](https://github.com/geastack/targets)\n\nEmbedded boards, build and flash support, and OTA clients.\n\n#### [apple](https://github.com/geastack/apple)\n\nAppKit and UIKit targets and Apple SDK bindings.\n\n#### [windows](https://github.com/geastack/windows)\n\nWin32 controls and Windows SDK bindings.\n\n#### [linux](https://github.com/geastack/linux)\n\nGea raster rendering on Linux, focused on Raspberry Pi OS.\n\n#### [android](https://github.com/geastack/android)\n\nAndroid packaging for web-rendered Gea apps.\n\n#### [simulator](https://github.com/geastack/simulator)\n\nBrowser development loop and the web target.\n\n#### [node-compat](https://github.com/geastack/node-compat)\n\nNative runtime support for Node-style HTTP services.\n\n#### [native-webgl-angle](https://github.com/geastack/native-webgl-angle)\n\nWebGL through ANGLE and Metal for the Three.js path.\n\n### Examples & community\n\nIf something fails, open an issue in the relevant repo with the smallest example you can share, your target, package versions, and the build output.", "url": "https://wpnews.pro/news/make-hardware-personal", "canonical_source": "https://geastack.com/one-pager", "published_at": "2026-09-20 15:45:13+00:00", "updated_at": "2026-09-20 15:52:59.639119+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents"], "entities": ["GeaStack", "Gea", "geatsc", "gea CLI", "CoyoPedal", "ESP32-S3", "Three.js", "Xbox"], "alternates": {"html": "https://wpnews.pro/news/make-hardware-personal", "markdown": "https://wpnews.pro/news/make-hardware-personal.md", "text": "https://wpnews.pro/news/make-hardware-personal.txt", "jsonld": "https://wpnews.pro/news/make-hardware-personal.jsonld"}}