Current guideLocal + web

Build embedded projects with less friction

Dexmod combines an Arduino-focused code workspace, AI assistance, project libraries, GitHub export, Web Serial tools, and a live telemetry dashboard in one browser-based workflow.

01

Create

Select a board and write or generate code.

02

Verify

Review problems, libraries, and AI suggestions.

03

Observe

Read serial data and visualize telemetry.

First project

Quick start

  1. 1

    Create an account

    Register with email and password, Google, or GitHub.

  2. 2

    Create a project

    Open Project Manager, choose New project, name it, and select the target board.

  3. 3

    Write or ask AI

    Edit main.ino directly or ask the AI Assistant to explain, diagnose, or generate code.

  4. 4

    Add dependencies

    Open Libraries to install a registry library or upload a compatible ZIP library.

  5. 5

    Save and test

    Changes are autosaved. Use Problems, Output, and Serial Monitor to inspect the project.

Workspace

Projects and the editor

Each project stores its name, selected board, source files, installed libraries, and project-specific AI conversation history. The editor remembers the active file during navigation and saves file changes automatically.

Project Manager

Create, import, rename, duplicate, delete, and open projects. Plan limits determine the maximum number of stored projects.

Editor workspace

Work with multiple Arduino and header files, select a target board, manage libraries, export code, and open the AI panel.

Assisted coding

AI Assistant

AvailableUses monthly AI credits

The assistant receives the active file as context. It can answer in the language used by the user, explain code, locate likely issues, and apply generated code to the editor. Review pin assignments, hardware assumptions, and safety-related behavior before uploading.

  • Use precise hardware names, board type, pins, libraries, and expected behavior.
  • Ask for telemetry output when the project will use Serial Dashboard.
  • Use Undo after an applied response if the generated code is not suitable.
  • AI output can be incorrect; compilation and hardware validation remain necessary.
cpp
Create an ESP32 temperature monitor using a DHT22 on GPIO 4.
Print temperature and humidity as one JSON object every second
so Dexmod Serial Dashboard can visualize both values.

Hardware targets

Boards and libraries

Choose the board that matches the physical target before compiling or uploading. The current catalog includes Arduino Uno, Nano, Mega, Leonardo, Nano Every, Uno R4 WiFi, ESP32, ESP32-S3, NodeMCU ESP8266, and Raspberry Pi Pico targets.

Library sourceUsage
Arduino registrySearch and install
External ZIPUpload up to 10 MB

Local telemetry

Serial Monitor and Dashboard

AvailableBrowser local

Serial Monitor connects directly to an authorized device port. Console displays raw text, while Dashboard recognizes numeric telemetry and generates value cards and live charts automatically.

  1. Open the Serial Monitor tab below the editor.
  2. Select the same baud rate used by Serial.begin().
  3. Click Connect and choose the correct USB serial device.
  4. Switch from Console to Dashboard.
  5. Use Record to capture parsed samples, then Export CSV.
cpp
void setup() {
  Serial.begin(115200);
}

void loop() {
  float temperature = 28.4;
  float humidity = 72.0;

  Serial.print("{\"temperature\":");
  Serial.print(temperature);
  Serial.print(",\"humidity\":");
  Serial.print(humidity);
  Serial.println("}");
  delay(1000);
}

Dashboard Builder

After telemetry is detected, choose Customize to rename metrics, add units, select Line, Number, Gauge, or Status widgets, hide metrics, and reorder the layout. Select Save layout to store the configuration for the current project in this browser.

Metric and widget count

The Dashboard is not limited to three labels. The demo creates three widgets because it sends only temperature, humidity, and motorRpm. Every new numeric telemetry key automatically creates another configurable widget after its first sample arrives.

text
{"temperature":28.4,"humidity":72,"pressure":1012,"motorRpm":1250,"voltage":12.3,"current":1.8}

This sample creates six metrics. There is currently no fixed widget limit, but keeping approximately 12–20 visible widgets per dashboard is recommended for readability and browser performance. Hide less important metrics or split very large systems into focused dashboards.

Data reference

Supported telemetry formats

Send one complete sample per line. JSON is recommended because metric names remain explicit and values stay synchronized.

JSON — recommended

text
{"temperature":28.4,"humidity":72,"motor":true}

Numbers and numeric strings become chart values. JSON booleans become 1 or 0.

Key-value

text
temperature=28.4 humidity=72 motorRpm=1280

CSV with header

text
temperature,humidity,motorRpm
28.4,72,1280
28.7,71,1310

Cloud telemetry · Phase 2

Remote IoT Monitoring

AvailableHTTPS + MQTT

Remote IoT Monitoring lets an internet-connected device send numeric telemetry to Dexmod without remaining connected to the browser by USB. Open a project and select Monitor, then create a device. Dexmod displays its secret token only once and stores only a cryptographic hash.

  1. Create a device inside the project's Remote Monitor.
  2. Copy the one-time token into secure device configuration.
  3. POST a flat JSON object to /api/iot/ingest with the token as a Bearer credential.
  4. Keep the monitor open to receive live updates through its authenticated stream.
  5. Customize labels, units, ranges, and widget types with Dashboard Builder.
http
POST /api/iot/ingest HTTP/1.1
Authorization: Bearer dxm_DEVICE_ID.SECRET
Content-Type: application/json
Idempotency-Key: boot-42-sample-1001

{"temperature":28.4,"humidity":72,"pump":true}

A sample may contain 1–32 metrics. Metric names must start with a letter and values must be finite numbers or booleans. Each request is limited to 8 KB.

Complete ESP32 example

This local-network example connects an ESP32 to Wi-Fi and sends one JSON sample to Dexmod. Replace the Wi-Fi values, laptop IP address, and one-time device token before uploading it.

cpp
#include <WiFi.h>
#include <HTTPClient.h>

const char* WIFI_NAME = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

// Use your laptop's LAN IP, not localhost.
const char* DEXMOD_URL =
  "http://192.168.1.10:3000/api/iot/ingest";

const char* DEVICE_TOKEN =
  "dxm_DEVICE_ID.SECRET";

void setup() {
  Serial.begin(115200);
  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("Wi-Fi connected");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    HTTPClient http;

    http.begin(client, DEXMOD_URL);
    http.addHeader("Content-Type", "application/json");
    http.addHeader(
      "Authorization",
      String("Bearer ") + DEVICE_TOKEN
    );

    float temperature = 28.4;
    int humidity = 72;
    bool pump = true;

    String payload =
      "{"temperature":" + String(temperature, 1) +
      ","humidity":" + String(humidity) +
      ","pump":" + String(pump ? "true" : "false") +
      "}";

    int statusCode = http.POST(payload);
    Serial.print("Dexmod response: ");
    Serial.println(statusCode);
    Serial.println(http.getString());
    http.end();
  }

  delay(60000); // Free plan: minimum 60 seconds
}

Production HTTPS

After publishing Dexmod, change the endpoint to the public HTTPS domain and use WiFiClientSecure. Validate the server certificate with the certificate authority used by the deployed domain.

cpp
#include <WiFiClientSecure.h>

const char* DEXMOD_URL =
  "https://app.example.com/api/iot/ingest";

WiFiClientSecure secureClient;
HTTPClient http;

// ROOT_CA must contain the trusted CA certificate.
secureClient.setCACert(ROOT_CA);
http.begin(secureClient, DEXMOD_URL);

EMQX MQTT over TLS

MQTT devices publish to the project-independent topic below. Replace DEVICE_ID with the ID shown in Remote Monitor. The token inside the message must belong to the same device ID.

text
Topic:
dexmod/devices/DEVICE_ID/telemetry

Payload:
{"token":"dxm_DEVICE_ID.SECRET","messageId":"boot-42-sample-1001","metrics":{"temperature":28.4,"humidity":72,"pump":true}}

Use a new stable messageId for each logical sample. If QoS 1 delivers the same ID and payload again, Dexmod acknowledges it without storing another row. Reusing an ID with different metrics is rejected.

Connect to the EMQX Serverless address with MQTT over TLS on port 8883. Install the downloaded emqxsl-ca.crt on the device, then use the MQTT username and password created in EMQX. The broker credentials open the TLS connection; the Dexmod token authorizes telemetry for a specific device.

Test with MQTTX

  1. Keep npm run mqtt:worker running in its own terminal.
  2. Create an MQTTX connection using the exact deployment host shown in EMQX Cloud. Do not use the public broker.emqx.io host.
  3. Select mqtts://, port 8883, enable SSL/TLS and SSL Secure, then enter credentials from EMQX Access Control → Authentication.
  4. Use a unique Client ID such as mqttx-dexmod-test. Leave ALPN empty. The system CA option normally works; select the downloaded emqxsl-ca.crt if the connection cannot validate the server.
  5. Publish with QoS 1 and Retain disabled to the device topic shown above.
text
Protocol: mqtts://
Host: YOUR_DEPLOYMENT.emqxsl.com
Port: 8883
Topic: dexmod/devices/DEVICE_ID/telemetry
QoS: 1
Retain: off
cpp
WiFiClientSecure tlsClient;
PubSubClient mqtt(tlsClient);

tlsClient.setCACert(EMQX_ROOT_CA);
mqtt.setServer("YOUR_DEPLOYMENT.emqxsl.com", 8883);
mqtt.connect("esp32-device", MQTT_USERNAME, MQTT_PASSWORD);

String topic = "dexmod/devices/" + String(DEVICE_ID) + "/telemetry";
String messageId = "boot-" + String(esp_random(), HEX);
String payload =
  "{\"token\":\"" + String(DEVICE_TOKEN) +
  "\",\"messageId\":\"" + messageId +
  "\",\"metrics\":{\"temperature\":28.4,\"humidity\":72}}";
mqtt.publish(topic.c_str(), payload.c_str());

Response codes

CodeMeaningWhat the device should do
202Sample acceptedWait for the plan interval, then send the next sample.
401Token invalid, rotated, or revokedStop retrying and install a new device token.
422Telemetry format invalidCheck metric names and ensure values are numbers or booleans.
423Device paused by its ownerStop publishing until the owner resumes the device.
429Messages sent too quicklyRead Retry-After or increase the loop delay.
5xxTemporary server problemRetry later with increasing delays; do not retry continuously.

History, fleet, and CSV

The project monitor summarizes its devices and shows total account usage against the current plan. Open Device fleet from Project Manager, Remote Monitor, or the account menu to search and filter every device across all projects, inspect online/offline/paused totals, open its project monitor, or pause and resume ingestion. Use the History buttons to inspect the available time window, then select Export CSV to download the filtered samples.

PlanDevicesRetentionMinimum interval
Free124 hours60 seconds
Maker37 days15 seconds
Pro1090 days5 seconds
Team251 year1 second

Source control

Upload projects to GitHub

Available

Connect GitHub in Account settings, then use the GitHub button in the editor. Select an existing repository or create a public/private repository, choose a branch and optional folder, and upload all project files as one commit.

Dexmod also includes a .dexmod/project.json metadata file containing the board and library configuration. GitHub access tokens remain on the server and are never returned to the editor.

Physical hardware

Device upload

Preview

The upload workspace can select supported board targets and request Web Serial access. The current local build should be treated as a preview workflow: verify the compiled firmware and confirm that the target board reports the expected behavior before relying on it.

Help

Troubleshooting

No serial port appears+

Use desktop Chrome or Edge, reconnect the USB cable, install the board driver if required, and close other software using the port.

Console shows unreadable characters+

Set Dexmod baud rate to exactly the same value passed to Serial.begin().

Console works but Dashboard is empty+

Print numeric data as JSON, key=value, or CSV, and end every sample with a newline.

A metric does not update+

Check that the metric value is numeric. Free-form strings remain visible only in Console.

GitHub requests repository permission+

Open Account settings and reconnect GitHub to grant the repository scope used for commits.

An AI response is incomplete+

Reduce the requested scope, provide the active board and libraries, and split large changes into smaller prompts.

Ready to build?

Create a project, choose your board, and start with a small verified circuit.