Realrobots.net blockly microcontroller IDE

## Development

Two processes run side by side:

1. `npm run server` — Node/Express backend (auth, WebSocket realtime, arduino-cli). Reads `.env` (see `.env.example`). Listens on `PORT` (default 3001).
2. `npm run dev` — Vite dev server on port 3000. Proxies `/blocks/api/*` and `/blocks/ws` to the backend.

Sign in is optional. Without login the IDE works as before. Once logged in as a student, your Blockly workspace is mirrored in realtime to any teacher viewing `/blocks/teacher.html`.

## Creating a teacher account

There is no public "create teacher" flow. Promote a user to teacher in MySQL after they register:

```sql
UPDATE users SET role = 'teacher' WHERE username = 'alice';
```

## Build & deploy

`deploy.bat` builds to `dist/` and `scp`s it to `realrobots.net:~/blocks/` as before. The Node server now also needs to run on that host (e.g. via `pm2` or `systemd`) and the web server needs two proxy rules so the browser can reach it under the `/blocks/` base path:

- `/blocks/api/*` → `http://127.0.0.1:3001/api/*` (strip the `/blocks` prefix)
- `/blocks/ws`    → `http://127.0.0.1:3001/ws` with WebSocket upgrade (strip the `/blocks` prefix)

Example nginx snippet:

```nginx
location /blocks/api/ {
  proxy_pass http://127.0.0.1:3001/api/;
  proxy_set_header Host $host;
}
location /blocks/ws {
  proxy_pass http://127.0.0.1:3001/ws;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
  proxy_read_timeout 3600s;
}
```

After `deploy.bat`, restart the Node process (`pm2 restart esp32block-server` or equivalent).
