Replace manual generate_version.dart script with a custom build_runner builder that automatically generates lib/version.g.dart from pubspec.yaml during the build process. This eliminates manual steps and ensures version info stays in sync. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
229 lines
6.8 KiB
Markdown
229 lines
6.8 KiB
Markdown
# Tatlock UI
|
|
|
|
A Flutter-based unified homelab dashboard for the Tower of Joy infrastructure, replacing Organizr at `home.schweitz.net`.
|
|
|
|
## Overview
|
|
|
|
Tatlock UI provides a single interface for:
|
|
- **Dashboard**: System metrics, service status, quick actions
|
|
- **Tatlock Chat**: LLM conversation interface with streaming responses
|
|
- **Infrastructure**: Container management, logs, resource monitoring
|
|
- **Housekeeping**: Home automation control via Home Assistant
|
|
|
|
See [PHILOSOPHY.md](PHILOSOPHY.md) for the guiding vision.
|
|
|
|
## Tech Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|------------|
|
|
| Framework | Flutter 3.38+ |
|
|
| State Management | Riverpod 2.x with code generation |
|
|
| Routing | go_router |
|
|
| HTTP Client | Dio + Retrofit |
|
|
| Authentication | Authentik OIDC via flutter_appauth |
|
|
| Theming | flex_color_scheme (Material 3) |
|
|
| Code Generation | freezed, json_serializable, riverpod_generator |
|
|
|
|
## Platforms
|
|
|
|
| Platform | Status | Notes |
|
|
|----------|--------|-------|
|
|
| Web | Primary | Docker deployment at port 8092 |
|
|
| Android | Supported | For mobile access |
|
|
| iOS | Supported | For mobile access |
|
|
| macOS | Supported | Native desktop |
|
|
| Linux | Supported | Native desktop |
|
|
| Windows | Supported | Native desktop |
|
|
|
|
## Architecture
|
|
|
|
This project follows **Clean Architecture** with feature-based organization:
|
|
|
|
```
|
|
lib/
|
|
├── app.dart # MaterialApp.router setup
|
|
├── main.dart # Entry point
|
|
├── core/ # Shared infrastructure
|
|
│ ├── api/ # HTTP client, interceptors, SSE
|
|
│ ├── auth/ # Authentik OIDC integration
|
|
│ ├── config/ # Environment, service locator
|
|
│ └── theme/ # Material 3 theming
|
|
├── routing/ # go_router configuration
|
|
├── shared/ # Reusable components
|
|
│ ├── components/ # DataGrid, widgets
|
|
│ └── layouts/ # App scaffold, navigation
|
|
└── features/ # Feature modules
|
|
├── dashboard/
|
|
├── chat/
|
|
├── containers/
|
|
└── housekeeping/
|
|
```
|
|
|
|
Each feature follows the three-layer pattern:
|
|
|
|
```
|
|
features/{feature}/
|
|
├── presentation/ # UI Layer
|
|
│ ├── pages/ # Full screen widgets
|
|
│ ├── widgets/ # Feature-specific widgets
|
|
│ └── providers/ # Riverpod providers
|
|
├── domain/ # Business Logic Layer
|
|
│ ├── entities/ # Immutable business objects
|
|
│ ├── repositories/ # Abstract interfaces
|
|
│ └── usecases/ # Single-purpose operations
|
|
└── data/ # Data Layer
|
|
├── models/ # JSON serializable DTOs
|
|
├── datasources/ # API clients
|
|
└── repositories/ # Repository implementations
|
|
```
|
|
|
|
**Layer Rules**:
|
|
- Domain layer has NO dependencies on Flutter or external packages
|
|
- Data layer implements domain interfaces
|
|
- Presentation layer only depends on domain layer
|
|
- Cross-layer communication via dependency injection (Riverpod)
|
|
|
|
## Backend APIs
|
|
|
|
| Service | URL | Purpose |
|
|
|---------|-----|---------|
|
|
| Core API | `https://api.schweitz.net` | Infrastructure, widgets, housekeeping |
|
|
| Tatlock API | `https://tatlock.schweitz.net` | LLM chat completions, streaming |
|
|
|
|
Both APIs are behind Authentik SSO.
|
|
|
|
**Key Endpoints**:
|
|
- `GET /infrastructure/containers` - Container list and management
|
|
- `GET /infrastructure/resources/system` - CPU, memory, disk metrics
|
|
- `GET /housekeeping/devices` - Home Assistant devices
|
|
- `POST /v1/chat/completions` - Tatlock LLM (SSE streaming)
|
|
|
|
## Development Setup
|
|
|
|
### Prerequisites
|
|
|
|
- Flutter SDK 3.38+
|
|
- Dart SDK 3.10+
|
|
- Java 17+ (required for Android builds with Gradle 8.14+)
|
|
- For mobile: Android Studio / Xcode 26+
|
|
- For desktop: Platform-specific toolchains
|
|
|
|
### Getting Started
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone ssh://git@git.schweitz.net:2222/jpmschweitzer/tatlock-ui.git
|
|
cd tatlock-ui
|
|
|
|
# Install dependencies
|
|
flutter pub get
|
|
|
|
# Generate code (freezed, json_serializable, riverpod)
|
|
dart run build_runner build --delete-conflicting-outputs
|
|
|
|
# Run development server
|
|
flutter run -d chrome # Web
|
|
flutter run -d macos # macOS
|
|
flutter run # Default device
|
|
```
|
|
|
|
### Code Generation
|
|
|
|
Run build_runner after modifying:
|
|
- `@freezed`, `@JsonSerializable`, or `@riverpod` annotated code
|
|
- `pubspec.yaml` version (auto-generates `lib/version.g.dart`)
|
|
|
|
```bash
|
|
dart run build_runner build --delete-conflicting-outputs
|
|
|
|
# Or watch mode during development
|
|
dart run build_runner watch --delete-conflicting-outputs
|
|
```
|
|
|
|
**Generated files**:
|
|
- `*.freezed.dart` - Freezed immutable classes
|
|
- `*.g.dart` - JSON serialization, Riverpod providers
|
|
- `lib/version.g.dart` - App version from pubspec.yaml
|
|
|
|
## Deployment
|
|
|
|
### Web (Docker)
|
|
|
|
```bash
|
|
# Build the image
|
|
docker build -t git.schweitz.net/jpmschweitzer/tatlock-ui:latest .
|
|
|
|
# Or use the Gitea CI/CD pipeline
|
|
git push origin main
|
|
```
|
|
|
|
**Deployment target**: Port 8092, proxied via NPM at `home.schweitz.net`
|
|
|
|
### Portainer Stack
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
services:
|
|
tatlock-ui:
|
|
image: git.schweitz.net/jpmschweitzer/tatlock-ui:latest
|
|
container_name: tatlock-ui
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8092:80"
|
|
networks:
|
|
- docker-dataplane
|
|
|
|
networks:
|
|
docker-dataplane:
|
|
external: true
|
|
```
|
|
|
|
## Navigation Structure
|
|
|
|
```
|
|
├── Homepage (Dashboard)
|
|
├── Tatlock (Chat)
|
|
├── Jellyfin (external)
|
|
├── SearXNG (external)
|
|
├── AMP
|
|
│ └── AMP Home
|
|
├── Coding
|
|
│ ├── Cloud IDE (external)
|
|
│ └── Gitea (external)
|
|
├── Infrastructure
|
|
│ ├── Containers
|
|
│ ├── Netdata (external)
|
|
│ ├── Portainer (external)
|
|
│ └── Proxy Manager (external)
|
|
├── Housekeeping
|
|
├── API Docs (external)
|
|
└── Settings
|
|
```
|
|
|
|
## Authentication
|
|
|
|
Uses Authentik OIDC with the following configuration:
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Application | `tatlock-ui` |
|
|
| Client Type | Public |
|
|
| Redirect URIs | `https://home.schweitz.net/callback`, `net.schweitz.tatlock://callback`, `http://localhost:*/callback` |
|
|
|
|
## Project Links
|
|
|
|
- **Repository**: [git.schweitz.net/jpmschweitzer/tatlock-ui](https://git.schweitz.net/jpmschweitzer/tatlock-ui)
|
|
- **Deployment**: [home.schweitz.net](https://home.schweitz.net) (replaces Organizr)
|
|
- **Core API Docs**: [api.schweitz.net/docs](https://api.schweitz.net/docs)
|
|
- **Tatlock API Docs**: [household.schweitz.net/docs](https://household.schweitz.net/docs)
|
|
|
|
## Related Repositories
|
|
|
|
- **tatlock**: Backend LLM orchestration service
|
|
- **core-api**: Infrastructure and housekeeping API
|
|
- **portainer-core**: Docker Swarm stack definitions
|
|
|
|
## License
|
|
|
|
Private - All rights reserved
|