jpmschweitzerandClaude c26b54398c docs: replace AGENTS.md with a repo-specific CLAUDE.md
One agent doc per repo, and it is CLAUDE.md. Written fresh rather than
reformatted. PHILOSOPHY.md linked to the old file, so that pointer moves
with it, and its standing requirement to be read before working here is
carried forward rather than lost in the rewrite.

Two claims did not survive verification. The app is published on 9999,
not the tower:8092 the old file gave, and it pointed at portainer-core
for full-stack documentation -- that repo is deprecated and must not be
used as a source of infra facts.

Establishing what is live needs a different method here: there is no
sys.modules to read, since the container holds a compiled web build
rather than source. A transitive walk of import/export/part directives
from lib/main.dart found 8 of 132 files unreachable, and five of those
are exactly what runs in production. They are conditional-import targets
-- `import 'a.dart' if (dart.library.html) 'b.dart'` -- and a walk that
takes the first string misses the branch. Since this ships as Flutter
web, the _web half is live and the _stub/_native half is dormant. The
naive reading was not merely wrong but inverted.

Of the three genuinely unreferenced files, stack_model.dart is imported
only by its own test, so the suite is green and vouches for a model the
app never uses. permission_gate.dart sits next to an unimplemented auth
redesign and is recorded as undetermined rather than dead.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-09 03:15:54 +02:00
2026-01-05 15:46:44 +01:00
2026-01-04 18:54:17 +01:00
2026-01-05 17:08:59 +01:00
2026-07-19 12:41:05 +02:00
2026-07-19 12:41:05 +02:00

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 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

# 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)
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)

# 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

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
  • tatlock: Backend LLM orchestration service
  • core-api: Infrastructure and housekeeping API
  • portainer-core: Docker Swarm stack definitions

License

Private - All rights reserved

S
Description
No description provided
Readme
17 MiB
2026-07-19 12:41:05 +02:00
Languages
Dart 92.2%
C++ 3.1%
CMake 2.4%
Shell 0.6%
Makefile 0.5%
Other 1.2%