# Starmoon: a solder-it-yourself ESP32 voice device the author has already deprecated

> Starmoon is a watch-sized conversational device built from an ESP32-S3 board, an I2S microphone and speaker, a NextJS frontend and a Python backend, with GPT-4o for the conversation, Deepgram for speech to text, Azure or Fish for text to speech and a HuggingFace model for emotion. The README opens by declaring the project deprecated and pointing at ElatoAI as its continuation.

**StarmoonAI/Starmoon** — A conversational, AI device + software framework for companionship, entertainment, education, healthcare, IoT applications, and DIY robotics. Built with Python, NextJS, Arduino, ESP32, LLMs (GPT-4o), Deepgram STT and Azure TTS 🤖

- Repository: https://github.com/StarmoonAI/Starmoon
- Website: https://www.elatoai.com
- Stars: 549 · Forks: 63
- Language: TypeScript
- License: GPL-3.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/starmoonai-starmoon

## The README opens by declaring the project deprecated and naming a successor

The first line of Starmoon is a status notice, and it is not a small one. The project states that it is no longer actively maintained, and that anyone who wants realtime multimodal voice AI on ESP32 and local devices should follow the work as it continues under ElatoAI, hosted at github.com/akdeb/ElatoAI. The stated reasons are specific: improved WiFi behaviour, better two-way voice AI audio reliability, global availability and a production-ready architecture. The repository metadata agrees with the notice in one direction and not the other. The project is not archived, so the code is still reachable, and the homepage field now points at elatoai.com rather than a Starmoon site. But the last push is dated 2026-03-27, there are no GitHub releases to pin to, and the licence is GPL-3.0 with 549 stars, 63 forks and 10 open issues. Nothing in the repository asks you to stop reading it; it asks you to stop expecting fixes.

## Provisioning means the device becomes its own WiFi access point

The step that shapes how the device behaves is the last one, not the first. You turn the unit on with the main button, wait for the LED to come on, then connect a phone, tablet or PC to a network named Starmoon-xxx and follow the instructions on it to set up an internet connection. The device hands you its own access point, you push credentials into it, and it joins your network. That approach is what lets a device with no display and no keyboard reach the internet at all, and it also fixes the ceiling: the instructions say it supports only 2.4 GHz WiFi, so a network that is 5 GHz only will not do. The hardware framing follows from the same idea of removing the screen. The device is described as only slightly larger than an Apple Watch, and reduced screen time is one of the stated reasons to build it, alongside cost, emotional voice analysis and the option to deploy locally and self-host. One gap worth stating: the setup walkthrough ends mid-sentence at the point where it tells you to connect the wifi by your credentials, so the steps after that are not written down here.

## Choosing a board is a source edit in two files

Starmoon ships for the Seeed Studio XIAO ESP32S3, and support for a generic ESP32-S3 board is a manual patch rather than a build flag. If you are on the plain chip you go to firmware/src/Config.h and uncomment one define while commenting another:

```cpp
// ----------------- Pin Definitions -----------------
// Define which board you are using (uncomment one)
#define USE_NORMAL_ESP32_S3
// #define USE_XIAO_ESP32_DEVKIT
// #define USE_XIAO_ESP32
// #define USE_NORMAL_ESP32
// #define USE_ESP32_S3_WHITE_CASE
```

Then you open firmware/platformio.ini and swap the build environment the same way:

```cpp
; [env:seeed_xiao_esp32s3]
; platform = espressif32
; board = seeed_xiao_esp32s3
; framework = arduino
; monitor_speed = 115200

[env:esp32-s3-devkitm-1]
platform = espressif32
board = esp32-s3-devkitm-1
framework = arduino
monitor_speed = 115200
```

Five board variants sit commented in that header, and the pin table is what makes the difference concrete. The I2S microphone pins are D0, D1 and D2 on the XIAO and GPIO 14, GPIO 1 and GPIO 4 on the generic board; the speaker needs D5, D6 and D4 against GPIO 5, GPIO 6 and GPIO 7, with the shutdown line on D3 marked N/A for the generic part. The RGB LED takes D7, D8 and D9 against GPIO 9, GPIO 8 and GPIO 13, and the button is D10 against GPIO 2. On the XIAO you can wire a lithium battery straight to the back of the ESP32.

## Firmware reaches the board through PlatformIO in VS Code

The flash path is four steps inside the editor rather than a command line. Open the PlatformIO icon in the VS Code sidebar, use Pick a folder, and point it at the firmware folder in the project, not the repository root. Then press Build in the PlatformIO toolbar, or run the build task. To get the result onto the board, connect the ESP32-S3 to the computer over USB and use the Upload button, or Upload and Monitor if you want the serial output attached. Both build environments the project ships set monitor_speed to 115200, which is the baud rate you will be reading at. None of this needs a separate toolchain install beyond the PlatformIO plugin and VS Code, which is the friendliest part of a project that otherwise assumes you have a soldering iron. It also means the firmware story stops at the device: there is no documented command anywhere in the project for flashing over the network, so every update after the first goes through USB again.

## The bill of materials is a list of part numbers and one STL file

The hardware section is a shopping list with links, and the cost argument only works if you actually assemble it. The core is a Seeed Studio XIAO ESP32S3 or any other ESP32-S3 board. Audio in is an INMP441 microphone, audio out is a MAX98357A amplifier feeding a 3525 speaker or any compatible microspeaker. A single LED is listed with an RGB LED recommended, plus a button. For the board itself there is a PCB prototype board or a custom PCB, and for the enclosure a 3D printed case supplied as case_model.stl. The tools list is 28AWG wires, a soldering toolset and flux, which tells you how much of this is a soldering job rather than a breadboard exercise. The note about tax and shipping rates varying by region is attached to the hardware list, and it is the part that decides whether the cost-effective claim survives contact with a real invoice. Assembly is described as step zero, before the pin configuration work.

## Backend, frontend and Redis come up through one compose file

The software side is a NextJS frontend talking to a Python backend, with Redis behind it, and docker-compose.yml wires the three together. The frontend service runs as the container named web on port 3000, pulling joeyhsiung/starmoon-frontend:latest with a pull policy of if_not_present, and it is built from the frontend context with NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, JWT_SECRET_KEY, OPENAI_API_KEY and GOOGLE_OAUTH passed as build arguments. The backend-core service pulls joeyhsiung/starmoon-backend:latest, reads its configuration from a .env file, mounts the backend directory at /app/, and listens on port 8000. Its command is poetry run uvicorn app.main:app bound to 0.0.0.0 on port 8000 with --ws-ping-interval 600 and --ws-ping-timeout 600, which are long websocket timeouts chosen for a streaming voice session rather than a request-response API. Both services set restart always, and both add a host.docker.internal host mapping so the containers can reach services running on the host.

## The healthcheck is commented out and the example secrets are populated

Two lines in the compose file deserve a second look before anyone runs it. The healthcheck for the backend is present but commented out, and what it would have run is a curl against http://localhost:8000/healthz, so nothing in the default stack verifies that the backend came up before the frontend starts talking to it. depends_on orders the startup without checking readiness. The other thing to watch is .env.example, because it is populated rather than blanked. It carries a NEXT_PUBLIC_SUPABASE_ANON_KEY with a full JWT-shaped value, a JWT_SECRET_KEY with a real-looking base64 secret, and CELERY_FLOWER_USER and CELERY_FLOWER_PASSWORD both set to admin. Those values are committed to the repository, so they are public, and the Supabase URL even points at a local port on the host. Rotating all of them is a five-minute job and belongs in your own secret store, not in a copy of the example file. The example also carries an MS_SPEECH_ENDPOINTY key with the misspelling intact, which is worth knowing before you spend time debugging an empty value.

## Self-hosting the backend does not remove the vendor keys

The privacy argument for Starmoon is that you can deploy it locally and self-host so your data stays yours. The environment file is where that claim meets reality, because the model and speech services are named one by one. LLM_MODEL_NAME is set to gpt-4o and OPENAI_API_KEY is required, with AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY marked optional. Text to speech is available through Azure, with MS_SPEECH_ENDPOINTY, SPEECH_KEY and SPEECH_REGION, or through Fish with FISH_API_KEY. Speech to text is Deepgram with DG_API_KEY. Emotion detection is a HuggingFace inference endpoint pointed at the roberta-base-go_emotions model, with HF_ACCESS_TOKEN for access. So a self-hosted Starmoon still sends audio to a hosted transcription service and conversation to a hosted model, and the pieces you most want to own are the ones you host while the pieces you most want to inspect are the ones you do not. There is also a vendor account in the loop before any of that: the prerequisites ask for a Starmoon API key obtained from the settings page after logging in at starmoon.app.

## Conclusion

Starmoon is worth reading as a parts list and a wiring table rather than as software to depend on. The board-level instructions, the pin map and the compose file are specific enough to rebuild a variant from, and the reason to rebuild rather than reuse is that the project itself says it is no longer actively maintained and hands the work to ElatoAI, whose repository is the one to track. Two things argue against wiring it up as shipped: the backend healthcheck in the compose file is commented out, and the environment example ships a populated anon key, a JWT secret and a flower login of admin on admin, all of which belong in your own secret store before anything else runs. Before you buy parts, confirm three things: that you can source an ESP32-S3 board plus an INMP441 and a MAX98357A where you live, that your network will give the device a 2.4 GHz network, and that you have a soldering iron, because the firmware path assumes you own the hardware before you own the software.

## FAQ

### Is Starmoon still maintained?

No. The README states that Starmoon is no longer actively maintained and directs anyone wanting realtime voice AI on ESP32 and local devices to ElatoAI at github.com/akdeb/ElatoAI. The repository itself is not archived, but its last push is dated 2026-03-27 and it publishes no GitHub releases.

### What hardware does a Starmoon device need?

A Seeed Studio XIAO ESP32S3 or any other ESP32-S3 board, an INMP441 I2S microphone, a MAX98357A amplifier, a 3525 speaker or compatible microspeaker, an LED, a button, a PCB prototype board or custom PCB, and a 3D printed case supplied as case_model.stl. You also need 28AWG wires, a soldering toolset and flux.

### Does a Starmoon device need 5 GHz WiFi?

The opposite. The documented setup says it supports only 2.4 GHz WiFi. After you press the main button and wait for the LED, you connect a phone, tablet or PC to a network named Starmoon-xxx and follow the on-device instructions to supply your own credentials.

### Which AI services does Starmoon call out to?

OpenAI with gpt-4o for the model, Deepgram for speech to text, Azure or Fish for text to speech, and a HuggingFace inference endpoint for the roberta-base-go_emotions emotion model. Azure OpenAI is available as an optional alternative, and the prerequisites also require a Starmoon API key from an account on starmoon.app.

### How do I flash the firmware onto a Starmoon board?

Through PlatformIO inside VS Code. Open the PlatformIO sidebar, use Pick a folder on the firmware directory, press Build, then connect the board over USB and use the Upload or Upload and Monitor button. If you are on a generic ESP32-S3 rather than the Seeed XIAO, you first edit firmware/src/Config.h and firmware/platformio.ini to switch the board define and the build environment.

## Sources

- [Issues](https://github.com/StarmoonAI/Starmoon/issues)
- [License: GPL-3.0](https://github.com/StarmoonAI/Starmoon/blob/main/LICENSE)
- [Project website](https://www.elatoai.com)
- [README](https://github.com/StarmoonAI/Starmoon/blob/main/README.md)
- [StarmoonAI/Starmoon on GitHub](https://github.com/StarmoonAI/Starmoon)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/starmoonai-starmoon
