feat(2.0): Phase 0 — Greenfield-Skeleton (FastAPI + React/shadcn)

Backend: FastAPI mit /api/health + /api/models (read-only aus llama-swap
config, Logik aus v1 portiert). Frontend: Vite + React + Tailwind v4 +
shadcn-Style App-Shell mit Cmd+K, Dark-default, PWA-Manifest; Modelle-View
live aus /api/models. Deploy-Geruest (systemd-Unit :9001, build/deploy-
Skripte, NOPASSWD-sudoers, kein Klartext-Passwort).

Verifiziert: Backend-Endpunkte + Frontend-Build + gerenderte Shell.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-24 22:17:45 +02:00
commit b805c294eb
30 changed files with 3972 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
@import "tailwindcss";
/* Design-System (von v3 übernommen): EINE Akzentfarbe Teal #2dd4bf.
Dark als Default; Light als Fallback. Tokens als CSS-Variablen → shadcn-Style. */
:root {
--background: 0 0% 100%;
--foreground: 222 22% 12%;
--card: 0 0% 100%;
--card-foreground: 222 22% 12%;
--popover: 0 0% 100%;
--popover-foreground: 222 22% 12%;
--primary: 172 70% 38%;
--primary-foreground: 0 0% 100%;
--muted: 220 14% 95%;
--muted-foreground: 220 9% 42%;
--accent: 220 14% 94%;
--accent-foreground: 222 22% 12%;
--border: 220 13% 88%;
--input: 220 13% 88%;
--ring: 172 66% 50%;
--radius: 0.65rem;
}
.dark {
--background: 222 24% 7%;
--foreground: 210 20% 92%;
--card: 222 22% 10%;
--card-foreground: 210 20% 92%;
--popover: 222 24% 9%;
--popover-foreground: 210 20% 92%;
--primary: 172 66% 50%;
--primary-foreground: 222 47% 8%;
--muted: 220 14% 15%;
--muted-foreground: 215 14% 62%;
--accent: 220 14% 17%;
--accent-foreground: 210 20% 92%;
--border: 220 14% 19%;
--input: 220 14% 19%;
--ring: 172 66% 50%;
}
/* Tailwind-v4-Mapping: macht bg-background, text-foreground, border-border … nutzbar
und an die obigen (themable) Variablen gebunden. */
@theme inline {
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-card: hsl(var(--card));
--color-card-foreground: hsl(var(--card-foreground));
--color-popover: hsl(var(--popover));
--color-popover-foreground: hsl(var(--popover-foreground));
--color-primary: hsl(var(--primary));
--color-primary-foreground: hsl(var(--primary-foreground));
--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));
--color-accent: hsl(var(--accent));
--color-accent-foreground: hsl(var(--accent-foreground));
--color-border: hsl(var(--border));
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
}
* {
border-color: hsl(var(--border));
}
html,
body,
#root {
height: 100%;
}
body {
margin: 0;
background-color: hsl(var(--background));
color: hsl(var(--foreground));
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
-webkit-font-smoothing: antialiased;
}