# Context App AI-powered document management and context system for knowledge organization. | App | Port | URL | |-----|------|-----| | Backend | 3020 | http://localhost:3020 | | Web App | 5192 | http://localhost:5192 | | Mobile | 8081 | Expo Go | ## Structure ``` apps/context/ ├── apps/ │ ├── backend/ # NestJS API server (@context/backend) │ │ └── src/ │ │ ├── main.ts │ │ ├── app.module.ts │ │ ├── db/ # Drizzle schemas + migrations │ │ │ ├── schema/ │ │ │ │ ├── spaces.schema.ts │ │ │ │ ├── documents.schema.ts │ │ │ │ ├── token-transactions.schema.ts │ │ │ │ ├── model-prices.schema.ts │ │ │ │ └── user-tokens.schema.ts │ │ │ ├── connection.ts │ │ │ ├── database.module.ts │ │ │ ├── migrate.ts │ │ │ └── seed.ts │ │ ├── space/ # Space CRUD │ │ ├── document/ # Document CRUD + versions + tags │ │ ├── ai/ # AI generation (Azure + Google) │ │ ├── token/ # Token balance + stats │ │ └── common/ │ ├── web/ # SvelteKit web application (@context/web) │ ├── mobile/ # Expo React Native app (@context/mobile) │ └── landing/ # (Planned) Astro Landing Page ├── packages/ # Project-specific shared code └── package.json # Workspace root ``` ## Development Commands ```bash # From monorepo root pnpm dev:context:full # Start auth + backend + web (with DB setup) pnpm dev:context:backend # Start backend only (port 3020) pnpm dev:context:web # Start web only (port 5192) pnpm dev:context:app # Start web + backend together pnpm dev:context:mobile # Start mobile app # Database pnpm context:db:push # Push schema to database pnpm context:db:studio # Open Drizzle Studio pnpm context:db:seed # Seed model prices pnpm setup:db:context # Create DB + push schema ``` ## Tech Stack | Layer | Technology | |-------|------------| | **Backend** | NestJS 10, Drizzle ORM, PostgreSQL | | **Web** | SvelteKit 2.x, Svelte 5 (runes mode), Tailwind CSS 4 | | **Mobile** | React Native 0.76 + Expo SDK 52, NativeWind | | **Auth** | Mana Core Auth (JWT) | | **AI** | Azure OpenAI (GPT-4.1), Google Gemini (Pro, Flash) | | **i18n** | svelte-i18n (DE, EN) | ## Core Features - **Spaces**: Organize documents into collections with prefix-based short IDs - **Documents**: Text, context references, and AI prompts with versioning - **AI Generation**: Multi-model support (Azure OpenAI, Google Gemini) - **Token Economy**: Track and manage AI usage credits per user - **Document Versioning**: AI-generated summaries, continuations, rewrites ## Backend API Endpoints ### Health | Endpoint | Method | Description | |----------|--------|-------------| | `/health` | GET | Health check | ### Spaces | Endpoint | Method | Description | |----------|--------|-------------| | `/api/v1/spaces` | GET | List user's spaces | | `/api/v1/spaces` | POST | Create space | | `/api/v1/spaces/:id` | GET | Get space details | | `/api/v1/spaces/:id` | PUT | Update space | | `/api/v1/spaces/:id` | DELETE | Delete space (cascades documents) | ### Documents | Endpoint | Method | Description | |----------|--------|-------------| | `/api/v1/documents` | GET | List documents (?spaceId=&preview=true&limit=) | | `/api/v1/documents/recent` | GET | Recent documents (?limit=) | | `/api/v1/documents` | POST | Create document | | `/api/v1/documents/:id` | GET | Get document | | `/api/v1/documents/:id` | PUT | Update document | | `/api/v1/documents/:id` | DELETE | Delete document | | `/api/v1/documents/:id/tags` | PUT | Update document tags | | `/api/v1/documents/:id/pinned` | PUT | Toggle pinned | | `/api/v1/documents/:id/versions` | GET | Get document versions | | `/api/v1/documents/:id/versions` | POST | Create AI version | ### AI | Endpoint | Method | Description | |----------|--------|-------------| | `/api/v1/ai/generate` | POST | Generate text (server-side AI) | | `/api/v1/ai/estimate` | POST | Estimate token cost | ### Tokens | Endpoint | Method | Description | |----------|--------|-------------| | `/api/v1/tokens/balance` | GET | Get user token balance | | `/api/v1/tokens/stats` | GET | Usage stats (?timeframe=day\|week\|month\|year) | | `/api/v1/tokens/transactions` | GET | Transaction history (?limit=&offset=) | | `/api/v1/tokens/models` | GET | Available model prices | ## Database Schema ### spaces | Column | Type | Description | |--------|------|-------------| | `id` | UUID | Primary key | | `user_id` | TEXT | Owner | | `name` | VARCHAR(255) | Space name | | `description` | TEXT | Optional description | | `settings` | JSONB | Space settings | | `pinned` | BOOLEAN | Pinned in sidebar | | `prefix` | VARCHAR(10) | Short ID prefix (e.g. "A") | | `text_doc_counter` | INTEGER | Counter for text docs | | `context_doc_counter` | INTEGER | Counter for context docs | | `prompt_doc_counter` | INTEGER | Counter for prompt docs | ### documents | Column | Type | Description | |--------|------|-------------| | `id` | UUID | Primary key | | `user_id` | TEXT | Owner | | `space_id` | UUID | FK to spaces (cascade delete) | | `title` | VARCHAR(500) | Document title | | `content` | TEXT | Document content | | `type` | VARCHAR(20) | text / context / prompt | | `short_id` | VARCHAR(20) | Short ID (e.g. "AD1") | | `pinned` | BOOLEAN | Pinned flag | | `metadata` | JSONB | Tags, word count, version info | ### token_transactions | Column | Type | Description | |--------|------|-------------| | `id` | UUID | Primary key | | `user_id` | TEXT | User | | `amount` | INTEGER | Tokens used (negative for usage) | | `transaction_type` | VARCHAR(50) | usage / bonus / purchase | | `model_used` | VARCHAR(100) | AI model name | | `prompt_tokens` | INTEGER | Input tokens | | `completion_tokens` | INTEGER | Output tokens | | `cost_usd` | NUMERIC(10,6) | Actual USD cost | ### model_prices | Column | Type | Description | |--------|------|-------------| | `model_name` | VARCHAR(100) | Unique model name | | `input_price_per_1k_tokens` | NUMERIC(10,6) | Input price | | `output_price_per_1k_tokens` | NUMERIC(10,6) | Output price | | `tokens_per_dollar` | INTEGER | App tokens per USD | ### user_tokens | Column | Type | Description | |--------|------|-------------| | `user_id` | TEXT | Primary key | | `token_balance` | INTEGER | Current balance | | `monthly_free_tokens` | INTEGER | Free monthly allocation | ## Environment Variables ### Backend (.env) ```env NODE_ENV=development PORT=3020 DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/context MANA_CORE_AUTH_URL=http://localhost:3001 AZURE_OPENAI_API_KEY=your-key AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/ GOOGLE_API_KEY=your-key ``` ### Web (.env) ```env PUBLIC_BACKEND_URL=http://localhost:3020 PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001 ``` ## Important Patterns 1. **API Client pattern** - All web services use `@manacore/shared-api-client` (Go-style `{ data, error }`) 2. **Svelte 5 runes** - `$state`, `$derived`, `$effect` throughout 3. **Server-side AI keys** - API keys only on backend, never in frontend 4. **Auto word/token count** - Backend calculates on create/update 5. **Optimistic updates** - Immediate UI feedback in stores 6. **Document versioning** - AI generations linked via `parent_document` in metadata