diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a18a5fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.superpowers/ +.env +.claude/ +__pycache__/ +*.pyc +*.pyo +node_modules/ +dist/ +screenshot.png +*.png diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..940ed7b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,92 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project: HomeHub + +HomeHub is a personal organization self-hosted PWA deployed via Docker Compose on Proxmox 9 (Debian 13). It targets heavy mobile usage with offline support. + +## Architecture décidée + +Two competing architectures are documented. The **retained one** (from `Consignes de Développement App Self-hosted.md`) is: + +| Service | Stack | +|---------|-------| +| Frontend | React + Vite + TypeScript + Tailwind CSS (PWA) | +| Backend | FastAPI (Python) — async, SQLAlchemy 2.0 | +| Database | PostgreSQL 16 — multiple schemas (not multiple DBs) | +| Queue/Cache | Redis | +| Proxy | Traefik / OPNsense in front | + +The alternative modular approach (Vikunja + PocketBase + Keeper.sh + SvelteKit in the brainstorming doc) was **not retained**. + +### Backend structure (FastAPI) +``` +backend/ +├── app/ +│ ├── api/ # Endpoints split by domain: auth, todos, shopping, notes, calendar, mcp +│ ├── core/ # Config, security, DB (SQLAlchemy async) +│ ├── models/ # SQLAlchemy models using PostgreSQL schemas +│ ├── schemas/ # Pydantic validation schemas +│ ├── services/ # Business logic (calendar sync, Hermes Vision integration) +│ └── main.py +├── Dockerfile +└── requirements.txt +``` + +### PostgreSQL schemas +One PostgreSQL instance, logical separation via schemas: `auth`, `todos`, `shopping`, `notes`, `kanban`. This allows cross-schema joins while simplifying backups (`pg_dump` once). + +### Security +- JWT authentication +- CORS allowing local network `10.0.0.0/22` only + +## Design System — Gruvbox seventies + +**All UI must use the design system files in `design_system/`.** Read `design_system/consigne_design_system.md` before writing any UI code. + +### Absolute rules +1. **Always use CSS variables** — never hardcode hex colors. `color: var(--accent)` ✅, `color: #fe8019` ❌ +2. **Always declare `data-theme="dark|light"`** on a parent element (`` or a wrapper) +3. **Never reinvent existing components** — check `design_system/components/ui-kit.jsx` first (14 components: Button, IconButton, Toggle, Tooltip, StatusLed, BatteryGauge, RadialGauge, BigRadialGauge, Popup, TreeNav, Sparkline, LineChart, Icon…) +4. **Never use emoji or custom SVG** for icons — use `` with the mapped names +5. **No hover effects** on buttons/tiles (only 3D press on click via `.interactive`) +6. **Always use tooltips** on standalone icon buttons (`` requires `label`) +7. **Three fonts only**: `var(--font-ui)` (Inter, UI text), `var(--font-mono)` (JetBrains Mono, data/numbers), `var(--font-terminal)` (Share Tech Mono, logs/retro) +8. **Border radius**: tiles 10-12px, buttons 8px, pills 999px — never 24px+ + +### Key CSS tokens +- Backgrounds: `--bg-1` (app) → `--bg-2` (panels) → `--bg-3` (cards/tiles) → `--bg-4` (hover) → `--bg-5` (active) +- Text: `--ink-1` (primary) → `--ink-2` → `--ink-3` (labels) → `--ink-4` (disabled) +- Status: `--ok`, `--warn`, `--err`, `--info` +- `className="glass"` or `"glass-strong"` handles card styling (backdrop-filter + shadow) + +### Design system files +- `design_system/tokens/tokens.css` — web CSS variables (dark + light) +- `design_system/tokens/tokens.gnome.css` — GTK 4 / libadwaita overrides +- `design_system/tokens/tokens.json` — generic format for Tailwind/Figma +- `design_system/components/ui-kit.jsx` — all 14 React components +- `design_system/examples/exemple-minimal.html` — reference demo + +## Frontend PWA requirements +- Configure `@vite-pwa/plugin` with aggressive asset caching for offline use +- `manifest.json` with icons for iOS and Android +- Show a clean "Offline" state in UI +- Touch targets minimum 48px height (mobile-first) +- Swipe gestures on todo/shopping lists (left to postpone, right to complete) +- Wake Lock API on the shopping list active view (screen stays on in-store) + +## Integrations +- **Gitea**: `gitea.maison43.duckdns.org` — webhook endpoint `/api/webhooks/gitea` for issue/PR sync to Kanban +- **Home Assistant**: `10.0.0.2:8123` — expose delayed task count as sensor via REST/MQTT +- **Agent Hermes / Vision LLM**: `POST /api/shopping/analyze-fridge` — sends fridge photo to LLM for missing ingredient suggestions +- **MCP server**: embedded in FastAPI — exposes `get_todos()`, `add_todo()`, `add_shopping_item()`, `search_notes()` tools +- **CalDAV**: `/api/caldav/` for native iOS subscription +- **Google Calendar**: OAuth2 per user + async background worker + +## Development phases (reference) +1. Docker setup + PostgreSQL schemas + FastAPI auth + React PWA scaffold +2. Todos CRUD + Notes CRUD + mobile UI + full-text search (PostgreSQL FTS in French) +3. Shopping list (store mode + Wake Lock + frequency-based auto-fill + Hermes vision) +4. Calendar (CalDAV + Google OAuth2 sync worker) +5. MCP server + Gitea webhooks diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b95986 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# HomeHub + +Application d'organisation personnelle auto-hébergée — PWA mobile-first déployée sur Proxmox 9. + +## Fonctionnalités + +- **Todos** — tâches classées par domaine (informatique, DIY, jardinage, cuisine…) +- **Liste de courses** — générée depuis les habitudes d'achat, mode magasin avec Wake Lock, suivi des prix, OCR étiquettes et tickets +- **Notes** — saisie rapide avec photo, audio, GPS et métadonnées libres +- **MCP Server** — expose les données à des agents IA (Hermes, Claude, etc.) + +## Stack technique + +| Composant | Technologie | +|-----------|-------------| +| Frontend | React 18 + Vite + TypeScript + Tailwind CSS | +| Backend | Python 3.12 + FastAPI (async) | +| Base de données | PostgreSQL 16 (schémas multiples) | +| Migrations | Alembic | +| OCR | Tesseract 5 (service Docker dédié, partagé entre modules) | +| Scan code-barres | zxing-js (frontend, iOS + Android) | +| Catalogue produits | OpenFoodFacts API (~3M produits alimentaires) | +| Recherche image | SearXNG (auto-hébergé, fallback image produits) | +| Déploiement | Docker Compose · Nginx Proxy Manager | +| Design system | Gruvbox seventies (`design_system/`) | + +## Démarrage rapide (développement local) + +```bash +# Copier la configuration +cp .env.example .env + +# Lancer l'environnement de développement +./dev.sh + +# Backend disponible sur http://localhost:8000 +# Frontend disponible sur http://localhost:3000 +# Documentation API : http://localhost:8000/docs +``` + +## Structure du projet + +``` +home_hub/ +├── ocr/ +│ ├── app.py # Service FastAPI OCR (Tesseract + Pillow) +│ └── Dockerfile +├── product-search/ +│ ├── app.py # Client OpenFoodFacts + proxy SearXNG images +│ └── Dockerfile +├── backend/ +│ ├── app/ +│ │ ├── api/ # Endpoints par domaine (todos, shopping, notes, media, mcp) +│ │ ├── core/ # Config, base de données, middleware +│ │ ├── models/ # Modèles SQLAlchemy +│ │ ├── schemas/ # Schémas Pydantic +│ │ └── services/ +│ │ ├── media.py # Upload, compression, génération miniatures (Pillow) +│ │ ├── ocr.py # Client vers service ocr:8001 +│ │ └── ... # Suggestions shopping, sync calendrier (futur) +│ ├── alembic/ # Migrations de base de données +│ ├── Dockerfile +│ └── requirements.txt +├── frontend/ +│ ├── src/ +│ │ ├── components/ # Composants React +│ │ ├── pages/ # Pages par module +│ │ ├── hooks/ # Hooks personnalisés (camera, geolocation, wake-lock…) +│ │ └── api/ # Client API typé +│ ├── public/ +│ │ └── manifest.json +│ ├── Dockerfile +│ └── vite.config.ts +├── design_system/ # Design system Gruvbox seventies (tokens + composants) +├── docs/ +│ ├── spec.md # Spécification fonctionnelle complète +│ └── plan.md # Plan de développement par phases +├── docker-compose.yml +├── docker-compose.dev.yml +└── .env.example +``` + +## Documentation + +- [Spécification fonctionnelle](docs/spec.md) — features détaillées, schéma DB, interfaces +- [Plan de développement](docs/plan.md) — phases et tâches +- [Design system](design_system/README.md) — composants et règles visuelles +- API REST : `http://localhost:8000/docs` (Swagger auto-généré par FastAPI) + +## Déploiement (Proxmox) + +```bash +# Production +docker compose up -d + +# Nginx Proxy Manager pointe vers : +# homehub.local → frontend:3000 +# homehub.local/api → backend:8000 +# homehub.local/mcp → backend:8000/mcp (pour les agents IA) +``` + +## Évolutions prévues + +- Authentification multi-utilisateurs (JWT) +- Sync Google Calendar + CalDAV iOS +- Intégration Home Assistant +- Webhooks Gitea → Kanban +- Analyse frigo par Vision LLM (Hermes/Ollama) diff --git a/design_system/README.md b/design_system/README.md new file mode 100644 index 0000000..a0ee628 --- /dev/null +++ b/design_system/README.md @@ -0,0 +1,304 @@ +# mon design system — Gruvbox seventies + +> Design system rétro-futuriste pour applications de monitoring, ops, IoT, domotique. +> Orange brûlé, fond brun délavé en sombre / gris clair usé en clair. +> **Version 1.0** · deux thèmes (dark + light), 14+ composants React, palette GTK pour GNOME. + +--- + +## 🚀 Démarrage rapide (web) + +```html + + + + + + + + + + + + + + + + + + +
+ + + + + +``` + +Pour voir tout fonctionner, ouvre `examples/exemple-minimal.html`. + +--- + +## 📂 Contenu du package + +``` +export/ +├── README.md ← Ce fichier +├── consigne_design_system.md ← Brief pour agents IA (Claude, ChatGPT…) +├── tokens/ +│ ├── tokens.css ← Variables CSS web (dark + light) +│ ├── tokens.gnome.css ← GTK 4 / libadwaita (apps GNOME) +│ └── tokens.json ← Format générique (Tailwind, Figma…) +├── components/ +│ └── ui-kit.jsx ← 14 composants React (Button, IconButton, Toggle, Tooltip, +│ StatusLed, BatteryGauge, RadialGauge, BigRadialGauge, +│ Popup, TreeNav, Sparkline, LineChart, Icon, …) +└── examples/ + └── exemple-minimal.html ← Démo minimale autoportante +``` + +--- + +## 🎨 Ce qui est paramétrable + +### 1. Thème global + +```html + +``` + +Tu peux mettre `data-theme` sur **n'importe quel parent** pour basculer un sous-arbre uniquement (utile pour une preview en mode opposé dans un menu de réglages). + +### 2. Toutes les couleurs (CSS variables) + +Édite `tokens.css` ou surcharge dans ton propre CSS : + +```css +:root[data-theme="dark"] { + --accent: #fe8019; /* Couleur principale (orange seventies) */ + --accent-soft: #d65d0e; + --bg-1: #2a231d; /* Fond app */ + --bg-3: #3c332a; /* Cartes */ + --ink-1: #f2e5c7; /* Texte */ + --ok: #4dbb26; + --warn: #fabd2f; + --err: #fb4934; + --blue: #3db0d1; /* Datavis additionnel */ + --purple: #c882c8; +} +``` + +**4 statuts** (ok / warn / err / info) + **2 couleurs datavis** (blue / purple) + **6 niveaux de fond** + **4 niveaux d'encre** + **3 niveaux de bordure**. + +### 3. Polices + +Trois familles, toutes substituables : + +| Variable | Usage | Défaut | +|-----------------|-------------------------------------|---------------------| +| `--font-ui` | Interface (titres, corps, boutons) | Inter | +| `--font-mono` | Données, code, valeurs numériques | JetBrains Mono | +| `--font-terminal` | Logs, terminal embarqué, vibe rétro | Share Tech Mono | + +Pour changer, remplace simplement les `@import` Google Fonts et redéfinis les variables. + +### 4. Ombres et relief + +```css +--tile-3d /* Relief 3D marqué pour cartes */ +--shadow-1, -2, -3 /* Niveaux d'élévation */ +--shadow-press /* Inset pour état pressé */ +--hover-glow /* Halo accent au survol */ +``` + +### 5. Composants — props paramétrables + +Chaque composant accepte des props pour personnaliser sans toucher au CSS. Exemples : + +```jsx + + + + + + + + + + + + + Contenu + + + +``` + +Voir la doc complète des props : `Component Reference.html` dans le projet original. + +--- + +## 🐧 Utilisation dans une app GNOME (GTK 4 / libadwaita) + +Charge `tokens/tokens.gnome.css` comme provider CSS au démarrage de l'app. + +**Python (PyGObject)** : +```python +from gi.repository import Gtk, Gdk + +css_provider = Gtk.CssProvider() +css_provider.load_from_path("tokens.gnome.css") +Gtk.StyleContext.add_provider_for_display( + Gdk.Display.get_default(), + css_provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION +) +``` + +**GJS** : +```javascript +const provider = new Gtk.CssProvider(); +provider.load_from_path('tokens.gnome.css'); +Gtk.StyleContext.add_provider_for_display( + Gdk.Display.get_default(), + provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION +); +``` + +**Rust (gtk4-rs)** : +```rust +let provider = gtk::CssProvider::new(); +provider.load_from_path("tokens.gnome.css"); +gtk::style_context_add_provider_for_display( + &gdk::Display::default().unwrap(), + &provider, + gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, +); +``` + +Le fichier override directement les couleurs sémantiques de libadwaita (`@window_bg_color`, `@accent_color`, etc.) ET ajoute des styles spécifiques pour les widgets courants : `button.suggested-action`, `entry`, `switch`, `scale`, `progressbar`, `notebook`, `popover`… + +Classes CSS supplémentaires à appliquer via `add_css_class()` : +- `.tile` / `.card` — Tuile en relief 3D +- `.mono` — Texte monospace JetBrains Mono +- `.terminal` — Texte terminal Share Tech Mono +- `.status.ok` / `.status.warn` / `.status.error` / `.status.info` — Badge de statut + +--- + +## 🔧 Intégration dans d'autres outils + +### Tailwind CSS + +Convertis `tokens.json` en `tailwind.config.js` : + +```js +const tokens = require('./tokens/tokens.json'); +module.exports = { + theme: { + extend: { + colors: { + accent: tokens.themes.dark.accent.primary.value, + ok: tokens.themes.dark.status.ok.value, + // … + }, + fontFamily: { + sans: [tokens.typography.fonts.ui.family, ...tokens.typography.fonts.ui.fallback], + mono: [tokens.typography.fonts.mono.family], + }, + }, + }, +}; +``` + +### Figma / outils de design + +`tokens.json` suit un schéma compatible avec la plupart des plugins de tokens (Figma Tokens, Style Dictionary). Importe-le directement. + +### Variables Sass / SCSS + +```scss +@use 'sass:map'; +$tokens: ( + accent: #fe8019, + bg-1: #2a231d, + ok: #4dbb26, +); +// … +``` + +--- + +## ⚙️ Personnalisation avancée + +### Créer un thème dérivé + +Duplique `tokens.css`, change le nom du sélecteur (`[data-theme="ocean"]` par exemple) et modifie les variables. Charge les deux fichiers — `data-theme` choisira automatiquement. + +### Ajouter une couleur status custom + +```css +:root[data-theme="dark"] { + --critical: #ff0080; + --critical-glow: rgba(255, 0, 128, 0.45); +} +``` + +Utilisable ensuite partout : `` nécessite une PR dans `ui-kit.jsx` (carte `map` dans `StatusLed`), mais en raw CSS tu peux utiliser la variable directement. + +### Désactiver les effets + +Tous les effets de `transition` / `transform` / `box-shadow` sont concentrés dans les classes `.interactive`, `.bg-hover`, `.gauge-hover`. Surcharge-les en CSS si besoin : + +```css +.interactive { transition: none !important; } +``` + +--- + +## ✅ Checklist d'intégration + +- [ ] Polices Google Fonts chargées (Inter, JetBrains Mono, Share Tech Mono) +- [ ] Font Awesome 6 chargé +- [ ] `tokens.css` (web) **ou** `tokens.gnome.css` (GTK) chargé +- [ ] Attribut `data-theme="dark"` (ou "light") sur `` ou un parent +- [ ] React 18 + Babel chargés (uniquement pour `ui-kit.jsx`) +- [ ] `ui-kit.jsx` chargé en `type="text/babel"` + +--- + +## 📋 Statuts du système + +| Couleur | Token | Hex (dark) | Hex (light) | Usage | +|---------|--------|------------|-------------|-----------------------------| +| Accent | `--accent` | `#fe8019` | `#af3a03` | Primaire, focus, sélection | +| OK | `--ok` | `#4dbb26` | `#3c911c` | Succès, état nominal | +| Warn | `--warn` | `#fabd2f` | `#b57614` | Attention, latence élevée | +| Err | `--err` | `#fb4934` | `#9d0006` | Erreur, alerte critique | +| Info | `--info` | `#83a598` | `#427b58` | Information neutre | +| Blue | `--blue` | `#3db0d1` | `#2d82a3` | Datavis catégorie 2 | +| Purple | `--purple` | `#c882c8` | `#8c468c` | Datavis catégorie 3 | + +--- + +## 🤖 Pour les agents IA + +Si tu utilises ce design system avec une IA (Claude, GPT, Copilot, etc.), partage-lui le fichier **`consigne_design_system.md`**. Il y trouvera toutes les règles d'utilisation, conventions, contre-exemples à éviter. + +--- + +**Licence** · Usage libre dans tes projets. Pas de garantie. diff --git a/design_system/components/ui-kit.jsx b/design_system/components/ui-kit.jsx new file mode 100644 index 0000000..92f9e76 --- /dev/null +++ b/design_system/components/ui-kit.jsx @@ -0,0 +1,656 @@ +/* ============================================================ + ui-kit.jsx + Composants haute-fid Gruvbox Seventies. + Tout est purement décoratif/interactif côté composant. + Effets : transparence (glass), hover glow, click 3D, tooltips. + ============================================================ */ + +const { useState, useRef, useEffect } = React; + +/* ============================================================ + Icônes — Font Awesome 6 Free. + Mapping nom logique → classe FA. Le CSS de FA est chargé en CDN + dans le . Le composant garde la MÊME API qu'avant (name, + size, style) pour ne rien casser ailleurs. + ============================================================ */ +const ICON_MAP = { + cpu: 'microchip', + memory: 'memory', + disk: 'hard-drive', + network: 'network-wired', + clock: 'clock', + grid: 'table-cells', + list: 'list', + cog: 'gear', + alert: 'triangle-exclamation', + bell: 'bell', + server: 'server', + chart: 'chart-line', + bars: 'chart-simple', + terminal: 'terminal', + refresh: 'arrows-rotate', + play: 'play', + pause: 'pause', + power: 'power-off', + sun: 'sun', + moon: 'moon', + search: 'magnifying-glass', + close: 'xmark', + chevR: 'chevron-right', + chevL: 'chevron-left', + chevD: 'chevron-down', + chevU: 'chevron-up', + plus: 'plus', + filter: 'filter', + download: 'download', + folder: 'folder', + node: 'circle-nodes', + user: 'user', +}; + +const Icon = ({ name, size = 16, style }) => { + const fa = ICON_MAP[name] || 'circle-question'; + return ( +