add README and MIT license
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Gabriel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
161
README.md
Normal file
161
README.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# K-Frame
|
||||
|
||||
IoT dashboard system. A server aggregates data from external sources (weather APIs, media players, RSS feeds, webhooks) and pushes rendered updates to ESP32 display clients over TCP.
|
||||
|
||||
**Server** polls data sources, projects values through configurable widget mappings, computes layouts, and broadcasts binary frames to connected clients. Configuration via REST API + web UI.
|
||||
|
||||
**Clients** receive structured data + layout trees, compute bounding boxes, format text per display hint rules, and render to hardware. The client domain is chip-agnostic — the same rendering engine runs on ESP32 (ILI9341 TFT) and desktop (terminal).
|
||||
|
||||
**Web UI** (SPA) configures data sources, widgets, layouts, themes, and presets. Includes a live layout preview that mirrors what the physical display shows.
|
||||
|
||||
## Architecture
|
||||
|
||||
Hexagonal / ports-and-adapters with full CQRS. Domain logic has zero framework dependencies. Static dispatch everywhere (no `Box<dyn>`, no trait objects).
|
||||
|
||||
```
|
||||
┌─────────────────── Server ───────────────────┐
|
||||
│ domain/ entities, value objects, │
|
||||
│ ports (traits) │
|
||||
│ application/ use cases, data projection │
|
||||
│ bootstrap/ composition root, polling │
|
||||
│ │
|
||||
│ adapters/ │
|
||||
│ config-sqlite persistence │
|
||||
│ http-api REST API (Axum) │
|
||||
│ tcp-server binary protocol broadcast │
|
||||
│ http-json external API polling │
|
||||
│ media, rss source-specific adapters │
|
||||
│ auth argon2 + JWT │
|
||||
├─────────────────── Shared ───────────────────┤
|
||||
│ protocol/ wire types, postcard serde │
|
||||
│ api-types/ REST DTOs │
|
||||
├─────────────────── Client ───────────────────┤
|
||||
│ client-domain/ layout engine, render engine │
|
||||
│ markup parser, scroll state │
|
||||
│ client-application/ message handling │
|
||||
│ client-esp32/ ESP32 firmware (ILI9341) │
|
||||
│ client-desktop/ terminal debug client │
|
||||
├──────────────────── SPA ─────────────────────┤
|
||||
│ spa/ React + TanStack Router │
|
||||
│ shadcn/ui + Tailwind │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key design decisions
|
||||
|
||||
- **postcard + serde** for the wire protocol — compact varint encoding, `no_std` compatible, no codegen
|
||||
- **Static dispatch** — port traits used as generic bounds, not trait objects. Composition root resolves all types
|
||||
- **Event-driven CQRS** — config mutations emit domain events, read model projected in memory
|
||||
- **Domain-owned rendering** — client-domain owns text wrapping, alignment, color markup, scroll. DisplayPort is a thin pixel-pusher (`draw_text_span`, `fill_rect`, `flush`)
|
||||
- **WiFi provisioning** — ESP32 boots into AP captive portal if no config in NVS, auto-falls back on WiFi failure
|
||||
|
||||
See `docs/adr/` for architectural decision records and `CONTEXT.md` for the domain glossary.
|
||||
|
||||
## Features
|
||||
|
||||
- **Data sources**: HTTP/JSON, weather, media (Subsonic/Navidrome), RSS, webhooks
|
||||
- **Layout engine**: flexbox-like containers (row/column, fixed/flex sizing, gap, padding, justify-content, align-items)
|
||||
- **Theming**: 5 configurable colors (primary, secondary, accent, text, background), live push to clients
|
||||
- **Rich text**: inline color markup (`{primary}text{/}`, `{#FF0000}hex{/}`)
|
||||
- **Overflow scroll**: bounce animation when content exceeds widget bounds, speed auto-derived from overflow
|
||||
- **Captive portal**: ESP32 AP mode with DNS + HTTP config form for WiFi provisioning
|
||||
- **Auth**: argon2 password hashing, JWT tokens, protected API routes
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Rust** (stable) — server, desktop client, shared crates
|
||||
- **Rust ESP32 toolchain** — `espup`, xtensa target. See [esp-rs book](https://docs.esp-rs.org/book/)
|
||||
- **Node.js / Bun** — SPA development
|
||||
- **SQLite** — server persistence (created automatically)
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
# 1. Clone and configure
|
||||
cp .env.example .env
|
||||
# Edit .env — set JWT_SECRET and KFRAME_ENCRYPTION_KEY
|
||||
|
||||
# 2. Start the server
|
||||
make server
|
||||
|
||||
# 3. Start the SPA dev server (separate terminal)
|
||||
cd spa && bun install && bun run dev
|
||||
# Open http://localhost:5173
|
||||
|
||||
# 4. Register an account (first launch = setup mode)
|
||||
# 5. Add a data source, create widgets, build a layout
|
||||
```
|
||||
|
||||
### ESP32 client
|
||||
|
||||
```bash
|
||||
# Build firmware
|
||||
make esp-build
|
||||
|
||||
# Flash (default port: /dev/ttyACM0)
|
||||
make esp-flash
|
||||
|
||||
# Flash with custom port
|
||||
make esp-flash ESP_PORT=/dev/ttyUSB0
|
||||
|
||||
# Flash and monitor serial output
|
||||
make esp-run
|
||||
|
||||
# On first boot: connect to "KFrame-Setup" WiFi, enter credentials in captive portal
|
||||
```
|
||||
|
||||
### Desktop client
|
||||
|
||||
```bash
|
||||
make desktop
|
||||
# Connects to localhost:2699, prints render commands to terminal
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Full check suite (fmt + clippy + test)
|
||||
make check
|
||||
|
||||
# Auto-fix formatting and clippy warnings
|
||||
make fix
|
||||
|
||||
# Run tests only
|
||||
make test
|
||||
|
||||
# SPA type checking
|
||||
cd spa && bun run typecheck
|
||||
```
|
||||
|
||||
### Project structure
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `crates/domain/` | Entities, value objects, port traits |
|
||||
| `crates/application/` | Use cases (ConfigService, DataProjection) |
|
||||
| `crates/protocol/` | Wire types, encode/decode (`no_std`) |
|
||||
| `crates/bootstrap/` | Server composition root |
|
||||
| `crates/adapters/` | All port implementations |
|
||||
| `crates/client-domain/` | Display-agnostic rendering engine |
|
||||
| `crates/client-application/` | Client message handling |
|
||||
| `crates/client-esp32/` | ESP32 firmware |
|
||||
| `crates/client-desktop/` | Terminal debug client |
|
||||
| `crates/api-types/` | REST API DTOs |
|
||||
| `spa/` | React SPA |
|
||||
| `docs/adr/` | Architecture decision records |
|
||||
| `CONTEXT.md` | Domain glossary |
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repo
|
||||
2. Create a feature branch
|
||||
3. Run `make check` before pushing — CI runs the same checks
|
||||
4. Open a PR with a clear description of what changed and why
|
||||
|
||||
The domain glossary in `CONTEXT.md` defines the canonical language. Use it in code, commits, and PRs. If you're adding a new concept, update the glossary.
|
||||
|
||||
Architecture decisions are documented in `docs/adr/`. If your change involves a hard-to-reverse design choice, write an ADR.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
Reference in New Issue
Block a user