Rename all workspace packages to reflect the actual project name: - @caldav/client -> @calchat/client - @caldav/server -> @calchat/server - @caldav/shared -> @calchat/shared - Root package: caldav-mono -> calchat-mono Update all import statements across client and server to use the new package names. Update default MongoDB database name and logging service identifier accordingly.
440 lines
22 KiB
Markdown
440 lines
22 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
**CalChat** is a calendar mobile app with AI support. The core concept is managing calendar events through a chat interface with an AI chatbot. Users can add, edit, and delete events via natural language conversation.
|
|
|
|
This is a fullstack TypeScript monorepo with npm workspaces.
|
|
|
|
## Commands
|
|
|
|
### Root (monorepo)
|
|
```bash
|
|
npm install # Install all dependencies for all workspaces
|
|
npm run format # Format all TypeScript files with Prettier
|
|
```
|
|
|
|
### Client (apps/client) - Expo React Native app
|
|
```bash
|
|
npm run start -w @calchat/client # Start Expo dev server
|
|
npm run android -w @calchat/client # Start on Android
|
|
npm run ios -w @calchat/client # Start on iOS
|
|
npm run web -w @calchat/client # Start web version
|
|
npm run lint -w @calchat/client # Run ESLint
|
|
npm run build:apk -w @calchat/client # Build APK locally with EAS
|
|
```
|
|
|
|
### Server (apps/server) - Express.js backend
|
|
```bash
|
|
npm run dev -w @calchat/server # Start dev server with hot reload (tsx watch)
|
|
npm run build -w @calchat/server # Compile TypeScript
|
|
npm run start -w @calchat/server # Run compiled server (port 3000)
|
|
```
|
|
|
|
## Technology Stack
|
|
|
|
| Area | Technology | Purpose |
|
|
|------|------------|---------|
|
|
| Frontend | React Native | Mobile UI Framework |
|
|
| | Expo | Development platform |
|
|
| | Expo-Router | File-based routing |
|
|
| | NativeWind | Tailwind CSS for React Native |
|
|
| | Zustand | State management |
|
|
| | FlashList | High-performance lists |
|
|
| | EAS Build | Local APK/IPA builds |
|
|
| Backend | Express.js | Web framework |
|
|
| | MongoDB | Database |
|
|
| | Mongoose | ODM |
|
|
| | GPT (OpenAI) | AI/LLM for chat |
|
|
| | X-User-Id Header | Authentication (simple, no JWT yet) |
|
|
| | pino / pino-http | Structured logging |
|
|
| | react-native-logs | Client-side logging |
|
|
| Planned | iCalendar | Event export/import |
|
|
|
|
## Architecture
|
|
|
|
### Workspace Structure
|
|
```
|
|
apps/client - @calchat/client - Expo React Native app
|
|
apps/server - @calchat/server - Express.js backend
|
|
packages/shared - @calchat/shared - Shared TypeScript types and models
|
|
```
|
|
|
|
### Frontend Architecture (apps/client)
|
|
|
|
```
|
|
src/
|
|
├── app/ # Expo-Router file-based routing
|
|
│ ├── _layout.tsx # Root Stack layout
|
|
│ ├── index.tsx # Entry redirect
|
|
│ ├── login.tsx # Login screen
|
|
│ ├── register.tsx # Registration screen
|
|
│ ├── (tabs)/ # Tab navigation group
|
|
│ │ ├── _layout.tsx # Tab bar configuration
|
|
│ │ ├── chat.tsx # Chat screen (AI conversation)
|
|
│ │ └── calendar.tsx # Calendar overview
|
|
│ ├── event/
|
|
│ │ └── [id].tsx # Event detail screen (dynamic route)
|
|
│ └── note/
|
|
│ └── [id].tsx # Note editor for event (dynamic route)
|
|
├── components/
|
|
│ ├── BaseBackground.tsx # Common screen wrapper
|
|
│ ├── Header.tsx # Header component with logout button
|
|
│ ├── AuthButton.tsx # Reusable button for auth screens (with shadow)
|
|
│ ├── EventCardBase.tsx # Shared event card layout with icons (used by EventCard & ProposedEventCard)
|
|
│ ├── EventCard.tsx # Calendar event card (uses EventCardBase + edit/delete buttons)
|
|
│ ├── EventConfirmDialog.tsx # AI-proposed event confirmation modal
|
|
│ └── ProposedEventCard.tsx # Chat event proposal (uses EventCardBase + confirm/reject buttons)
|
|
├── Themes.tsx # Centralized color/theme definitions
|
|
├── logging/
|
|
│ ├── index.ts # Re-exports
|
|
│ └── logger.ts # react-native-logs config (apiLogger, storeLogger)
|
|
├── services/
|
|
│ ├── index.ts # Re-exports all services
|
|
│ ├── ApiClient.ts # HTTP client with X-User-Id header injection, request logging
|
|
│ ├── AuthService.ts # login(), register(), logout() - calls API and updates AuthStore
|
|
│ ├── EventService.ts # getAll(), getById(), getByDateRange(), create(), update(), delete()
|
|
│ └── ChatService.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation()
|
|
└── stores/ # Zustand state management
|
|
├── index.ts # Re-exports all stores
|
|
├── AuthStore.ts # user, isAuthenticated, isLoading, login(), logout(), loadStoredUser()
|
|
│ # Uses expo-secure-store (native) / localStorage (web)
|
|
├── ChatStore.ts # messages[], addMessage(), addMessages(), updateMessage(), clearMessages(), chatMessageToMessageData()
|
|
└── EventsStore.ts # events[], setEvents(), addEvent(), updateEvent(), deleteEvent()
|
|
```
|
|
|
|
**Routing:** Tab-based navigation with Chat and Calendar as main screens. Auth screens (login, register) outside tabs. Dynamic routes for event detail and note editing.
|
|
|
|
### Backend Architecture (apps/server)
|
|
|
|
```
|
|
src/
|
|
├── app.ts # Entry point, DI setup, Express config
|
|
├── controllers/ # Request handlers + middleware (per architecture diagram)
|
|
│ ├── AuthController.ts # login(), register(), refresh(), logout()
|
|
│ ├── ChatController.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation()
|
|
│ ├── EventController.ts # create(), getById(), getAll(), getByDateRange(), update(), delete()
|
|
│ ├── AuthMiddleware.ts # authenticate() - X-User-Id header validation
|
|
│ └── LoggingMiddleware.ts # httpLogger - pino-http request logging
|
|
├── logging/
|
|
│ ├── index.ts # Re-exports
|
|
│ ├── logger.ts # pino config with redact for sensitive data
|
|
│ └── Logged.ts # @Logged() class decorator for automatic method logging
|
|
├── routes/ # API endpoint definitions
|
|
│ ├── index.ts # Combines all routes under /api
|
|
│ ├── auth.routes.ts # /api/auth/*
|
|
│ ├── chat.routes.ts # /api/chat/* (protected)
|
|
│ └── event.routes.ts # /api/events/* (protected)
|
|
├── services/ # Business logic
|
|
│ ├── interfaces/ # DB-agnostic interfaces (for dependency injection)
|
|
│ │ ├── AIProvider.ts # processMessage()
|
|
│ │ ├── UserRepository.ts # findById, findByEmail, findByUserName, create + CreateUserData
|
|
│ │ ├── EventRepository.ts
|
|
│ │ └── ChatRepository.ts
|
|
│ ├── AuthService.ts
|
|
│ ├── ChatService.ts
|
|
│ └── EventService.ts
|
|
├── repositories/ # Data access (DB-specific implementations)
|
|
│ ├── index.ts # Re-exports from ./mongo
|
|
│ └── mongo/ # MongoDB implementation
|
|
│ ├── models/ # Mongoose schemas
|
|
│ │ ├── types.ts # Shared types (IdVirtual interface)
|
|
│ │ ├── UserModel.ts
|
|
│ │ ├── EventModel.ts
|
|
│ │ └── ChatModel.ts
|
|
│ ├── MongoUserRepository.ts # findById, findByEmail, findByUserName, create
|
|
│ ├── MongoEventRepository.ts
|
|
│ └── MongoChatRepository.ts
|
|
├── ai/
|
|
│ ├── GPTAdapter.ts # Implements AIProvider using OpenAI GPT
|
|
│ ├── index.ts # Re-exports GPTAdapter
|
|
│ └── utils/ # Shared AI utilities (provider-agnostic)
|
|
│ ├── index.ts # Re-exports
|
|
│ ├── eventFormatter.ts # formatExistingEvents() for system prompt
|
|
│ ├── systemPrompt.ts # buildSystemPrompt() - German calendar assistant prompt
|
|
│ ├── toolDefinitions.ts # TOOL_DEFINITIONS - provider-agnostic tool specs
|
|
│ └── toolExecutor.ts # executeToolCall() - handles getDay, proposeCreate/Update/Delete, searchEvents
|
|
├── utils/
|
|
│ ├── jwt.ts # signToken(), verifyToken() - NOT USED YET (no JWT)
|
|
│ ├── password.ts # hash(), compare() using bcrypt
|
|
│ ├── eventFormatters.ts # getWeeksOverview(), getMonthOverview() - formatted event listings
|
|
│ └── recurrenceExpander.ts # expandRecurringEvents() - expand recurring events into occurrences
|
|
└── scripts/
|
|
└── hash-password.js # Utility to hash passwords for manual DB updates
|
|
```
|
|
|
|
**API Endpoints:**
|
|
- `POST /api/auth/login` - User login
|
|
- `POST /api/auth/register` - User registration
|
|
- `POST /api/auth/refresh` - Refresh JWT token
|
|
- `POST /api/auth/logout` - User logout
|
|
- `GET /api/events` - Get all events (protected)
|
|
- `GET /api/events/range` - Get events by date range (protected)
|
|
- `GET /api/events/:id` - Get single event (protected)
|
|
- `POST /api/events` - Create event (protected)
|
|
- `PUT /api/events/:id` - Update event (protected)
|
|
- `DELETE /api/events/:id` - Delete event (protected)
|
|
- `POST /api/chat/message` - Send message to AI (protected)
|
|
- `POST /api/chat/confirm/:conversationId/:messageId` - Confirm proposed event (protected)
|
|
- `POST /api/chat/reject/:conversationId/:messageId` - Reject proposed event (protected)
|
|
- `GET /api/chat/conversations` - Get all conversations (protected)
|
|
- `GET /api/chat/conversations/:id` - Get messages of a conversation with cursor-based pagination (protected)
|
|
- `GET /health` - Health check
|
|
- `POST /api/ai/test` - AI test endpoint (development only)
|
|
|
|
### Shared Package (packages/shared)
|
|
|
|
```
|
|
src/
|
|
├── index.ts
|
|
├── models/
|
|
│ ├── index.ts
|
|
│ ├── User.ts # User, CreateUserDTO, LoginDTO, AuthResponse
|
|
│ ├── CalendarEvent.ts # CalendarEvent, CreateEventDTO, UpdateEventDTO, ExpandedEvent
|
|
│ ├── ChatMessage.ts # ChatMessage, Conversation, SendMessageDTO, CreateMessageDTO,
|
|
│ │ # GetMessagesOptions, ChatResponse, ConversationSummary,
|
|
│ │ # ProposedEventChange, EventAction, RespondedAction, UpdateMessageDTO
|
|
│ └── Constants.ts # DAYS, MONTHS, Day, Month, DAY_INDEX, DAY_INDEX_TO_DAY,
|
|
│ # DAY_TO_GERMAN, DAY_TO_GERMAN_SHORT, MONTH_TO_GERMAN
|
|
└── utils/
|
|
├── index.ts
|
|
└── dateHelpers.ts # getDay() - get date for specific weekday relative to today
|
|
```
|
|
|
|
**Key Types:**
|
|
- `User`: id, email, userName, passwordHash?, createdAt?, updatedAt?
|
|
- `CalendarEvent`: id, userId, title, description?, startTime, endTime, note?, isRecurring?, recurrenceRule?
|
|
- `ExpandedEvent`: Extends CalendarEvent with occurrenceStart, occurrenceEnd (for recurring event instances)
|
|
- `ChatMessage`: id, conversationId, sender ('user' | 'assistant'), content, proposedChanges?
|
|
- `ProposedEventChange`: id, action ('create' | 'update' | 'delete'), eventId?, event?, updates?, respondedAction?
|
|
- Each proposal has unique `id` (e.g., "proposal-0") for individual confirm/reject
|
|
- `respondedAction` tracks user response per proposal (not per message)
|
|
- `Conversation`: id, userId, createdAt?, updatedAt? (messages loaded separately via lazy loading)
|
|
- `CreateUserDTO`: email, userName, password (for registration)
|
|
- `LoginDTO`: identifier (email OR userName), password
|
|
- `CreateEventDTO`: Used for creating events AND for AI-proposed events
|
|
- `GetMessagesOptions`: Cursor-based pagination with `before?: string` and `limit?: number`
|
|
- `ConversationSummary`: id, lastMessage?, createdAt? (for conversation list)
|
|
- `UpdateMessageDTO`: proposalId?, respondedAction? (for marking individual proposals as confirmed/rejected)
|
|
- `RespondedAction`: 'confirm' | 'reject' (tracks user response to proposed events)
|
|
- `Day`: "Monday" | "Tuesday" | ... | "Sunday"
|
|
- `Month`: "January" | "February" | ... | "December"
|
|
|
|
### Database Abstraction
|
|
|
|
The repository pattern allows swapping databases:
|
|
- **Interfaces** (`services/interfaces/`) are DB-agnostic
|
|
- **Implementations** (`repositories/mongo/`) are DB-specific
|
|
- To add MySQL: create `repositories/mysql/` with TypeORM entities
|
|
|
|
### Mongoose Model Pattern
|
|
|
|
All Mongoose models use a consistent pattern for TypeScript-safe `id` virtuals:
|
|
|
|
```typescript
|
|
import { IdVirtual } from './types';
|
|
|
|
const Schema = new Schema<Doc, Model<Doc, {}, {}, IdVirtual>, {}, {}, IdVirtual>(
|
|
{ /* fields */ },
|
|
{
|
|
virtuals: {
|
|
id: {
|
|
get() { return this._id.toString(); }
|
|
}
|
|
},
|
|
toJSON: {
|
|
virtuals: true,
|
|
transform: (_, ret) => {
|
|
delete ret._id;
|
|
delete ret.__v;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
);
|
|
```
|
|
|
|
Repositories use `doc.toJSON() as unknown as Type` casting (required because Mongoose's TypeScript types don't reflect virtual fields in toJSON output).
|
|
|
|
### Logging
|
|
|
|
Structured logging with pino (server) and react-native-logs (client).
|
|
|
|
**Server Logging:**
|
|
- `pino` with `pino-pretty` for development, JSON in production
|
|
- `pino-http` middleware logs all HTTP requests (method, path, status, duration)
|
|
- `@Logged()` class decorator for automatic method logging on repositories and services
|
|
- Sensitive data (password, token, etc.) automatically redacted via pino's `redact` config
|
|
|
|
**@Logged Decorator Pattern:**
|
|
```typescript
|
|
@Logged("MongoEventRepository")
|
|
export class MongoEventRepository implements EventRepository { ... }
|
|
|
|
@Logged("GPTAdapter")
|
|
export class GPTAdapter implements AIProvider { ... }
|
|
```
|
|
|
|
The decorator uses a Proxy to intercept method calls lazily, preserves sync/async nature, and logs start/completion/failure with duration.
|
|
|
|
**Log Summarization:**
|
|
The `@Logged` decorator automatically summarizes large arguments to keep logs readable:
|
|
- `conversationHistory` → `"[5 messages]"`
|
|
- `existingEvents` → `"[3 events]"`
|
|
- `proposedChanges` → logged in full (for debugging AI issues)
|
|
- Long strings (>100 chars) → truncated
|
|
- Arrays → `"[Array(n)]"`
|
|
|
|
**Client Logging:**
|
|
- `react-native-logs` with namespaced loggers (apiLogger, storeLogger)
|
|
- ApiClient logs all requests with method, endpoint, status, duration
|
|
- Log level: debug in __DEV__, warn in production
|
|
|
|
## MVP Feature Scope
|
|
|
|
### Must-Have
|
|
- Chat interface with AI assistant (text input) for event management
|
|
- Calendar overview
|
|
- Manual event CRUD (without AI)
|
|
- View completed events
|
|
- Simple reminders
|
|
- One note per event
|
|
- Recurring events
|
|
|
|
### Nice-to-Have
|
|
- iCalendar import/export
|
|
- Multiple calendars
|
|
- CalDAV synchronization with external services
|
|
|
|
## Development Environment
|
|
|
|
### MongoDB (Docker)
|
|
```bash
|
|
cd apps/server/docker/mongo
|
|
docker compose up -d # Start MongoDB + Mongo Express
|
|
docker compose down # Stop services
|
|
```
|
|
- MongoDB: `localhost:27017` (root/mongoose)
|
|
- Mongo Express UI: `localhost:8083` (admin/admin)
|
|
|
|
### Environment Variables
|
|
Server requires `.env` file in `apps/server/`:
|
|
```
|
|
JWT_SECRET=your-secret-key
|
|
JWT_EXPIRES_IN=1h
|
|
MONGODB_URI=mongodb://root:mongoose@localhost:27017/calchat?authSource=admin
|
|
OPENAI_API_KEY=sk-proj-...
|
|
USE_TEST_RESPONSES=false # true = static test responses, false = real GPT AI
|
|
LOG_LEVEL=debug # debug | info | warn | error | fatal
|
|
NODE_ENV=development # development = pretty logs, production = JSON
|
|
```
|
|
|
|
## Current Implementation Status
|
|
|
|
**Backend:**
|
|
- **Implemented:**
|
|
- `AuthController`: login(), register() with error handling
|
|
- `AuthService`: login() supports email OR userName, register() checks for existing email AND userName
|
|
- `AuthMiddleware`: Validates X-User-Id header for protected routes
|
|
- `MongoUserRepository`: findById(), findByEmail(), findByUserName(), create()
|
|
- `utils/password`: hash(), compare() using bcrypt
|
|
- `scripts/hash-password.js`: Utility for manual password resets
|
|
- `dotenv` integration for environment variables
|
|
- `ChatController`: sendMessage(), confirmEvent(), rejectEvent()
|
|
- `ChatService`: processMessage() with test responses (create, update, delete actions), confirmEvent() handles all CRUD actions
|
|
- `MongoEventRepository`: Full CRUD implemented (findById, findByUserId, findByDateRange, create, update, delete)
|
|
- `EventController`: Full CRUD (create, getById, getAll, getByDateRange, update, delete)
|
|
- `EventService`: Full CRUD with recurring event expansion via recurrenceExpander
|
|
- `utils/eventFormatters`: getWeeksOverview(), getMonthOverview() with German localization
|
|
- `utils/recurrenceExpander`: expandRecurringEvents() using rrule library for RRULE parsing
|
|
- `ChatController`: getConversations(), getConversation() with cursor-based pagination support
|
|
- `ChatService`: getConversations(), getConversation(), processMessage() uses real AI or test responses (via USE_TEST_RESPONSES), confirmEvent()/rejectEvent() update respondedAction and persist response messages
|
|
- `MongoChatRepository`: Full CRUD implemented (getConversationsByUser, createConversation, getMessages with cursor pagination, createMessage, updateMessage, updateProposalResponse)
|
|
- `ChatRepository` interface: updateMessage() and updateProposalResponse() for per-proposal respondedAction tracking
|
|
- `GPTAdapter`: Full implementation with OpenAI GPT (gpt-4o-mini model), function calling for calendar operations, collects multiple proposals per response
|
|
- `ai/utils/`: Provider-agnostic shared utilities (systemPrompt, toolDefinitions, toolExecutor, eventFormatter)
|
|
- `ai/utils/systemPrompt`: Includes RRULE documentation - AI knows to create separate events when times differ by day
|
|
- `utils/recurrenceExpander`: Handles RRULE parsing, strips `RRULE:` prefix if present (AI may include it)
|
|
- `logging/`: Structured logging with pino, pino-http middleware, @Logged decorator
|
|
- All repositories and GPTAdapter decorated with @Logged for automatic method logging
|
|
- CORS configured to allow X-User-Id header
|
|
- **Stubbed (TODO):**
|
|
- `AuthController`: refresh(), logout()
|
|
- `AuthService`: refreshToken()
|
|
- JWT authentication (currently using simple X-User-Id header)
|
|
|
|
**Shared:** Types, DTOs, constants (Day, Month with German translations), ExpandedEvent type, and date utilities defined and exported.
|
|
|
|
**Frontend:**
|
|
- **Authentication fully implemented:**
|
|
- `AuthStore`: Manages user state with expo-secure-store (native) / localStorage (web)
|
|
- `AuthService`: login(), register(), logout() - calls backend API
|
|
- `ApiClient`: Automatically injects X-User-Id header for authenticated requests
|
|
- Login screen: Supports email OR userName login
|
|
- Register screen: Email validation, checks for existing email/userName
|
|
- `AuthButton`: Reusable button component with shadow effect
|
|
- `Header`: Contains logout button on all screens
|
|
- `index.tsx`: Auth redirect - checks stored user on app start
|
|
- Tab navigation (Chat, Calendar) implemented with basic UI
|
|
- Calendar screen fully functional:
|
|
- Month navigation with grid display and Ionicons (chevron-back/forward)
|
|
- MonthSelector dropdown with infinite scroll (dynamically loads months, lazy-loaded when modal opens, cleared on close for memory efficiency)
|
|
- Events loaded from API via EventService.getByDateRange()
|
|
- Orange dot indicator for days with events
|
|
- Tap-to-open modal overlay showing EventCards for selected day
|
|
- Supports events from adjacent months visible in grid
|
|
- Uses `useFocusEffect` for automatic reload on tab focus
|
|
- Chat screen fully functional with FlashList, message sending, and event confirm/reject
|
|
- **Multiple event proposals**: AI can propose multiple events in one response
|
|
- Arrow navigation between proposals with "Event X von Y" counter
|
|
- Each proposal individually confirmable/rejectable
|
|
- Messages persisted to database via ChatService and loaded on mount
|
|
- Tracks conversationId for message continuity across sessions
|
|
- ChatStore with addMessages() for bulk loading, chatMessageToMessageData() helper
|
|
- KeyboardAvoidingView for proper keyboard handling (iOS padding, Android height)
|
|
- Auto-scroll to end on new messages and keyboard show
|
|
- keyboardDismissMode="interactive" and keyboardShouldPersistTaps="handled"
|
|
- `EventService`: getAll(), getById(), getByDateRange(), create(), update(), delete() - fully implemented
|
|
- `ChatService`: sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation() - fully implemented with cursor pagination
|
|
- `EventCardBase`: Shared base component with event layout (header, date/time/recurring icons, description) - used by both EventCard and ProposedEventCard
|
|
- `EventCard`: Uses EventCardBase + edit/delete buttons for calendar display
|
|
- `ProposedEventCard`: Uses EventCardBase + confirm/reject buttons for chat proposals (supports create/update/delete actions)
|
|
- `Themes.tsx`: Centralized color definitions including textPrimary, borderPrimary, eventIndicator, secondaryBg
|
|
- `EventsStore`: Zustand store with setEvents(), addEvent(), updateEvent(), deleteEvent() - stores ExpandedEvent[]
|
|
- `ChatStore`: Zustand store with addMessage(), addMessages(), updateMessage(), clearMessages() - loads from server on mount and persists across tab switches
|
|
- Event Detail and Note screens exist as skeletons
|
|
|
|
## Building
|
|
|
|
### Local APK Build with EAS
|
|
```bash
|
|
npm run build:apk -w @calchat/client
|
|
```
|
|
|
|
This uses the `preview` profile from `eas.json` which builds an APK with:
|
|
- `arm64-v8a` architecture only (smaller APK size)
|
|
- No credentials required (`withoutCredentials: true`)
|
|
- Internal distribution
|
|
|
|
**Requirements:** Android SDK and Java must be installed locally.
|
|
|
|
**EAS Configuration:** `apps/client/eas.json` contains build profiles:
|
|
- `development`: Development client with internal distribution
|
|
- `preview`: APK build for testing (used by `build:apk`)
|
|
- `production`: Production build with auto-increment versioning
|
|
|
|
**App Identity:**
|
|
- Package name: `com.gilmour109.calchat`
|
|
- EAS Project ID: `b722dde6-7d89-48ff-9095-e007e7c7da87`
|
|
|
|
## Documentation
|
|
|
|
Detailed architecture diagrams are in `docs/`:
|
|
- `api-routes.md` - API endpoint overview (German)
|
|
- `technisches_brainstorm.tex` - Technical concept document (German)
|
|
- `architecture-class-diagram.puml` - Backend class diagram
|
|
- `frontend-class-diagram.puml` - Frontend class diagram
|
|
- `component-diagram.puml` - System component overview
|