From 937118a528cf98fc5eb1aac6aac893c2eee25fda Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Tue, 24 Feb 2026 04:05:19 +0800 Subject: [PATCH] Remove .claude directory from repository tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Local-only Claude Code context — not part of the UMBRA application. Files remain on disk, just untracked per .gitignore. Co-Authored-By: Claude Opus 4.6 --- .claude/CLAUDE.md | 165 --------------- .claude/context/stylesheet.md | 359 --------------------------------- .claude/projects/ui_refresh.md | 296 --------------------------- 3 files changed, 820 deletions(-) delete mode 100644 .claude/CLAUDE.md delete mode 100644 .claude/context/stylesheet.md delete mode 100644 .claude/projects/ui_refresh.md diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md deleted file mode 100644 index 02c2552..0000000 --- a/.claude/CLAUDE.md +++ /dev/null @@ -1,165 +0,0 @@ -# CLAUDE.md - UMBRA - -## CRUCIAL CONTEXT EFFICIENCY - -### Subagent Discipline -- Prefer inline work for tasks under ~5 tool calls. Subagents have overhead — don't delegate trivially. -- When using subagents, include output rules: "Final response under 2000 characters. List outcomes, not process." -- Never call TaskOutput twice for the same subagent. If it times out, increase the timeout — don't re-read. - -### File Reading -- Read files with purpose. Before reading a file, know what you're looking for. -- Use Grep to locate relevant sections before reading entire large files. -- Never re-read a file you've already read in this session. -- For files over 500 lines, use offset/limit to read only the relevant section. - -### Responses -- Don't echo back file contents you just read — the user can see them. -- Don't narrate tool calls ("Let me read the file..." / "Now I'll edit..."). Just do it. -- Keep explanations proportional to complexity. Simple changes need one sentence, not three paragraphs. - -## Deployment & Access - -- **UMBRA is hosted on a remote machine** at `http://10.0.69.35` (not localhost). -- **Login PIN:** `1993` -- **Rebuilds are manual.** Do not run `docker-compose` commands — the user will rebuild on the remote machine when needed. -- **Browser automation** can access the live app at `http://10.0.69.35`. - -## Operational Procedures - -- Before making any changes or edits to code, create a branch. Once work is completed, commit and push to the branch automatically, then merge into main and push. -- When required: For backend work invoke the 'backend-engineer' subagent, for work on the front end, invoke the 'frontend-engineer' subagent. To review work use the 'senior-code-reviewer' subagent and for any research use the 'research-analyst' subagent. -- For any frontend UI related work you MUST use the frontend design skill AND reference the [stylesheet](.claude/context/stylesheet.md) to ensure visual consistency. The stylesheet defines all colors, typography, spacing, component patterns, and design principles for UMBRA. Do not invent new patterns. - -## Future Roadmap - -After the UI refresh is complete, the next major phases are: -- **Multi-user authentication** — replace single PIN auth with per-user accounts -- **Backend restructure** — add user_id foreign keys to all models, scope all queries per-user -- **Always build for scale.** Even though UMBRA is currently single-user, design features, indexes, validations, and state machines with multi-user in mind. Cutting corners now means rework later. - -## Key Features & Patterns - -- **Reminder alerts**: Real-time polling (30s) via `AlertsProvider` context. Dashboard shows `AlertBanner`, other pages get Sonner toasts (max 3 + summary). Snooze/dismiss with `client_now` for Docker UTC offset. -- **Two-click delete**: `useConfirmAction` hook in `hooks/useConfirmAction.ts` — first click shows "Sure?", auto-resets after 4s, second click executes. Used by TodoItem and ReminderItem. -- **Naive datetime contract**: All datetimes are naive (no timezone). Frontend sends `toLocalDatetime()` from `lib/date-utils.ts` when the backend needs "now". Docker container runs UTC; `client_now` bridges the gap. - -## Known Issues - -- **Git push auth flake.** The first `git push` to the Gitea remote will fail with an authentication error. Simply retry the same push command — the second attempt succeeds. - -## Hard Rules - -- **Naive datetimes only.** The DB uses `TIMESTAMP WITHOUT TIME ZONE`. Never send timezone-aware strings (no `Z` suffix, no `.toISOString()`). Use local datetime formatting helpers instead. -- **Eager load relationships in async SQLAlchemy.** Any `response_model` that includes a relationship (e.g. `ProjectResponse.tasks`) must use `selectinload()` when querying. Lazy loading raises `MissingGreenlet` in async context. -- **Never shadow SQLAlchemy names.** Model columns must not be named `relationship`, `column`, `metadata`, or other SQLAlchemy reserved names. The `person.py` model aliases the import as `sa_relationship` for this reason. -- **Frontend date inputs require exact formats.** `` needs `YYYY-MM-DD`, `` needs `YYYY-MM-DDThh:mm`. Backend may return `2026-02-15T00:00:00` which must be sliced/converted before binding. -- **All API routes are prefixed with `/api`.** Frontend axios base URL is `/api`. Nginx proxies `/api/` to backend:8000. Never duplicate the prefix. - -## Tech Stack - -### Backend -- **Python 3.12** (slim Docker image - no curl, use `urllib` for healthchecks) -- **FastAPI** with async lifespan, Pydantic v2 (`model_dump()`, `ConfigDict(from_attributes=True)`) -- **SQLAlchemy 2.0** async with `Mapped[]` type hints, `mapped_column()`, `async_sessionmaker` -- **PostgreSQL 16** (Alpine) via `asyncpg` -- **Alembic** for migrations -- **Auth:** PIN-based with bcrypt + itsdangerous signed cookies (not JWT) - -### Frontend -- **React 18** + TypeScript + Vite 6 -- **TanStack Query v5** for server state (`useQuery`, `useMutation`, `invalidateQueries`) -- **FullCalendar 6** (dayGrid, timeGrid, interaction plugins) -- **Tailwind CSS 3** with custom dark theme + accent color CSS variables -- **Sonner** for toast notifications -- **Lucide React** for icons -- Custom shadcn/ui-style components in `frontend/src/components/ui/` - -### Infrastructure -- **Docker Compose** - 3 services: `db`, `backend`, `frontend` -- **Nginx** (Alpine) serves frontend SPA, proxies `/api/` to backend -- Frontend served on port **80**, backend on port **8000** - -## Authority Links - -- [ui_refresh.md](.claude/projects/ui_refresh.md) - UI overhaul project plan, audit findings, implementation stages -- [stylesheet.md](.claude/context/stylesheet.md) - Design system & visual reference for all frontend work - -## Project Structure - -``` -backend/app/ - main.py # FastAPI app, router registration, health endpoint - config.py # Pydantic BaseSettings (DATABASE_URL, SECRET_KEY) - database.py # Async engine, session factory, get_db dependency - models/ # SQLAlchemy 2.0 models (Mapped[] style) - schemas/ # Pydantic v2 request/response schemas - routers/ # One router per feature (auth, todos, events, etc.) - -frontend/src/ - App.tsx # Routes + ProtectedRoute wrapper - lib/api.ts # Axios instance + getErrorMessage helper - hooks/ # useAuth, useSettings, useTheme, useCalendars - types/index.ts # TypeScript interfaces matching backend schemas - components/ - ui/ # 16 base components (Button, Dialog, Sheet, Card, Input, Select, etc.) - layout/ # AppLayout + Sidebar - auth/ # LockScreen (PIN setup/login) - dashboard/ # DashboardPage + widgets (Stats, Calendar, Todo, Upcoming, Countdown, etc.) - calendar/ # CalendarPage, CalendarSidebar, CalendarForm, EventForm, TemplateForm - todos/ # TodosPage + TodoList + TodoItem + TodoForm - reminders/ # RemindersPage + ReminderList + ReminderForm - projects/ # ProjectsPage, ProjectCard, ProjectDetail, ProjectForm, KanbanBoard, TaskRow, TaskForm, TaskDetailPanel - people/ # PeoplePage + PersonCard + PersonForm - locations/ # LocationsPage + LocationCard + LocationForm - settings/ # SettingsPage (accent color, PIN change, first day of week) -``` - -## Essential Commands - -```bash -# Build and run all services -docker-compose up --build - -# Rebuild single service after changes -docker-compose up --build backend -docker-compose up --build frontend - -# View logs -docker-compose logs -f -docker-compose logs -f backend - -# Reset database (destroys all data) -docker-compose down -v && docker-compose up --build - -# Stop everything -docker-compose down -``` - -## API Routes - -All routes require auth (signed cookie) except `/api/auth/*` and `/health`. - -| Prefix | Resource | -|----------------------|-----------------| -| `/api/auth` | PIN setup/login/logout/status | -| `/api/todos` | Todos CRUD + toggle | -| `/api/events` | Calendar events CRUD (incl. recurring) | -| `/api/event-templates` | Event templates CRUD | -| `/api/calendars` | User calendars CRUD + visibility | -| `/api/reminders` | Reminders CRUD + dismiss | -| `/api/projects` | Projects + nested tasks CRUD | -| `/api/people` | People CRUD | -| `/api/locations` | Locations CRUD + search | -| `/api/settings` | Settings + PIN change | -| `/api/dashboard` | Dashboard aggregation | -| `/api/upcoming` | Unified upcoming items | -| `/api/weather` | Weather data proxy | - -## Stop Conditions - -- **Do not** add timezone info to datetime strings sent to the backend -- **Do not** use `datetime.utcnow()` - use `datetime.now(timezone.utc)` instead (deprecated in 3.12) -- **Do not** return relationships from async endpoints without `selectinload()` -- **Do not** use `curl` in backend Docker healthchecks (not available in python:slim) -- **Do not** use `git push --force` or destructive git operations without explicit approval diff --git a/.claude/context/stylesheet.md b/.claude/context/stylesheet.md deleted file mode 100644 index 2eb589b..0000000 --- a/.claude/context/stylesheet.md +++ /dev/null @@ -1,359 +0,0 @@ -# UMBRA Design System & Stylesheet - -> This document defines the visual language for every page in UMBRA. -> All frontend work MUST conform to these patterns. Do not invent new colors, spacing scales, or component styles. - ---- - -## Visual Reference - -The dashboard establishes the canonical look: a near-black canvas with thin-bordered cards, cyan accent highlights, the Sora/DM Sans type pairing, and subtle glow effects on interactive elements. Every page should feel like a natural extension of this dashboard. - -**Key visual characteristics:** -- Ultra-dark background (~#0a0a0a) with very subtle card elevation (#0d0d0d cards) -- Thin 1px borders in dark gray (#262626) - never heavy or prominent -- Accent color (default cyan) used sparingly: active nav, stat icons, today highlights, hover glows -- High-contrast white text on dark, with muted gray (#a3a3a3) for secondary content -- Cards have a gentle hover glow (`shadow-accent/5`) - not dramatic, just a hint of life -- Clean data-dense layouts with compact spacing - no wasted space -- Type badges and priority pills use color-coded backgrounds at 10% opacity (e.g. `bg-blue-500/10 text-blue-400`) - ---- - -## 1. Color Tokens (CSS Custom Properties) - -All colors use HSL format via CSS variables. Never hardcode hex values. - -### Surface Colors -| Token | HSL | Approx Hex | Usage | -|---|---|---|---| -| `--background` | `0 0% 3.9%` | `#0a0a0a` | Page background | -| `--card` | `0 0% 5%` | `#0d0d0d` | Card/panel surfaces | -| `--card-elevated` | `0 0% 7%` | `#121212` | Hover states, elevated surfaces | -| `--secondary` | `0 0% 10%` | `#1a1a1a` | Secondary backgrounds, muted surfaces | -| `--muted` | `0 0% 10%` | `#1a1a1a` | Disabled/muted backgrounds | - -### Text Colors -| Token | HSL | Approx Hex | Usage | -|---|---|---|---| -| `--foreground` | `0 0% 98%` | `#fafafa` | Primary text | -| `--muted-foreground` | `0 0% 63.9%` | `#a3a3a3` | Secondary/subtle text | - -### Border & Input -| Token | HSL | Approx Hex | Usage | -|---|---|---|---| -| `--border` | `0 0% 14.9%` | `#262626` | All borders, dividers | -| `--input` | `0 0% 14.9%` | `#262626` | Input borders | - -### Semantic Colors -| Token | HSL | Usage | -|---|---|---| -| `--destructive` | `0 62.8% 30.6%` | Delete actions, errors | -| `--primary` / `--accent-color` / `--ring` | Dynamic (accent HSL) | Primary actions, focus rings | - -### Accent System (Dynamic) - -The accent is composed of three root variables set at runtime by `useTheme`: -- `--accent-h` (hue) -- `--accent-s` (saturation) -- `--accent-l` (lightness) - -These feed into `--primary`, `--ring`, and `--accent-color`. - -**Presets:** -| Name | H | S | L | Approx Color | -|---|---|---|---|---| -| `cyan` (default) | 187 | 85.7% | 53.3% | Teal-cyan | -| `blue` | 217 | 91.2% | 59.8% | Bright blue | -| `purple` | 258 | 89.5% | 66.3% | Violet | -| `orange` | 21 | 94.6% | 53.3% | Warm orange | -| `green` | 142 | 70.6% | 45.3% | Emerald | - -### Semantic Color Assignments (Fixed per feature) - -These are NOT theme-dependent. They provide visual consistency for item types: - -| Feature | Text | Background | Usage | -|---|---|---|---| -| Todos | `text-blue-400` | `bg-blue-500/10` | Todo badges, type indicators | -| Events | `text-purple-400` | `bg-purple-500/10` | Event badges, calendar items | -| Reminders | `text-orange-400` | `bg-orange-500/10` | Reminder badges | -| Projects | `text-blue-400` | `bg-blue-500/10` | Project counts | -| In Progress | `text-purple-400` | `bg-purple-500/10` | Status indicators | -| Open Todos | `text-teal-400` | `bg-teal-500/10` | Stat cards | -| Weather | `text-amber-400` | `bg-amber-500/10` | Weather widget | -| High priority | `text-red-400` | `bg-red-500/10` | Priority pills | -| Medium priority | `text-yellow-400` | `bg-yellow-500/10` | Priority pills | -| Low priority | `text-green-400` | `bg-green-500/10` | Priority pills | - ---- - -## 2. Typography - -### Font Families -- **Headings:** `Sora` (`font-heading`) — all h1-h6, card titles, stat values, logo -- **Body:** `DM Sans` (`font-body`) — everything else - -### Type Scale (as used) -| Class | Usage | -|---|---| -| `text-[9px]` | Micro labels (priority badges, type tags) | -| `text-[10px] tracking-wider uppercase` | Stat labels | -| `text-[11px]` | Small metadata | -| `text-xs` | Timestamps, secondary metadata | -| `text-sm` | Body text, list items, form inputs, nav items | -| `text-lg font-semibold` | Card titles (with `font-heading`) | -| `text-xl font-bold tabular-nums` | Stat values (with `font-heading`) | -| `text-3xl font-bold tracking-tight` | Page greeting/hero (with `font-heading`) | - -### Font Rendering -```css -font-feature-settings: "rlig" 1, "calt" 1; --webkit-font-smoothing: antialiased; -``` - ---- - -## 3. Spacing & Layout - -### Border Radius -| Token | Value | Usage | -|---|---|---| -| `rounded-lg` | `0.5rem` (8px) | Cards, panels | -| `rounded-md` | `~6px` | Buttons, inputs | -| `rounded-sm` | `~4px` | Small elements | -| `rounded-full` | Pill | Badges, dots, icon containers | - -### Page Layout -``` -App Shell: flex h-screen overflow-hidden bg-background -├── Sidebar: w-64 (expanded) / w-16 (collapsed), border-r, bg-card -│ transition-all duration-300 -└── Content: flex-1 flex flex-col overflow-hidden - ├── MobileHeader: md:hidden, h-14, border-b, bg-card - └──
: flex-1 overflow-y-auto - └── Page content: px-6 py-6 -``` - -### Grid Patterns -| Pattern | Classes | Usage | -|---|---|---| -| Stat row | `grid gap-2.5 grid-cols-2 lg:grid-cols-4` | Dashboard stats | -| Main + sidebar | `grid gap-5 lg:grid-cols-5` → `lg:col-span-3` + `lg:col-span-2` | Dashboard layout | -| Card grid | `grid gap-4 md:grid-cols-2 lg:grid-cols-3` | List pages (people, locations, projects) | - -### Standard Spacing -- Page padding: `px-6 py-6` -- Card padding: `p-5` (header), `p-5 pt-0` (content/footer) -- Card gap in grid: `gap-4` to `gap-5` -- List row padding: `py-1.5 px-2` -- Section gap: `space-y-4` to `space-y-6` - ---- - -## 4. Component Patterns - -### Card -``` -Base: rounded-lg border bg-card text-card-foreground shadow-sm -Hover: hover:shadow-lg hover:shadow-accent/5 hover:border-accent/20 -Motion: transition-all duration-200 -Header: flex flex-col space-y-1.5 p-5 -Title: font-heading text-lg font-semibold leading-none tracking-tight -Content: p-5 pt-0 -Footer: flex items-center p-5 pt-0 -``` - -### Button (CVA variants) -``` -Base: inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium - transition-colors focus-visible:ring-2 focus-visible:ring-ring -Variants: - default: bg-accent text-accent-foreground hover:bg-accent/90 - destructive: bg-destructive text-destructive-foreground hover:bg-destructive/90 - outline: border border-input bg-background hover:bg-accent/10 hover:text-accent - secondary: bg-secondary text-secondary-foreground hover:bg-secondary/80 - ghost: hover:bg-accent/10 hover:text-accent - link: text-accent underline-offset-4 hover:underline -Sizes: - default: h-10 px-4 py-2 - sm: h-9 px-3 - lg: h-11 px-8 - icon: h-10 w-10 -``` - -### Badge -``` -Base: inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold -Variants: - default: border-transparent bg-accent text-accent-foreground - secondary: border-transparent bg-secondary text-secondary-foreground - destructive: border-transparent bg-destructive text-destructive-foreground - outline: text-foreground -``` - -### Input / Select / Textarea -``` -h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm -placeholder:text-muted-foreground -focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 -disabled:cursor-not-allowed disabled:opacity-50 -``` - -### Dialog -``` -Overlay: fixed inset-0 bg-background/80 backdrop-blur-sm -Content: border bg-card p-6 shadow-lg rounded-lg max-w-xl -Header: flex flex-col space-y-1.5 -Title: text-lg font-semibold leading-none tracking-tight -Footer: flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 -Close: absolute right-4 top-4, X icon h-4 w-4 -``` - -### Empty State -``` -Container: flex flex-col items-center justify-center py-16 px-4 -Icon: rounded-full bg-muted p-4 mb-4, icon h-8 w-8 text-muted-foreground -Title: text-lg font-semibold mb-1 -Desc: text-sm text-muted-foreground text-center max-w-sm mb-4 -Action: