mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 16:41:08 +02:00
Final cleanup of references missed in previous rename commits: - Dockerfiles: PUBLIC_MANA_CORE_AUTH_URL → PUBLIC_MANA_AUTH_URL - Go modules: github.com/manacore/* → github.com/mana/* (7 go.mod files) - launchd plists: com.manacore.* → com.mana.* (14 files renamed + content) - Image assets: *_Manacore_AI_Credits* → *_Mana_AI_Credits* (11 files) - .env.example files: ManaCore brand strings → Mana - .prettierignore: stale apps/manacore/* paths → apps/mana/* - Markdown docs (CLAUDE.md, /docs/*): mana-core-auth → mana-auth, etc. Excluded from rename: .claude/, devlog/, manascore/ (historical content), client testimonials, blueprints, npm package refs (@mana-core/*). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9.8 KiB
9.8 KiB
Contacts Project Guide
Project Structure
apps/contacts/
├── apps/
│ ├── server/ # Hono/Bun compute server (@contacts/server) - Port 3015
│ ├── landing/ # Astro marketing landing page (@contacts/landing)
│ ├── web/ # SvelteKit web application (@contacts/web) - Port 5184
│ └── mobile/ # Expo/React Native mobile app (@contacts/mobile)
├── packages/
│ └── shared/ # Shared types, utils, configs (@contacts/shared)
└── package.json
Commands
Root Level (from monorepo root)
pnpm contacts:dev # Run all contacts apps
pnpm dev:contacts:mobile # Start mobile app
pnpm dev:contacts:web # Start web app
pnpm dev:contacts:landing # Start landing page
pnpm dev:contacts:server # Start server
pnpm dev:contacts:app # Start web + server together
pnpm dev:contacts:local # Start web + sync (no auth needed)
Mobile App (apps/contacts/apps/mobile)
pnpm dev # Start Expo dev server
pnpm ios # Run on iOS simulator
pnpm android # Run on Android emulator
Backend (apps/contacts/apps/backend)
pnpm dev # Start with hot reload
pnpm build # Build for production
pnpm start:prod # Start production server
pnpm db:push # Push schema to database
pnpm db:studio # Open Drizzle Studio
Web App (apps/contacts/apps/web)
pnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
Landing Page (apps/contacts/apps/landing)
pnpm dev # Start dev server
pnpm build # Build for production
Technology Stack
- Mobile: React Native 0.81 + Expo SDK 54, NativeWind, Expo Router, Zustand
- Web: SvelteKit 2.x, Svelte 5 (runes mode), Tailwind CSS
- Landing: Astro 5.x, Tailwind CSS
- Backend: NestJS 10, Drizzle ORM, PostgreSQL
- Types: TypeScript 5.x
Architecture
Backend API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/health |
GET | Health check |
/api/v1/contacts |
GET | Get user's contacts |
/api/v1/contacts |
POST | Create new contact |
/api/v1/contacts/:id |
GET | Get contact details |
/api/v1/contacts/:id |
PATCH | Update contact |
/api/v1/contacts/:id |
DELETE | Delete contact |
/api/v1/contacts/:id/favorite |
POST | Toggle favorite |
/api/v1/contacts/:id/archive |
POST | Toggle archive |
/api/v1/contacts/:id/photo |
POST | Upload contact photo |
/api/v1/tags |
GET | Get user's tags |
/api/v1/tags |
POST | Create new tag |
/api/v1/tags/:id |
DELETE | Delete tag |
/api/v1/contacts/:id/notes |
GET | Get contact notes |
/api/v1/contacts/:id/notes |
POST | Add note to contact |
/api/v1/notes/:id |
PATCH | Update note |
/api/v1/notes/:id |
DELETE | Delete note |
/api/v1/contacts/:id/activities |
GET | Get contact activities |
/api/v1/contacts/:id/activities |
POST | Log activity |
/api/v1/import/preview |
POST | Preview file import (vCard/CSV) |
/api/v1/import/execute |
POST | Execute contact import |
/api/v1/import/template/csv |
GET | Download CSV template |
/api/v1/google/auth-url |
GET | Get Google OAuth URL |
/api/v1/google/callback |
POST | Exchange OAuth code |
/api/v1/google/status |
GET | Get Google connection status |
/api/v1/google/disconnect |
DELETE | Disconnect Google account |
/api/v1/google/contacts |
GET | Fetch Google contacts |
/api/v1/google/import |
POST | Import from Google |
/api/v1/export |
GET | Quick export all contacts |
/api/v1/export |
POST | Export with options |
/api/v1/organizations/:orgId/contacts |
GET | Get organization contacts |
/api/v1/teams/:teamId/contacts |
GET | Get team contacts |
/api/v1/contacts/:id/share |
POST | Share contact |
Database Schema
contacts - Contact information
id(UUID) - Primary keyuser_id(VARCHAR) - User referencefirst_name,last_name,display_name,nickname(VARCHAR)email,phone,mobile(VARCHAR)street,city,postal_code,country(VARCHAR)company,job_title,department(VARCHAR)website,birthday,notes,photo_url(VARCHAR/TEXT/DATE)is_favorite,is_archived(BOOLEAN)organization_id,team_id(UUID) - Mana integrationvisibility(VARCHAR) - private/team/organization/publicshared_with(JSONB) - Array of user IDscreated_at,updated_at(TIMESTAMP)
contact_tags - Tags for contacts
id(UUID) - Primary keyuser_id(VARCHAR) - User referencename(VARCHAR) - Tag namecolor(VARCHAR) - Tag color
contact_to_tags - Many-to-many relation
contact_id(UUID) - Contact referencetag_id(UUID) - Tag reference
contact_notes - Notes for contacts
id(UUID) - Primary keycontact_id(UUID) - Contact referenceuser_id(VARCHAR) - User referencecontent(TEXT) - Note contentis_pinned(BOOLEAN)created_at,updated_at(TIMESTAMP)
contact_activities - Activity log
id(UUID) - Primary keycontact_id(UUID) - Contact referenceuser_id(VARCHAR) - User referenceactivity_type(VARCHAR) - created/updated/called/emailed/met/note_addeddescription(TEXT)metadata(JSONB)created_at(TIMESTAMP)
connected_accounts - OAuth provider connections (Google, etc.)
id(UUID) - Primary keyuser_id(VARCHAR) - User referenceprovider(VARCHAR) - Provider name (e.g., 'google')provider_account_id(VARCHAR) - Provider's user IDprovider_email(VARCHAR) - Provider account emailaccess_token(TEXT) - OAuth access token (encrypted)refresh_token(TEXT) - OAuth refresh token (encrypted)token_expires_at(TIMESTAMP) - Token expiration timescope(TEXT) - Granted OAuth scopesprovider_data(JSONB) - Additional provider-specific datacreated_at,updated_at(TIMESTAMP)
Environment Variables
Backend (.env)
NODE_ENV=development
PORT=3015
DATABASE_URL=postgresql://mana:devpassword@localhost:5432/contacts
MANA_AUTH_URL=http://localhost:3001
CORS_ORIGINS=http://localhost:5173,http://localhost:5184,http://localhost:8081
S3_ENDPOINT=http://localhost:9000
S3_REGION=us-east-1
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_BUCKET=contacts-photos
# Google OAuth (for contacts import)
# Get credentials from https://console.cloud.google.com/apis/credentials
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=http://localhost:5184/data?tab=import&source=google
Mobile (.env)
EXPO_PUBLIC_BACKEND_URL=http://localhost:3015
EXPO_PUBLIC_MANA_AUTH_URL=http://localhost:3001
Web (.env)
PUBLIC_BACKEND_URL=http://localhost:3015
PUBLIC_MANA_AUTH_URL=http://localhost:3001
Shared Packages
@contacts/shared
- Types:
Contact,ContactGroup,ContactTag,ContactNote,ContactActivity - Utils: Search, filter, import/export functions
- Configs: App configuration
Quick Input Syntax
The NewContactModal includes a NL quick-input bar that parses contact info and pre-fills form fields:
"Max Mustermann @ACME Corp max@example.com +49 170 1234567 #kunde"
→ firstName: Max, lastName: Mustermann, company: ACME Corp,
email: max@example.com, phone: +49 170..., tags: [kunde]
Recognized patterns:
- Name: First and last name (remaining text after extraction)
- Company:
@CompanyNameorbei CompanyNameorvon CompanyName - Email: Standard email format
- Phone: International (+49...), German (0123...), or 6+ digit numbers
- Tags:
#tag1 #tag2
Type the full text and press Enter to apply. Fields are pre-filled and can be edited before saving.
Live Duplicate Detection
While typing in the name or email fields, the system checks for duplicates against IndexedDB in real-time:
- Email: Exact match (case-insensitive)
- Name: Fuzzy match (Levenshtein distance, tolerates typos)
- Shows warning with matched contact name, company, and match type
Implementation: duplicate-detector.ts — runs fully offline, no server calls.
Code Style Guidelines
- TypeScript: Strict typing with interfaces
- Mobile: Functional components with hooks, Zustand for state
- Web: Svelte 5 runes mode (
$state,$derived,$effect) - Styling: Tailwind CSS / NativeWind
- Formatting: Prettier with project config
Important Notes
- Authentication: Uses Mana Auth (JWT in Authorization header)
- Database: PostgreSQL with Drizzle ORM
- Port: Backend runs on port 3015, Web on port 5184 by default
- Storage: Uses MinIO/S3 for contact photos via @mana/shared-storage
- Mana Integration: Contacts can be linked to Organizations and Teams