docs: Document frontend technology choices for ESP32-S3, detailing the selection of Svelte, Vite, and TailwindCSS for a lightweight web UI.
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
## 1. Goal
|
## 1. Goal
|
||||||
|
|
||||||
Create a lightweight web frontend for the ESP32-S3 Provider that displays system information and provides a reboot control. The frontend must compile to static files small enough to live in ESP32 flash memory (~4-8kB gzipped).
|
Create a lightweight web frontend for the ESP32-S3 Provider that displays system information and provides a reboot control. The frontend must compile to static files small enough to live in ESP32 flash memory.
|
||||||
|
|
||||||
## 2. Chosen Stack
|
## 2. Chosen Stack
|
||||||
|
|
||||||
@@ -97,13 +97,13 @@ Although we don't use the framework, we adopt the same **proven patterns**:
|
|||||||
Source Files Build Steps Output
|
Source Files Build Steps Output
|
||||||
───────────── ─────────── ──────
|
───────────── ─────────── ──────
|
||||||
src/App.svelte ─┐
|
src/App.svelte ─┐
|
||||||
src/app.css ├─→ Vite + Svelte Compiler ─→ dist/index.html (~15-25kB)
|
src/app.css ├─→ Vite + Svelte Compiler ─→ dist/index.html (47kB)
|
||||||
src/lib/api.js ─┘ + TailwindCSS JIT │
|
src/lib/api.js ─┘ + TailwindCSS JIT │
|
||||||
+ vite-plugin-singlefile ▼
|
+ vite-plugin-singlefile ▼
|
||||||
gzip compression
|
gzip compression (level 9)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
dist/index.html.gz (~4-8kB)
|
dist/index.html.gz (16kB)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
ESP32 Flash (SPIFFS/LittleFS)
|
ESP32 Flash (SPIFFS/LittleFS)
|
||||||
@@ -125,7 +125,7 @@ This is handled via Vite's `.env.development` and `.env.production` files. The v
|
|||||||
|
|
||||||
When OTA updates are implemented, the frontend will be embedded into the firmware binary as a C header array:
|
When OTA updates are implemented, the frontend will be embedded into the firmware binary as a C header array:
|
||||||
|
|
||||||
1. `npm run build:esp32` → `dist/index.html.gz` (~4-8kB)
|
1. `npm run build:esp32` → `dist/index.html.gz` (~16kB)
|
||||||
2. A script converts the gzipped file to a C `const uint8_t[]` array
|
2. A script converts the gzipped file to a C `const uint8_t[]` array
|
||||||
3. The array is compiled into the firmware binary
|
3. The array is compiled into the firmware binary
|
||||||
4. OTA flashes one binary that includes both firmware and frontend
|
4. OTA flashes one binary that includes both firmware and frontend
|
||||||
@@ -134,4 +134,79 @@ This avoids needing a separate SPIFFS partition for the frontend and ensures the
|
|||||||
|
|
||||||
## 10. Summary
|
## 10. Summary
|
||||||
|
|
||||||
We chose **Svelte + TailwindCSS + Vite** because they are build-time tools that produce the smallest possible static output, ideal for ESP32 constraints. We build to a **single gzipped HTML file** of ~4-8kB. We did not adopt ESP32-SvelteKit because it requires PlatformIO/Arduino, which is incompatible with our native ESP-IDF project, and includes unnecessary complexity for our simple dashboard.
|
We chose **Svelte + TailwindCSS + Vite** because they are build-time tools that produce the smallest possible static output, ideal for ESP32 constraints. We build to a **single gzipped HTML file** of ~16kB. We did not adopt ESP32-SvelteKit because it requires PlatformIO/Arduino, which is incompatible with our native ESP-IDF project, and includes unnecessary complexity for our simple dashboard.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Implementation Results
|
||||||
|
|
||||||
|
*Added 2026-03-02 after implementation was completed.*
|
||||||
|
|
||||||
|
### Final Build Output
|
||||||
|
|
||||||
|
| File | Size | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `dist/index.html` | **47.0 kB** | Single self-contained file (all JS + CSS inlined) |
|
||||||
|
| `dist/index.html.gz` | **16.1 kB** | Gzipped at max level 9 (65% reduction) |
|
||||||
|
|
||||||
|
### Size Breakdown (before inlining)
|
||||||
|
|
||||||
|
| Asset | Uncompressed | Gzipped |
|
||||||
|
|---|---|---|
|
||||||
|
| HTML shell | 0.4 kB | 0.3 kB |
|
||||||
|
| CSS (TailwindCSS JIT) | 12.4 kB | 3.2 kB |
|
||||||
|
| JS (Svelte compiled) | 34.9 kB | 13.5 kB |
|
||||||
|
| **Total** | **47.7 kB** | **17.0 kB** |
|
||||||
|
|
||||||
|
The singlefile plugin reduces total size by ~0.8kB (removes multi-file boilerplate). Its main value is operational (one file, one HTTP request, no filesystem overhead).
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
Provider/frontend/
|
||||||
|
├── .env.development # VITE_API_BASE=http://ESP32_IP_HERE
|
||||||
|
├── .env.production # VITE_API_BASE= (empty, same-origin)
|
||||||
|
├── index.html # Vite entry point
|
||||||
|
├── package.json # npm scripts: dev, build, build:esp32
|
||||||
|
├── vite.config.js # Svelte + TailwindCSS + singlefile plugins
|
||||||
|
├── scripts/
|
||||||
|
│ └── gzip.js # Node.js gzip script (built-in zlib, no deps)
|
||||||
|
└── src/
|
||||||
|
├── main.js # Svelte mount point
|
||||||
|
├── app.css # TailwindCSS v4 imports + @theme tokens
|
||||||
|
├── App.svelte # Dashboard UI (system info, reboot button)
|
||||||
|
└── lib/
|
||||||
|
└── api.js # API helpers (getSystemInfo, reboot)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dashboard Features
|
||||||
|
|
||||||
|
- System info display: chip model, free heap, uptime, firmware version, connection type
|
||||||
|
- Reboot button with confirmation modal
|
||||||
|
- Auto-refresh polling every 5 seconds
|
||||||
|
- Four status states: loading, connected, offline, rebooting
|
||||||
|
- Dark theme with custom color tokens
|
||||||
|
- Fully responsive layout
|
||||||
|
|
||||||
|
### npm Scripts
|
||||||
|
|
||||||
|
| Script | Command | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `npm run dev` | `vite` | Dev server with HMR (for PC development) |
|
||||||
|
| `npm run build` | `vite build` | Production build (single `index.html`) |
|
||||||
|
| `npm run build:esp32` | `vite build && node scripts/gzip.js` | Build + gzip for ESP32 deployment |
|
||||||
|
|
||||||
|
### Versions Used
|
||||||
|
|
||||||
|
| Package | Version |
|
||||||
|
|---|---|
|
||||||
|
| Svelte | 5.45.2 |
|
||||||
|
| Vite | 7.3.1 |
|
||||||
|
| TailwindCSS | 4.2.1 |
|
||||||
|
| @tailwindcss/vite | 4.2.1 |
|
||||||
|
| vite-plugin-singlefile | 2.3.0 |
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
|
||||||
|
- **W: drive**: Vite requires `resolve.preserveSymlinks: true` in `vite.config.js` because `W:` is a `subst` drive mapped to `C:\Dev\...`. Without this, the build fails with `fileName` path resolution errors.
|
||||||
|
- **ESP32 backend not yet implemented**: The frontend expects `GET /api/system/info` and `POST /api/system/reboot` endpoints. These need to be added to `main.cpp` using `esp_http_server`.
|
||||||
|
|||||||
Reference in New Issue
Block a user