4d2f924537
- Address Book: type dropdown always sorted alphabetically (ro locale), including custom types - Hot Desk: window ~half height (top-[35%] bottom-[35%]), door ~double height (h-16) - Mini Utilities: TVA calculator (19%) with add/extract modes, RON formatting, copy buttons - ROADMAP: new Phase 4B Pre-Launch Hardening with 10 structured tasks - CLAUDE.md: bumped versions (Address Book 0.1.1, Mini Utilities 0.1.1, Hot Desk 0.1.1), Visual Copilot separate repo note
345 lines
27 KiB
Markdown
345 lines
27 KiB
Markdown
# ArchiTools — Project Context for AI Assistants
|
|
|
|
> This file provides all context needed for Claude Code, Sonnet, or any AI model to work on this project from scratch.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev # http://localhost:3000
|
|
npx next build # verify zero errors before pushing
|
|
git push origin main # auto-deploys via Portainer webhook
|
|
```
|
|
|
|
---
|
|
|
|
## Project Overview
|
|
|
|
**ArchiTools** is a modular internal web dashboard for an architecture/engineering office group of 3 companies:
|
|
|
|
- **Beletage** (architecture)
|
|
- **Urban Switch** (urbanism)
|
|
- **Studii de Teren** (geotechnics)
|
|
|
|
It runs on an on-premise Ubuntu server at `10.10.10.166`, containerized with Docker, managed via Portainer, served by Nginx Proxy Manager.
|
|
|
|
### Stack
|
|
|
|
| Layer | Technology |
|
|
| ------------ | ---------------------------------------------------------------------------- |
|
|
| Framework | Next.js 16.x, App Router, TypeScript (strict) |
|
|
| Styling | Tailwind CSS v4, shadcn/ui |
|
|
| Database | PostgreSQL (10.10.10.166:5432) via Prisma v6 ORM |
|
|
| Storage | `DatabaseStorageAdapter` (PostgreSQL) — localStorage fallback available |
|
|
| File Storage | MinIO (10.10.10.166:9002 API / 9003 UI) — client configured, adapter pending |
|
|
| Auth | NextAuth v4 + Authentik OIDC (auth.beletage.ro) |
|
|
| Deploy | Docker multi-stage, Portainer CE, Nginx Proxy Manager |
|
|
| Repo | Gitea at `https://git.beletage.ro/gitadmin/ArchiTools` |
|
|
| Language | Code in **English**, UI in **Romanian** |
|
|
|
|
### Architecture Principles
|
|
|
|
- **Module platform, not monolith** — each module isolated with own types/services/hooks/components
|
|
- **Feature flags** gate module loading (disabled = zero bundle cost)
|
|
- **Storage abstraction**: `StorageService` interface with adapters (database default via Prisma, localStorage fallback)
|
|
- **Cross-module tagging system** as shared service
|
|
- **Auth via Authentik SSO** — NextAuth v4 + OIDC, group→role/company mapping
|
|
- **All entities** include `visibility` / `createdBy` fields from day one
|
|
- **Company logos** — theme-aware (light/dark variants), dual-rendered for SSR safety
|
|
|
|
---
|
|
|
|
## Repository Structure
|
|
|
|
```
|
|
src/
|
|
├── app/ # Routing only (thin wrappers)
|
|
│ ├── (modules)/ # Module route pages
|
|
│ └── layout.tsx # App shell
|
|
├── core/ # Platform services
|
|
│ ├── module-registry/ # Module registration + types
|
|
│ ├── feature-flags/ # Flag evaluation + env override
|
|
│ ├── storage/ # StorageService + adapters
|
|
│ │ └── adapters/ # localStorage adapter (+ future DB/MinIO)
|
|
│ ├── tagging/ # Cross-module tag service
|
|
│ ├── i18n/ # Romanian translations
|
|
│ ├── theme/ # Light/dark theme
|
|
│ └── auth/ # Auth types + stub (future Authentik)
|
|
├── modules/ # Module business logic
|
|
│ ├── <module-name>/
|
|
│ │ ├── components/ # Module UI components
|
|
│ │ ├── hooks/ # Module-specific hooks
|
|
│ │ ├── services/ # Module business logic
|
|
│ │ ├── types.ts # Module types
|
|
│ │ ├── config.ts # Module metadata
|
|
│ │ └── index.ts # Public exports
|
|
│ └── ...
|
|
├── shared/ # Shared UI
|
|
│ ├── components/
|
|
│ │ ├── ui/ # shadcn/ui primitives
|
|
│ │ ├── layout/ # Sidebar, Header
|
|
│ │ └── common/ # Reusable app components
|
|
│ ├── hooks/ # Shared hooks
|
|
│ └── lib/ # Utils (cn, etc.)
|
|
├── config/ # Global config
|
|
│ ├── modules.ts # Module registry entries
|
|
│ ├── flags.ts # Default feature flags
|
|
│ ├── navigation.ts # Sidebar nav structure
|
|
│ └── companies.ts # Company definitions
|
|
docs/ # 16 internal technical docs
|
|
legacy/ # Original HTML tools for reference
|
|
```
|
|
|
|
---
|
|
|
|
## Implemented Modules (16 total — 14 original + 2 new)
|
|
|
|
| # | Module | Route | Version | Key Features |
|
|
| --- | ---------------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| 1 | **Dashboard** | `/` | 0.1.0 | KPI cards (6), activity feed (last 20), module grid, external tools |
|
|
| 2 | **Email Signature** | `/email-signature` | 0.1.0 | Multi-company branding, address toggle (BTG/US/SDT), live preview, zoom/copy/download |
|
|
| 3 | **Word XML Generator** | `/word-xml` | 0.1.0 | Category-based XML gen, simple/advanced mode, ZIP export |
|
|
| 4 | **Registratura** | `/registratura` | 0.4.0 | CRUD registry, dynamic doc types, bidirectional Address Book, threads, backdating, **legal deadline tracking**, recipient registration, document expiry, **NAS network path attachments** (A/O/P/T drives, copy-to-clipboard), **detail sheet side panel**, **configurable column visibility**, **QuickLook attachment preview** (images: zoom/pan, PDFs: native viewer, multi-file navigation) |
|
|
| 5 | **Tag Manager** | `/tag-manager` | 0.2.0 | CRUD tags, category/scope/color, US/SDT seeds, mandatory categories, **ManicTime bidirectional sync** |
|
|
| 6 | **IT Inventory** | `/it-inventory` | 0.2.0 | Dynamic equipment types, rented status (purple pulse), **42U rack visualization**, type/status/company filters |
|
|
| 7 | **Address Book** | `/address-book` | 0.1.1 | CRUD contacts, card grid, vCard export, Registratura reverse lookup, **dynamic types (creatable)**, **alphabetically sorted type dropdown** |
|
|
| 8 | **Password Vault** | `/password-vault` | 0.3.0 | CRUD credentials, 9 categorii cu iconițe, **WiFi QR code real**, context-aware form, strength meter, company scope, **AES-256-GCM encryption** |
|
|
| 9 | **Mini Utilities** | `/mini-utilities` | 0.1.1 | Text case, char counter, percentage, **TVA calculator (19%)**, area converter, U→R, num→text, artifact cleaner, MDLPA, PDF reducer, OCR, color palette |
|
|
| 10 | **Prompt Generator** | `/prompt-generator` | 0.2.0 | Template-driven prompt builder, **18 templates** (14 text + 4 image), search bar, target type filter |
|
|
| 11 | **Digital Signatures** | `/digital-signatures` | 0.1.0 | CRUD assets, drag-and-drop file upload, tag chips |
|
|
| 12 | **Word Templates** | `/word-templates` | 0.1.0 | Template library, 8 categories, version tracking, .docx placeholder auto-detection |
|
|
| 13 | **AI Chat** | `/ai-chat` | 0.2.0 | Multi-provider (OpenAI/Claude/Ollama/demo), **project linking via Tag Manager**, provider status badge |
|
|
| 14 | **Hot Desk** | `/hot-desk` | 0.1.1 | 4 desks, week-ahead calendar, room layout (window+door proportioned), reserve/cancel |
|
|
| 15 | **ParcelSync** | `/parcel-sync` | 0.5.0 | eTerra ANCPI integration, **PostGIS database**, background sync, 23-layer catalog, enrichment pipeline, owner search, **per-UAT analytics dashboard**, **health check + maintenance detection** |
|
|
| 16 | **Visual Copilot** | `/visual-copilot` | 0.1.0 | AI-powered image analysis — **developed in separate repo** (`https://git.beletage.ro/gitadmin/vim`), placeholder in ArchiTools, will be merged as module later |
|
|
|
|
### Registratura — Legal Deadline Tracking (Termene Legale)
|
|
|
|
The Registratura module includes a full legal deadline tracking engine for Romanian construction permitting:
|
|
|
|
- **16 deadline types** across 5 categories (Avize, Completări, Analiză, Autorizare, Publicitate)
|
|
- **Working days vs calendar days** with Romanian public holiday support (including Orthodox Easter via Meeus algorithm)
|
|
- **Backward deadlines** (e.g., AC extension: 45 working days BEFORE expiry)
|
|
- **Chain deadlines** (resolving one prompts adding the next)
|
|
- **Tacit approval** (auto-detected when overdue + applicable type)
|
|
- **Tabbed UI**: "Registru" tab (existing registry) + "Termene legale" tab (deadline dashboard)
|
|
|
|
Key files:
|
|
|
|
- `services/working-days.ts` — Romanian holidays, `addWorkingDays()`, `isWorkingDay()`
|
|
- `services/deadline-catalog.ts` — 16 `DeadlineTypeDef` entries
|
|
- `services/deadline-service.ts` — `createTrackedDeadline()`, `resolveDeadline()`, `aggregateDeadlines()`
|
|
- `components/attachment-preview.tsx` — QuickLook-style fullscreen preview (images: zoom/pan, PDFs: blob URL iframe, multi-file nav)
|
|
- `components/deadline-dashboard.tsx` — Stats + filters + table
|
|
- `components/deadline-add-dialog.tsx` — 3-step wizard (category → type → date preview)
|
|
|
|
### ParcelSync — eTerra ANCPI GIS Integration
|
|
|
|
The ParcelSync module connects to Romania's national eTerra/ANCPI cadastral system:
|
|
|
|
- **eTerra API client** (`eterra-client.ts`): form-post auth, JSESSIONID cookie jar, session caching (9min TTL), auto-relogin, paginated fetching with `maxRecordCount=1000` + fallback page sizes (500, 200)
|
|
- **23-layer catalog** (`eterra-layers.ts`): TERENURI_ACTIVE, CLADIRI_ACTIVE, LIMITE_UAT, etc. organized in 6 categories
|
|
- **PostGIS storage**: `GisFeature` model with geometry column, SIRUTA-based partitioning, `enrichment` JSONB field
|
|
- **Background sync**: long-running jobs via server singleton, progress polling (2s), phase tracking (fetch → save → enrich)
|
|
- **Enrichment pipeline** (`enrich-service.ts`): hits eTerra `/api/immovable/list` per parcel to extract NR_CAD, NR_CF, PROPRIETARI, SUPRAFATA, INTRAVILAN, CATEGORIE_FOLOSINTA, HAS_BUILDING, etc.
|
|
- **Owner search**: DB-first (ILIKE on enrichment JSON) with eTerra API fallback
|
|
- **Per-UAT dashboard**: SQL aggregates (area stats, intravilan/extravilan, land use, top owners), CSS-only visualizations (donut ring, bar charts)
|
|
- **Health check** (`eterra-health.ts`): pings `eterra.ancpi.ro` every 3min, detects maintenance by keywords in HTML response, blocks login when down, UI shows amber "Mentenanță" state
|
|
- **Test UAT**: Feleacu (SIRUTA 57582, ~30k immovables, ~8k GIS features)
|
|
|
|
Key files:
|
|
|
|
- `services/eterra-client.ts` — API client (~1000 lines), session cache, pagination, retry
|
|
- `services/eterra-layers.ts` — 23-layer catalog with categories
|
|
- `services/sync-service.ts` — Layer sync engine with progress tracking
|
|
- `services/enrich-service.ts` — Enrichment pipeline (FeatureEnrichment type)
|
|
- `services/eterra-health.ts` — Health check singleton, maintenance detection
|
|
- `services/session-store.ts` — Server-side session management
|
|
- `components/parcel-sync-module.tsx` — Main UI (~4100 lines), 4 tabs (Export/Layers/Search/DB)
|
|
- `components/uat-dashboard.tsx` — Per-UAT analytics dashboard (CSS-only charts)
|
|
|
|
---
|
|
|
|
## Infrastructure
|
|
|
|
### Server: `10.10.10.166` (Ubuntu)
|
|
|
|
| Service | Port | Purpose |
|
|
| ----------------------- | ---------------------- | ----------------------------------- |
|
|
| **ArchiTools** | 3000 | This app (tools.beletage.ro) |
|
|
| **Gitea** | 3002 | Git hosting (git.beletage.ro) |
|
|
| **PostgreSQL** | 5432 | App database (Prisma ORM) |
|
|
| **Portainer** | 9000 | Docker management |
|
|
| **Nginx Proxy Manager** | 81 (admin) | Reverse proxy + SSL termination |
|
|
| **Uptime Kuma** | 3001 | Service monitoring |
|
|
| **MinIO** | 9002 (API) / 9003 (UI) | Object storage |
|
|
| **Authentik** | 9100 | SSO (auth.beletage.ro) — **active** |
|
|
| **N8N** | 5678 | Workflow automation (future) |
|
|
| **Stirling PDF** | 8087 | PDF tools |
|
|
| **IT-Tools** | 8085 | Developer utilities |
|
|
| **FileBrowser** | 8086 | File management |
|
|
| **Netdata** | 19999 | System monitoring |
|
|
| **Dozzle** | 9999 | Docker log viewer |
|
|
| **CrowdSec** | 8088 | Security |
|
|
|
|
### Deployment Pipeline
|
|
|
|
```
|
|
git push origin main
|
|
→ Gitea webhook fires
|
|
→ Portainer CE detects new commit
|
|
→ Manual "Pull and redeploy" in Portainer (CE doesn't auto-rebuild)
|
|
→ Docker multi-stage build (~1-2 min)
|
|
→ Container starts on :3000
|
|
→ Nginx Proxy Manager routes to tools.beletage.ro
|
|
```
|
|
|
|
### Docker
|
|
|
|
- `Dockerfile`: 3-stage build (deps → builder → runner), `node:20-alpine`, non-root user
|
|
- `Dockerfile` includes `npx prisma generate` before build step
|
|
- `docker-compose.yml`: single service, port 3000, **all env vars hardcoded** (Portainer CE can't inject env vars)
|
|
- `output: 'standalone'` in `next.config.ts` is **required**
|
|
- `@prisma/client` must be in `dependencies` (not devDependencies) for runtime
|
|
|
|
---
|
|
|
|
## Development Rules
|
|
|
|
### TypeScript Strict Mode Gotchas
|
|
|
|
- `array.split()[0]` returns `string | undefined` — use `.slice(0, 10)` instead
|
|
- `Record<string, T>[key]` returns `T | undefined` — always guard with null check
|
|
- Spread of possibly-undefined objects: `{ ...obj[key], field }` — check existence first
|
|
- lucide-react Icons: cast through `unknown` → `React.ComponentType<{ className?: string }>`
|
|
- `arr[0]` is `T | undefined` even after `arr.length > 0` check — assign to const first: `const first = arr[0]; if (first) { ... }`
|
|
- Prisma `$queryRaw` returns `unknown[]` — always cast with `as Array<{ field: type }>` and guard access
|
|
- `?? ""` on an object field typed `{}` produces `{}` not `string` — use explicit `typeof x === 'string'` or `'number'` check
|
|
|
|
### Conventions
|
|
|
|
- **Code**: English
|
|
- **UI text**: Romanian
|
|
- **Components**: functional, `'use client'` directive where needed
|
|
- **State**: localStorage via `useStorage('module-name')` hook
|
|
- **IDs**: `uuid v4`
|
|
- **Dates**: ISO strings (`YYYY-MM-DD` for display, full ISO for timestamps)
|
|
- **No emojis** in code or UI unless explicitly requested
|
|
|
|
### Storage Performance Rules
|
|
|
|
- **NEVER** use `storage.list()` followed by `storage.get()` in a loop — this is an N+1 query bug
|
|
- `list()` fetches ALL items (keys+values) from DB but discards values, then each `get()` re-fetches individually
|
|
- **ALWAYS** use `storage.exportAll()` (namespaced) or `storage.export(namespace)` (service-level) to batch-load
|
|
- Filter items client-side after a single fetch: `for (const [key, value] of Object.entries(all)) { ... }`
|
|
- After mutations (add/update), either do optimistic local state update or a single `refresh()` — never both
|
|
- **NEVER store large binary data (base64 files) inside entity JSON** — this makes list loading transfer tens of MB
|
|
- For modules with attachments: use `exportAll({ lightweight: true })` for listing, `storage.get()` for single-entry full load
|
|
- The API `?lightweight=true` parameter strips `data`/`fileData` strings >1KB from JSON values server-side
|
|
- Future: move file data to MinIO; only store metadata (name, size, type, url) in the entity JSON
|
|
|
|
### Module Development Pattern
|
|
|
|
Every module follows:
|
|
|
|
```
|
|
src/modules/<name>/
|
|
├── components/ # React components
|
|
├── hooks/ # Custom hooks (use-<name>.ts)
|
|
├── services/ # Business logic (pure functions)
|
|
├── types.ts # TypeScript interfaces
|
|
├── config.ts # ModuleConfig metadata
|
|
└── index.ts # Public exports
|
|
```
|
|
|
|
### eTerra / External API Rules
|
|
|
|
- **ArcGIS REST API** has `maxRecordCount=1000` — always paginate with `resultOffset`/`resultRecordCount`
|
|
- **eTerra sessions expire after ~10min** — session cache TTL is 9min, auto-relogin on 401/redirect
|
|
- **eTerra goes into maintenance regularly** — health check must detect and block login attempts
|
|
- **Never hardcode timeouts too low** — eTerra 1000-feature geometry pages can take 60-90s; default is 120s
|
|
- **CookieJar + axios-cookiejar-support** required for eTerra auth (JSESSIONID tracking)
|
|
- **Page size fallbacks**: if 1000 fails, retry with 500, then 200
|
|
|
|
### Before Pushing
|
|
|
|
1. `npx next build` — must pass with zero errors
|
|
2. Test the feature manually on `localhost:3000`
|
|
3. Commit with descriptive message
|
|
4. `git push origin main` — Portainer auto-deploys
|
|
|
|
---
|
|
|
|
## Company IDs
|
|
|
|
| ID | Name | Prefix |
|
|
| ----------------- | --------------- | ------ |
|
|
| `beletage` | Beletage | B |
|
|
| `urban-switch` | Urban Switch | US |
|
|
| `studii-de-teren` | Studii de Teren | SDT |
|
|
| `group` | Grup | G |
|
|
|
|
---
|
|
|
|
## Current Integrations
|
|
|
|
| Feature | Status | Notes |
|
|
| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------ |
|
|
| **Authentik SSO** | ✅ Active | NextAuth v4 + OIDC, group→role/company mapping |
|
|
| **PostgreSQL** | ✅ Active | Prisma ORM, `KeyValueStore` model, `/api/storage` route |
|
|
| **MinIO** | Client configured | 10.10.10.166:9002, bucket `tools`, adapter pending |
|
|
| **AI Chat API** | ✅ Multi-provider | `/api/ai-chat` — OpenAI/Claude/Ollama/demo; needs API key env |
|
|
| **Vault Encryption** | ✅ Active | AES-256-GCM server-side, `/api/vault`, ENCRYPTION_SECRET env |
|
|
| **ManicTime Sync** | ✅ Implemented | `/api/manictime` — bidirectional Tags.txt sync, needs SMB mount |
|
|
| **NAS Paths** | ✅ Active | `\\newamun` (10.10.10.10), drives A/O/P/T, hostname+IP fallback, `src/config/nas-paths.ts` |
|
|
| **eTerra ANCPI** | ✅ Active | ParcelSync module, `eterra-client.ts`, health check + maintenance detection |
|
|
| **PostGIS** | ✅ Active | `GisFeature` model, geometry storage, spatial queries, used by ParcelSync |
|
|
| **N8N automations** | Webhook URL configured | For notifications, backups, workflows |
|
|
|
|
---
|
|
|
|
## Model Recommendations
|
|
|
|
| Task Type | Claude | OpenAI | Google | Notes |
|
|
| ----------------------------- | -------------- | ------------- | ---------------- | ----------------------------------------------- |
|
|
| **Bug fixes, config** | Haiku 4.5 | GPT-4o-mini | Gemini 2.5 Flash | Fast, cheap |
|
|
| **Features, tests, UI** | **Sonnet 4.6** | GPT-5.2 | Gemini 3 Flash | Best value — Opus-class quality at Sonnet price |
|
|
| **New modules, architecture** | Opus 4.6 | GPT-5.3-Codex | Gemini 3 Pro | Complex multi-file, business logic |
|
|
|
|
**Default: Sonnet 4.6** for most work. See `ROADMAP.md` for per-task recommendations.
|
|
|
|
### Session Handoff Tips
|
|
|
|
- Read this `CLAUDE.md` first — it has all context
|
|
- Read `ROADMAP.md` for the complete task list with dependencies
|
|
- Check `docs/` for deep dives on specific systems
|
|
- Check `src/modules/<name>/types.ts` before modifying any module
|
|
- Always run `npx next build` before committing
|
|
- Push to `main` → Portainer auto-deploys via Gitea webhook
|
|
- The 16 docs in `docs/` total ~10,600 lines — search them for architecture questions
|
|
|
|
---
|
|
|
|
## Documentation Index
|
|
|
|
| Doc | Path | Content |
|
|
| ------------------- | ------------------------------------------ | -------------------------------------------- |
|
|
| System Architecture | `docs/architecture/SYSTEM-ARCHITECTURE.md` | Overall architecture, module platform design |
|
|
| Module System | `docs/architecture/MODULE-SYSTEM.md` | Module registry, lifecycle, config format |
|
|
| Feature Flags | `docs/architecture/FEATURE-FLAGS.md` | Flag system, env overrides |
|
|
| Storage Layer | `docs/architecture/STORAGE-LAYER.md` | StorageService interface, adapters |
|
|
| Tagging System | `docs/architecture/TAGGING-SYSTEM.md` | Cross-module tags |
|
|
| Security & Roles | `docs/architecture/SECURITY-AND-ROLES.md` | Visibility, auth, roles |
|
|
| Module Dev Guide | `docs/guides/MODULE-DEVELOPMENT.md` | How to create a new module |
|
|
| HTML Integration | `docs/guides/HTML-TOOL-INTEGRATION.md` | Legacy tool migration |
|
|
| UI Design System | `docs/guides/UI-DESIGN-SYSTEM.md` | Design tokens, component patterns |
|
|
| Docker Deployment | `docs/guides/DOCKER-DEPLOYMENT.md` | Full Docker/Portainer/Nginx guide |
|
|
| Coding Standards | `docs/guides/CODING-STANDARDS.md` | TS strict, naming, patterns |
|
|
| Testing Strategy | `docs/guides/TESTING-STRATEGY.md` | Testing approach |
|
|
| Configuration | `docs/guides/CONFIGURATION.md` | Env vars, flags, companies |
|
|
| Data Model | `docs/DATA-MODEL.md` | All entity schemas |
|
|
| Repo Structure | `docs/REPO-STRUCTURE.md` | Directory layout |
|
|
| Prompt Generator | `docs/modules/PROMPT-GENERATOR.md` | Prompt module deep dive |
|