mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:41:09 +02:00
1548 lines
35 KiB
Markdown
1548 lines
35 KiB
Markdown
# Picture Monorepo - Complete Architecture Guide
|
|
|
|
**Erstellt:** 2025-10-09
|
|
**Status:** Production Ready
|
|
**Letzte Aktualisierung:** 2025-10-09
|
|
|
|
---
|
|
|
|
## Inhaltsverzeichnis
|
|
|
|
1. [Executive Summary](#executive-summary)
|
|
2. [Architektur Übersicht](#architektur-übersicht)
|
|
3. [Framework Compatibility Matrix](#framework-compatibility-matrix)
|
|
4. [App Details](#app-details)
|
|
5. [Shared Packages](#shared-packages)
|
|
6. [PNPM Workspace Setup](#pnpm-workspace-setup)
|
|
7. [UI Component Strategy](#ui-component-strategy)
|
|
8. [Migration Steps](#migration-steps)
|
|
9. [Development Workflow](#development-workflow)
|
|
10. [Deployment Strategy](#deployment-strategy)
|
|
11. [Environment Variables](#environment-variables)
|
|
12. [Code Sharing Matrix](#code-sharing-matrix)
|
|
13. [Recommendations & Future Options](#recommendations--future-options)
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
Das Picture Projekt ist ein **PNPM Workspace Monorepo** mit drei unabhängigen Applikationen:
|
|
|
|
1. **Mobile App** (React Native + Expo) - iOS & Android
|
|
2. **Web App** (SvelteKit) - Vollständige Webanwendung
|
|
3. **Landing Page** (Astro) - Marketing Website
|
|
|
|
Alle Apps teilen gemeinsame TypeScript Packages für maximalen Code Reuse bei minimaler Komplexität.
|
|
|
|
### Wichtigste Erkenntnisse
|
|
|
|
✅ **Code Reuse:** ~35-40% des Codes wird geteilt
|
|
✅ **Framework-Unabhängigkeit:** Jede App nutzt den optimalen Tech Stack
|
|
✅ **Deployment-Flexibilität:** Unabhängiges Deployment pro App
|
|
⚠️ **UI Components:** Können NICHT zwischen Frameworks geteilt werden
|
|
|
|
---
|
|
|
|
## Architektur Übersicht
|
|
|
|
```
|
|
picture/
|
|
├── apps/
|
|
│ ├── mobile/ # React Native (Expo)
|
|
│ │ ├── app/ # Expo Router
|
|
│ │ ├── components/
|
|
│ │ ├── hooks/
|
|
│ │ ├── package.json
|
|
│ │ └── 🎯 Uses @memoro/mobile-ui
|
|
│ │
|
|
│ ├── web/ # SvelteKit
|
|
│ │ ├── src/
|
|
│ │ │ ├── lib/
|
|
│ │ │ │ ├── components/ # Svelte-specific UI
|
|
│ │ │ │ └── stores/
|
|
│ │ │ ├── routes/
|
|
│ │ │ │ ├── +layout.svelte
|
|
│ │ │ │ ├── +page.svelte
|
|
│ │ │ │ ├── auth/
|
|
│ │ │ │ ├── images/
|
|
│ │ │ │ └── profile/
|
|
│ │ │ └── app.html
|
|
│ │ ├── static/
|
|
│ │ ├── svelte.config.js
|
|
│ │ └── package.json
|
|
│ │
|
|
│ └── landing/ # Astro
|
|
│ ├── src/
|
|
│ │ ├── components/
|
|
│ │ │ ├── Hero.astro
|
|
│ │ │ ├── Features.astro
|
|
│ │ │ ├── Pricing.astro
|
|
│ │ │ └── Footer.astro
|
|
│ │ ├── layouts/
|
|
│ │ │ └── Layout.astro
|
|
│ │ ├── pages/
|
|
│ │ │ ├── index.astro # Homepage
|
|
│ │ │ ├── features.astro
|
|
│ │ │ ├── pricing.astro
|
|
│ │ │ └── about.astro
|
|
│ │ └── styles/
|
|
│ ├── public/
|
|
│ ├── astro.config.mjs
|
|
│ └── package.json
|
|
│
|
|
├── packages/
|
|
│ ├── mobile-ui/ # @memoro/mobile-ui
|
|
│ │ ├── components/
|
|
│ │ │ ├── ui/ # 17 React Native components
|
|
│ │ │ └── navigation/
|
|
│ │ ├── cli/ # CLI tool for installation
|
|
│ │ └── 🎯 React Native ONLY
|
|
│ │
|
|
│ ├── shared/ # @picture/shared
|
|
│ │ ├── src/
|
|
│ │ │ ├── types/
|
|
│ │ │ │ ├── database.ts # Supabase Types
|
|
│ │ │ │ ├── models.ts # App Models
|
|
│ │ │ │ └── index.ts
|
|
│ │ │ ├── api/
|
|
│ │ │ │ ├── supabase.ts # Supabase Config
|
|
│ │ │ │ ├── images.ts # Image API
|
|
│ │ │ │ ├── auth.ts # Auth API
|
|
│ │ │ │ └── index.ts
|
|
│ │ │ ├── utils/
|
|
│ │ │ │ ├── image.ts # Image Utils
|
|
│ │ │ │ ├── validation.ts # Validation
|
|
│ │ │ │ └── index.ts
|
|
│ │ │ └── index.ts
|
|
│ │ ├── package.json
|
|
│ │ └── tsconfig.json
|
|
│ │
|
|
│ ├── design-tokens/ # @memoro/design-tokens (Future)
|
|
│ │ ├── src/
|
|
│ │ │ ├── colors.ts
|
|
│ │ │ ├── spacing.ts
|
|
│ │ │ ├── typography.ts
|
|
│ │ │ └── index.ts
|
|
│ │ └── package.json
|
|
│ │
|
|
│ └── ui/ # (empty/deprecated)
|
|
│
|
|
├── package.json # Root Package.json
|
|
├── pnpm-workspace.yaml # PNPM Workspace Config
|
|
├── .npmrc # NPM Config
|
|
├── tsconfig.base.json # Base TypeScript Config
|
|
└── .env.example # Environment Variables Template
|
|
```
|
|
|
|
---
|
|
|
|
## Framework Compatibility Matrix
|
|
|
|
### Package Kompatibilität
|
|
|
|
| Package | Mobile (RN) | Web (Svelte) | Landing (Astro) | Beschreibung |
|
|
|---------|-------------|--------------|-----------------|--------------|
|
|
| `@memoro/mobile-ui` | ✅ Full support | ❌ Incompatible | ❌ Incompatible | React Native UI Components |
|
|
| `@picture/shared` | ✅ Yes | ✅ Yes | ✅ Yes | Backend Logic, Types, APIs |
|
|
| `@memoro/design-tokens` | ✅ Yes* | ✅ Yes* | ✅ Yes* | Colors, Spacing, Typography |
|
|
|
|
*Future implementation
|
|
|
|
### Warum UI Components nicht geteilt werden können
|
|
|
|
**@memoro/mobile-ui nutzt React Native Primitives:**
|
|
```tsx
|
|
import { View, Pressable, Text } from 'react-native';
|
|
import Animated from 'react-native-reanimated';
|
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
```
|
|
|
|
**Web Apps nutzen andere Primitives:**
|
|
```svelte
|
|
<!-- SvelteKit -->
|
|
<div class="...">
|
|
<button on:click={...}>
|
|
</div>
|
|
```
|
|
|
|
```astro
|
|
<!-- Astro -->
|
|
<div class="...">
|
|
<button onclick="...">
|
|
</div>
|
|
```
|
|
|
|
**Technische Einschränkungen:**
|
|
- `View` ≠ `<div>`
|
|
- `Pressable` ≠ `<button>`
|
|
- `react-native-reanimated` funktioniert nicht im Web Browser
|
|
- Svelte Components funktionieren nicht in React Native
|
|
- Astro Components funktionieren nicht in React Native
|
|
|
|
---
|
|
|
|
## App Details
|
|
|
|
### 1. Mobile App (React Native + Expo)
|
|
|
|
**Zweck:** Native iOS & Android App
|
|
|
|
**Tech Stack:**
|
|
- React Native 0.81
|
|
- Expo SDK 54
|
|
- Expo Router (File-based)
|
|
- NativeWind (Tailwind)
|
|
- Zustand (State)
|
|
- Supabase Client
|
|
- @memoro/mobile-ui (17 UI Components)
|
|
|
|
**Features:**
|
|
- ✅ Auth (Login/Signup)
|
|
- ✅ Image Upload
|
|
- ✅ Image Gallery
|
|
- ✅ Image Detail View mit Zoom
|
|
- ✅ Profile Management
|
|
- ✅ Offline Support (geplant)
|
|
|
|
**UI Components:**
|
|
```bash
|
|
# Install components via CLI
|
|
node packages/mobile-ui/cli/bin/cli.js add button
|
|
node packages/mobile-ui/cli/bin/cli.js add card
|
|
node packages/mobile-ui/cli/bin/cli.js add select
|
|
```
|
|
|
|
**Verfügbare Components:**
|
|
- Button, Card, Text, Icon
|
|
- Container, EmptyState, ErrorBanner
|
|
- Badge, Tag, Slider, Skeleton
|
|
- FAB, Select, ToggleGroup
|
|
- Header, HeaderButton, TabBarIcon
|
|
|
|
**Deployment:**
|
|
- EAS Build (Expo Application Services)
|
|
- App Store & Google Play
|
|
|
|
---
|
|
|
|
### 2. Web App (SvelteKit)
|
|
|
|
**Zweck:** Vollständige Web-Anwendung (Desktop + Mobile Web)
|
|
|
|
**Tech Stack:**
|
|
- SvelteKit 2.x
|
|
- Svelte 5
|
|
- Tailwind CSS v4
|
|
- Supabase Client
|
|
- Vite
|
|
- TypeScript
|
|
|
|
**Features:**
|
|
- ✅ Auth (Login/Signup)
|
|
- ✅ Image Upload (Drag & Drop)
|
|
- ✅ Image Gallery (Masonry Layout)
|
|
- ✅ Image Detail View
|
|
- ✅ Profile Management
|
|
- ✅ SSR für SEO
|
|
- ✅ Image Optimization
|
|
|
|
**UI Strategy:**
|
|
- **Location:** `apps/web/src/lib/components/ui/`
|
|
- **Components:** `Button.svelte`, `Card.svelte`, `Input.svelte`
|
|
- **Styling:** Tailwind CSS v4
|
|
- **Custom Implementation:** Svelte-spezifisch, nicht geteilt
|
|
|
|
**Routing:**
|
|
```
|
|
/ # Home (Gallery)
|
|
/auth # Login/Signup
|
|
/auth/callback # OAuth Callback
|
|
/images # Images Grid
|
|
/images/[id] # Image Detail
|
|
/profile # User Profile
|
|
/settings # Settings
|
|
```
|
|
|
|
**Deployment:**
|
|
- Cloudflare Pages (empfohlen)
|
|
- Alternativ: Vercel, Netlify
|
|
|
|
---
|
|
|
|
### 3. Landing Page (Astro)
|
|
|
|
**Zweck:** Marketing Website, SEO-optimiert, statisch
|
|
|
|
**Tech Stack:**
|
|
- Astro 5.x
|
|
- Tailwind CSS v3
|
|
- TypeScript
|
|
- Optional: Svelte/React Components
|
|
|
|
**Features:**
|
|
- ✅ Hero Section
|
|
- ✅ Features Overview
|
|
- ✅ Pricing Page
|
|
- ✅ About Page
|
|
- ✅ Blog (optional)
|
|
- ✅ SEO Optimiert
|
|
- ✅ Ultraschnell (Static)
|
|
|
|
**UI Strategy:**
|
|
- **Location:** `apps/landing/src/components/`
|
|
- **Components:** `Hero.astro`, `CTA.astro`, `Features.astro`
|
|
- **Styling:** Tailwind CSS v3
|
|
- **Custom Implementation:** Astro-spezifisch, nicht geteilt
|
|
|
|
**Seiten:**
|
|
```
|
|
/ # Homepage
|
|
/features # Features Detail
|
|
/pricing # Pricing Plans
|
|
/about # About Us
|
|
/blog/ # Blog (optional)
|
|
/docs/ # Documentation (optional)
|
|
```
|
|
|
|
**Warum Astro?**
|
|
- ⚡ Ultraschnell (0 JS by default)
|
|
- 🎯 Perfect für Marketing
|
|
- 🔍 SEO-optimiert out of the box
|
|
- 🎨 Kann Svelte/React Components nutzen
|
|
- 📦 Tiny Bundle Sizes
|
|
|
|
**Deployment:**
|
|
- Cloudflare Pages (empfohlen)
|
|
- Netlify
|
|
- Vercel
|
|
|
|
---
|
|
|
|
## Shared Packages
|
|
|
|
### Package: `@picture/shared`
|
|
|
|
**Zweck:** Core Business Logic, Types, API
|
|
|
|
**Was wird geteilt:**
|
|
|
|
```typescript
|
|
// Types
|
|
export type { Database, Image, User, Album } from './types';
|
|
|
|
// API Clients
|
|
export { createSupabaseClient } from './api/supabase';
|
|
export { ImageAPI } from './api/images';
|
|
export { AuthAPI } from './api/auth';
|
|
|
|
// Utils
|
|
export {
|
|
calculateAspectRatio,
|
|
validateImageSize,
|
|
formatFileSize,
|
|
generateBlurhash
|
|
} from './utils/image';
|
|
|
|
export {
|
|
validateEmail,
|
|
validatePassword,
|
|
sanitizeInput
|
|
} from './utils/validation';
|
|
|
|
export {
|
|
formatDate,
|
|
formatRelativeTime
|
|
} from './utils/date';
|
|
```
|
|
|
|
**Struktur:**
|
|
```
|
|
packages/shared/
|
|
├── src/
|
|
│ ├── types/
|
|
│ │ ├── database.ts # Supabase Generated
|
|
│ │ ├── models.ts # App Models
|
|
│ │ └── index.ts
|
|
│ ├── api/
|
|
│ │ ├── base.ts # Base API Client
|
|
│ │ ├── supabase.ts # Supabase Setup
|
|
│ │ ├── images.ts # Image Operations
|
|
│ │ ├── auth.ts # Auth Operations
|
|
│ │ └── index.ts
|
|
│ ├── utils/
|
|
│ │ ├── image.ts # Image Utils
|
|
│ │ ├── validation.ts # Input Validation
|
|
│ │ ├── date.ts # Date Formatting
|
|
│ │ └── index.ts
|
|
│ ├── constants/
|
|
│ │ ├── config.ts # App Config
|
|
│ │ └── index.ts
|
|
│ └── index.ts
|
|
├── package.json
|
|
└── tsconfig.json
|
|
```
|
|
|
|
**Package.json:**
|
|
```json
|
|
{
|
|
"name": "@picture/shared",
|
|
"version": "1.0.0",
|
|
"type": "module",
|
|
"main": "./src/index.ts",
|
|
"types": "./src/index.ts",
|
|
"exports": {
|
|
".": "./src/index.ts",
|
|
"./types": "./src/types/index.ts",
|
|
"./api": "./src/api/index.ts",
|
|
"./utils": "./src/utils/index.ts"
|
|
},
|
|
"scripts": {
|
|
"type-check": "tsc --noEmit",
|
|
"lint": "eslint src"
|
|
},
|
|
"dependencies": {
|
|
"@supabase/supabase-js": "^2.38.4"
|
|
},
|
|
"devDependencies": {
|
|
"typescript": "^5.8.3"
|
|
}
|
|
}
|
|
```
|
|
|
|
**API Client Beispiel:**
|
|
```typescript
|
|
// packages/shared/src/api/supabase.ts
|
|
import { createClient } from '@supabase/supabase-js';
|
|
import type { Database } from '../types/database';
|
|
|
|
export function createSupabaseClient(url: string, key: string) {
|
|
return createClient<Database>(url, key, {
|
|
auth: {
|
|
persistSession: true,
|
|
autoRefreshToken: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
// packages/shared/src/api/images.ts
|
|
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
import type { Database } from '../types/database';
|
|
|
|
export class ImageAPI {
|
|
constructor(private client: SupabaseClient<Database>) {}
|
|
|
|
async getImages(userId: string) {
|
|
const { data, error } = await this.client
|
|
.from('images')
|
|
.select('*')
|
|
.eq('user_id', userId)
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (error) throw error;
|
|
return data;
|
|
}
|
|
|
|
async getImage(id: string) {
|
|
const { data, error } = await this.client
|
|
.from('images')
|
|
.select('*')
|
|
.eq('id', id)
|
|
.single();
|
|
|
|
if (error) throw error;
|
|
return data;
|
|
}
|
|
|
|
async uploadImage(file: File | Blob, userId: string) {
|
|
// Upload logic
|
|
}
|
|
|
|
async deleteImage(id: string) {
|
|
const { error } = await this.client
|
|
.from('images')
|
|
.delete()
|
|
.eq('id', id);
|
|
|
|
if (error) throw error;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Utils Beispiel:**
|
|
```typescript
|
|
// packages/shared/src/utils/image.ts
|
|
export function calculateAspectRatio(width: number, height: number): number {
|
|
return width / height;
|
|
}
|
|
|
|
export function validateImageSize(size: number, maxSize: number = 10 * 1024 * 1024): boolean {
|
|
return size <= maxSize;
|
|
}
|
|
|
|
export function formatFileSize(bytes: number): string {
|
|
if (bytes === 0) return '0 Bytes';
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
}
|
|
|
|
// packages/shared/src/utils/validation.ts
|
|
export function validateEmail(email: string): boolean {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return emailRegex.test(email);
|
|
}
|
|
|
|
export function validatePassword(password: string): {
|
|
valid: boolean;
|
|
errors: string[];
|
|
} {
|
|
const errors: string[] = [];
|
|
|
|
if (password.length < 8) {
|
|
errors.push('Password must be at least 8 characters');
|
|
}
|
|
if (!/[A-Z]/.test(password)) {
|
|
errors.push('Password must contain uppercase letter');
|
|
}
|
|
if (!/[a-z]/.test(password)) {
|
|
errors.push('Password must contain lowercase letter');
|
|
}
|
|
if (!/[0-9]/.test(password)) {
|
|
errors.push('Password must contain number');
|
|
}
|
|
|
|
return {
|
|
valid: errors.length === 0,
|
|
errors
|
|
};
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Package: `@memoro/mobile-ui`
|
|
|
|
**Zweck:** React Native UI Component Library
|
|
|
|
**Verfügbare Components:** 17 komponenten
|
|
- **UI:** Button, Card, Text, Icon, Container, EmptyState, ErrorBanner, Badge, Tag, Slider, Skeleton, FAB, Select, ToggleGroup
|
|
- **Navigation:** Header, HeaderButton, TabBarIcon
|
|
|
|
**CLI Tool:**
|
|
```bash
|
|
# List available components
|
|
node packages/mobile-ui/cli/bin/cli.js list
|
|
|
|
# Add single component
|
|
node packages/mobile-ui/cli/bin/cli.js add button
|
|
|
|
# Add multiple components
|
|
node packages/mobile-ui/cli/bin/cli.js add button card text
|
|
```
|
|
|
|
**Features:**
|
|
- ✅ TypeScript support
|
|
- ✅ CLI for easy installation
|
|
- ✅ Expo/React Native only
|
|
- ❌ Not compatible with web frameworks
|
|
|
|
---
|
|
|
|
### Package: `@memoro/design-tokens` (Future)
|
|
|
|
**Zweck:** Shared Design System Values
|
|
|
|
**Was kann geteilt werden:**
|
|
```typescript
|
|
// packages/design-tokens/colors.ts
|
|
export const colors = {
|
|
primary: '#3B82F6',
|
|
secondary: '#8B5CF6',
|
|
dark: {
|
|
bg: '#000000',
|
|
surface: '#242424',
|
|
elevated: '#2a2a2a',
|
|
border: '#383838',
|
|
},
|
|
// ...
|
|
};
|
|
|
|
// packages/design-tokens/typography.ts
|
|
export const typography = {
|
|
fonts: {
|
|
body: 'Inter, system-ui, sans-serif',
|
|
heading: 'Inter, system-ui, sans-serif',
|
|
},
|
|
sizes: {
|
|
xs: '0.75rem',
|
|
sm: '0.875rem',
|
|
base: '1rem',
|
|
lg: '1.125rem',
|
|
xl: '1.25rem',
|
|
// ...
|
|
}
|
|
};
|
|
|
|
// packages/design-tokens/spacing.ts
|
|
export const spacing = {
|
|
xs: '0.25rem', // 4px
|
|
sm: '0.5rem', // 8px
|
|
md: '1rem', // 16px
|
|
lg: '1.5rem', // 24px
|
|
xl: '2rem', // 32px
|
|
// ...
|
|
};
|
|
```
|
|
|
|
**Verwendung in allen Apps:**
|
|
```tsx
|
|
// Mobile (React Native)
|
|
import { colors, spacing } from '@memoro/design-tokens';
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
backgroundColor: colors.dark.bg,
|
|
padding: spacing.md,
|
|
}
|
|
});
|
|
```
|
|
|
|
```svelte
|
|
<!-- Web (Svelte) -->
|
|
<script>
|
|
import { colors, spacing } from '@memoro/design-tokens';
|
|
</script>
|
|
|
|
<div style="background: {colors.dark.bg}; padding: {spacing.md}">
|
|
Content
|
|
</div>
|
|
```
|
|
|
|
```astro
|
|
---
|
|
// Landing (Astro)
|
|
import { colors, spacing } from '@memoro/design-tokens';
|
|
---
|
|
|
|
<div style={`background: ${colors.dark.bg}; padding: ${spacing.md}`}>
|
|
Content
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
## PNPM Workspace Setup
|
|
|
|
### 1. Root `package.json`
|
|
|
|
```json
|
|
{
|
|
"name": "picture-monorepo",
|
|
"version": "1.0.0",
|
|
"private": true,
|
|
"scripts": {
|
|
"dev": "pnpm run --parallel dev",
|
|
"dev:mobile": "pnpm --filter @picture/mobile dev",
|
|
"dev:web": "pnpm --filter @picture/web dev",
|
|
"dev:landing": "pnpm --filter @picture/landing dev",
|
|
|
|
"build": "pnpm run --recursive build",
|
|
"build:mobile": "pnpm --filter @picture/mobile build",
|
|
"build:web": "pnpm --filter @picture/web build",
|
|
"build:landing": "pnpm --filter @picture/landing build",
|
|
|
|
"lint": "pnpm run --recursive lint",
|
|
"type-check": "pnpm run --recursive type-check",
|
|
|
|
"clean": "pnpm run --recursive clean && rm -rf node_modules"
|
|
},
|
|
"devDependencies": {
|
|
"@types/node": "^20.0.0",
|
|
"typescript": "^5.8.3",
|
|
"prettier": "^3.2.5",
|
|
"eslint": "^9.25.1"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. `pnpm-workspace.yaml`
|
|
|
|
```yaml
|
|
packages:
|
|
- 'apps/*'
|
|
- 'packages/*'
|
|
```
|
|
|
|
### 3. `.npmrc`
|
|
|
|
```ini
|
|
# Use pnpm for all installs
|
|
auto-install-peers=true
|
|
shamefully-hoist=true
|
|
strict-peer-dependencies=false
|
|
```
|
|
|
|
### 4. `tsconfig.base.json`
|
|
|
|
```json
|
|
{
|
|
"compilerOptions": {
|
|
"target": "ES2022",
|
|
"module": "ESNext",
|
|
"lib": ["ES2022"],
|
|
"moduleResolution": "bundler",
|
|
"strict": true,
|
|
"esModuleInterop": true,
|
|
"skipLibCheck": true,
|
|
"forceConsistentCasingInFileNames": true,
|
|
"resolveJsonModule": true,
|
|
"isolatedModules": true,
|
|
"paths": {
|
|
"@picture/shared": ["./packages/shared/src"],
|
|
"@picture/shared/*": ["./packages/shared/src/*"],
|
|
"@memoro/mobile-ui": ["./packages/mobile-ui/src"],
|
|
"@memoro/design-tokens": ["./packages/design-tokens/src"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## UI Component Strategy
|
|
|
|
### Aktueller Ansatz: Framework-spezifische Implementierungen
|
|
|
|
#### Mobile App
|
|
✅ **Nutzt:** `@memoro/mobile-ui`
|
|
- 17 React Native components
|
|
- CLI tool für Installation
|
|
- Full TypeScript support
|
|
|
|
```bash
|
|
# Install components
|
|
node packages/mobile-ui/cli/bin/cli.js add button
|
|
```
|
|
|
|
#### Web App
|
|
🔨 **Strategie:** Eigene Svelte Components
|
|
- **Location:** `apps/web/src/lib/components/ui/`
|
|
- **Aktuell:** `Button.svelte`, `Card.svelte`, `Input.svelte`
|
|
- **Styling:** Tailwind CSS v4
|
|
- **Implementierung:** Svelte-spezifisch
|
|
|
|
#### Landing Page
|
|
🔨 **Strategie:** Eigene Astro Components
|
|
- **Location:** `apps/landing/src/components/`
|
|
- **Aktuell:** `Hero.astro`, `CTA.astro`, `Features.astro`
|
|
- **Styling:** Tailwind CSS v3
|
|
- **Implementierung:** Astro-spezifisch
|
|
|
|
### Was KANN geteilt werden
|
|
|
|
✅ **Backend Logic** - `@picture/shared`
|
|
- Supabase client
|
|
- Database types
|
|
- API utilities
|
|
- Validation logic
|
|
- Image utilities
|
|
|
|
✅ **Design Tokens** (Zukünftig) - `@memoro/design-tokens`
|
|
- Colors
|
|
- Spacing
|
|
- Typography
|
|
- Breakpoints
|
|
|
|
### Was NICHT geteilt werden kann
|
|
|
|
❌ **UI Components**
|
|
- React Native components funktionieren nicht im Web
|
|
- Svelte components funktionieren nicht in React Native
|
|
- Astro components funktionieren nicht in React Native
|
|
|
|
### Warum?
|
|
|
|
**Technische Einschränkungen:**
|
|
```tsx
|
|
// React Native
|
|
<View> ≠ <div>
|
|
<Pressable> ≠ <button>
|
|
<Text> ≠ <span>
|
|
react-native-reanimated ≠ Web Animations API
|
|
```
|
|
|
|
---
|
|
|
|
## Migration Steps
|
|
|
|
### Phase 1: Monorepo Setup (Tag 1, ~3h)
|
|
|
|
**1.1 PNPM Installation**
|
|
```bash
|
|
# Install PNPM globally
|
|
npm install -g pnpm
|
|
|
|
# Verify
|
|
pnpm --version
|
|
```
|
|
|
|
**1.2 Ordnerstruktur**
|
|
```bash
|
|
# Create apps directory
|
|
mkdir -p apps
|
|
|
|
# Create packages directory
|
|
mkdir -p packages/shared/src
|
|
mkdir -p packages/design-tokens/src
|
|
|
|
# Move existing code
|
|
mv app apps/mobile/
|
|
mv components apps/mobile/
|
|
mv hooks apps/mobile/
|
|
mv services apps/mobile/
|
|
mv utils apps/mobile/
|
|
mv store apps/mobile/
|
|
# ... all other mobile files
|
|
```
|
|
|
|
**1.3 Workspace Config**
|
|
- `pnpm-workspace.yaml` erstellen
|
|
- Root `package.json` anpassen
|
|
- `.npmrc` erstellen
|
|
- `tsconfig.base.json` erstellen
|
|
|
|
**1.4 Mobile App Package**
|
|
```json
|
|
// apps/mobile/package.json
|
|
{
|
|
"name": "@picture/mobile",
|
|
"version": "1.0.0",
|
|
"main": "expo-router/entry",
|
|
"scripts": {
|
|
"dev": "expo start",
|
|
"ios": "expo run:ios",
|
|
"android": "expo run:android",
|
|
"build:dev": "eas build --profile development",
|
|
"lint": "eslint .",
|
|
"type-check": "tsc --noEmit"
|
|
},
|
|
"dependencies": {
|
|
"@picture/shared": "workspace:*",
|
|
"@memoro/mobile-ui": "workspace:*",
|
|
// ... existing dependencies
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Phase 2: Shared Package (Tag 1-2, ~4h)
|
|
|
|
**2.1 Supabase Types generieren**
|
|
```bash
|
|
# In packages/shared/
|
|
npx supabase gen types typescript \
|
|
--project-id mjuvnnjxwfwlmxjsgkqu \
|
|
> src/types/database.ts
|
|
```
|
|
|
|
**2.2 Utils extrahieren**
|
|
- Image Utils nach `packages/shared/src/utils/image.ts`
|
|
- Validation Utils nach `packages/shared/src/utils/validation.ts`
|
|
- Date Utils nach `packages/shared/src/utils/date.ts`
|
|
|
|
**2.3 API Client erstellen**
|
|
- Supabase Client in `packages/shared/src/api/supabase.ts`
|
|
- Image API in `packages/shared/src/api/images.ts`
|
|
- Auth API in `packages/shared/src/api/auth.ts`
|
|
|
|
---
|
|
|
|
### Phase 3: SvelteKit Setup (Tag 2-3, ~6h)
|
|
|
|
**3.1 Create SvelteKit App**
|
|
```bash
|
|
cd apps
|
|
pnpm create svelte@latest web
|
|
|
|
# Choose:
|
|
# - Skeleton project
|
|
# - TypeScript
|
|
# - ESLint + Prettier
|
|
# - Vitest (optional)
|
|
```
|
|
|
|
**3.2 Install Dependencies**
|
|
```bash
|
|
cd web
|
|
pnpm add @supabase/supabase-js @supabase/ssr
|
|
pnpm add -D tailwindcss autoprefixer postcss
|
|
pnpm add -D @sveltejs/adapter-cloudflare
|
|
|
|
# Add shared package
|
|
pnpm add @picture/shared@workspace:*
|
|
```
|
|
|
|
**3.3 Configure Tailwind**
|
|
```bash
|
|
npx tailwindcss init -p
|
|
```
|
|
|
|
**3.4 Supabase Integration**
|
|
```typescript
|
|
// apps/web/src/lib/supabase.ts
|
|
import { createSupabaseClient } from '@picture/shared/api';
|
|
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
|
|
|
|
export function getSupabase() {
|
|
return createSupabaseClient(
|
|
PUBLIC_SUPABASE_URL,
|
|
PUBLIC_SUPABASE_ANON_KEY
|
|
);
|
|
}
|
|
```
|
|
|
|
**3.5 Basic Routes erstellen**
|
|
- `+layout.svelte` - Root Layout
|
|
- `+page.svelte` - Homepage/Gallery
|
|
- `auth/+page.svelte` - Auth
|
|
- `images/[id]/+page.svelte` - Image Detail
|
|
- `profile/+page.svelte` - Profile
|
|
|
|
---
|
|
|
|
### Phase 4: Astro Landing Page (Tag 3-4, ~4h)
|
|
|
|
**4.1 Create Astro Project**
|
|
```bash
|
|
cd apps
|
|
pnpm create astro@latest landing
|
|
|
|
# Choose:
|
|
# - Empty template
|
|
# - TypeScript (Strict)
|
|
# - Install dependencies
|
|
```
|
|
|
|
**4.2 Install Dependencies**
|
|
```bash
|
|
cd landing
|
|
pnpm add -D tailwindcss autoprefixer postcss
|
|
pnpm add -D @astrojs/tailwind
|
|
pnpm add -D @astrojs/sitemap
|
|
pnpm add -D @astrojs/svelte # Optional
|
|
```
|
|
|
|
**4.3 Configure Astro**
|
|
```javascript
|
|
// apps/landing/astro.config.mjs
|
|
import { defineConfig } from 'astro/config';
|
|
import tailwind from '@astrojs/tailwind';
|
|
import sitemap from '@astrojs/sitemap';
|
|
|
|
export default defineConfig({
|
|
site: 'https://picture.app',
|
|
integrations: [tailwind(), sitemap()],
|
|
output: 'static',
|
|
});
|
|
```
|
|
|
|
**4.4 Pages erstellen**
|
|
- `index.astro` - Homepage
|
|
- `features.astro` - Features
|
|
- `pricing.astro` - Pricing
|
|
- `about.astro` - About
|
|
|
|
---
|
|
|
|
### Phase 5: Design Tokens (Optional, Tag 5, ~3h)
|
|
|
|
**5.1 Package erstellen**
|
|
```bash
|
|
mkdir -p packages/design-tokens/src
|
|
```
|
|
|
|
**5.2 Tokens definieren**
|
|
```typescript
|
|
// packages/design-tokens/src/colors.ts
|
|
export const colors = {
|
|
primary: '#3B82F6',
|
|
secondary: '#8B5CF6',
|
|
dark: {
|
|
bg: '#000000',
|
|
surface: '#242424',
|
|
elevated: '#2a2a2a',
|
|
border: '#383838',
|
|
},
|
|
};
|
|
|
|
// packages/design-tokens/src/spacing.ts
|
|
export const spacing = {
|
|
xs: '0.25rem',
|
|
sm: '0.5rem',
|
|
md: '1rem',
|
|
lg: '1.5rem',
|
|
xl: '2rem',
|
|
};
|
|
|
|
// packages/design-tokens/src/typography.ts
|
|
export const typography = {
|
|
fonts: {
|
|
body: 'Inter, system-ui, sans-serif',
|
|
heading: 'Inter, system-ui, sans-serif',
|
|
},
|
|
sizes: {
|
|
xs: '0.75rem',
|
|
sm: '0.875rem',
|
|
base: '1rem',
|
|
lg: '1.125rem',
|
|
xl: '1.25rem',
|
|
},
|
|
};
|
|
```
|
|
|
|
**5.3 In Apps integrieren**
|
|
```bash
|
|
# Mobile
|
|
pnpm --filter @picture/mobile add @memoro/design-tokens@workspace:*
|
|
|
|
# Web
|
|
pnpm --filter @picture/web add @memoro/design-tokens@workspace:*
|
|
|
|
# Landing
|
|
pnpm --filter @picture/landing add @memoro/design-tokens@workspace:*
|
|
```
|
|
|
|
---
|
|
|
|
## Development Workflow
|
|
|
|
### Starting all apps
|
|
```bash
|
|
# Root directory
|
|
pnpm dev
|
|
```
|
|
|
|
### Starting individual apps
|
|
```bash
|
|
# Mobile (React Native)
|
|
pnpm dev:mobile # Expo on port 8081
|
|
|
|
# Web (SvelteKit)
|
|
pnpm dev:web # http://localhost:5173
|
|
|
|
# Landing (Astro)
|
|
pnpm dev:landing # http://localhost:4321
|
|
```
|
|
|
|
### Building
|
|
```bash
|
|
# Build all apps
|
|
pnpm build
|
|
|
|
# Build individual apps
|
|
pnpm build:mobile
|
|
pnpm build:web
|
|
pnpm build:landing
|
|
```
|
|
|
|
### Type Checking
|
|
```bash
|
|
# Check all packages
|
|
pnpm type-check
|
|
```
|
|
|
|
### Linting
|
|
```bash
|
|
# Lint all packages
|
|
pnpm lint
|
|
```
|
|
|
|
### Adding Dependencies
|
|
|
|
**To a specific app:**
|
|
```bash
|
|
# Add to mobile
|
|
pnpm --filter @picture/mobile add react-native-gesture-handler
|
|
|
|
# Add to web
|
|
pnpm --filter @picture/web add svelte-routing
|
|
|
|
# Add to landing
|
|
pnpm --filter @picture/landing add @astrojs/mdx
|
|
```
|
|
|
|
**To shared package:**
|
|
```bash
|
|
pnpm --filter @picture/shared add date-fns
|
|
```
|
|
|
|
**To all packages:**
|
|
```bash
|
|
pnpm add -w eslint
|
|
```
|
|
|
|
---
|
|
|
|
## Deployment Strategy
|
|
|
|
### Mobile (React Native + Expo)
|
|
|
|
**Development Build:**
|
|
```bash
|
|
cd apps/mobile
|
|
eas build --platform ios --profile development
|
|
eas build --platform android --profile development
|
|
```
|
|
|
|
**Production Build:**
|
|
```bash
|
|
eas build --platform ios --profile production
|
|
eas build --platform android --profile production
|
|
```
|
|
|
|
**Submit to Stores:**
|
|
```bash
|
|
eas submit --platform ios
|
|
eas submit --platform android
|
|
```
|
|
|
|
---
|
|
|
|
### Web (SvelteKit)
|
|
|
|
**Cloudflare Pages (empfohlen):**
|
|
|
|
1. Build locally:
|
|
```bash
|
|
cd apps/web
|
|
pnpm build
|
|
```
|
|
|
|
2. Deploy via Cloudflare Pages Dashboard:
|
|
- **Build command:** `pnpm build`
|
|
- **Output directory:** `build`
|
|
- **Framework preset:** SvelteKit
|
|
|
|
**Environment Variables (Cloudflare):**
|
|
```bash
|
|
PUBLIC_SUPABASE_URL=https://your-project.supabase.co
|
|
PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
|
```
|
|
|
|
**Alternative: Vercel/Netlify:**
|
|
```bash
|
|
# Vercel
|
|
vercel deploy
|
|
|
|
# Netlify
|
|
netlify deploy --prod
|
|
```
|
|
|
|
---
|
|
|
|
### Landing (Astro)
|
|
|
|
**Cloudflare Pages:**
|
|
|
|
1. Build:
|
|
```bash
|
|
cd apps/landing
|
|
pnpm build
|
|
```
|
|
|
|
2. Deploy via Dashboard:
|
|
- **Build command:** `pnpm build`
|
|
- **Output directory:** `dist`
|
|
- **Framework preset:** Astro
|
|
|
|
**Static Site - Alternativen:**
|
|
- Upload `dist/` zu beliebigem Static Host
|
|
- AWS S3 + CloudFront
|
|
- Netlify
|
|
- Vercel
|
|
- GitHub Pages
|
|
|
|
**Vorteile Static Site:**
|
|
- ⚡ Ultraschnell
|
|
- 💰 Günstig (oft kostenlos)
|
|
- 🔒 Sicher
|
|
- 🚀 Einfach zu deployen
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
### Root `.env.example`
|
|
|
|
```bash
|
|
# Supabase
|
|
SUPABASE_URL=https://your-project.supabase.co
|
|
SUPABASE_ANON_KEY=your-anon-key
|
|
SUPABASE_SERVICE_KEY=your-service-key
|
|
|
|
# URLs
|
|
MOBILE_APP_URL=exp://localhost:8081
|
|
WEB_APP_URL=http://localhost:5173
|
|
LANDING_URL=http://localhost:4321
|
|
|
|
# Feature Flags
|
|
FEATURE_UPLOAD_ENABLED=true
|
|
FEATURE_ARCHIVE_ENABLED=true
|
|
```
|
|
|
|
### App-specific Environment Files
|
|
|
|
**Mobile (`apps/mobile/.env`):**
|
|
```bash
|
|
EXPO_PUBLIC_SUPABASE_URL=$SUPABASE_URL
|
|
EXPO_PUBLIC_SUPABASE_ANON_KEY=$SUPABASE_ANON_KEY
|
|
```
|
|
|
|
**Web (`apps/web/.env`):**
|
|
```bash
|
|
PUBLIC_SUPABASE_URL=$SUPABASE_URL
|
|
PUBLIC_SUPABASE_ANON_KEY=$SUPABASE_ANON_KEY
|
|
```
|
|
|
|
**Landing (`apps/landing/.env`):**
|
|
```bash
|
|
# No env needed for static site
|
|
# Optional: PUBLIC_API_URL if needed for contact forms
|
|
```
|
|
|
|
---
|
|
|
|
## Code Sharing Matrix
|
|
|
|
### Was wird geteilt?
|
|
|
|
| Feature | Mobile | Web | Landing | Package | Status |
|
|
|---------|--------|-----|---------|---------|--------|
|
|
| **Backend & Logic** |
|
|
| Supabase Types | ✅ | ✅ | ❌ | `@picture/shared` | ✅ Implemented |
|
|
| API Client | ✅ | ✅ | ❌ | `@picture/shared` | ✅ Implemented |
|
|
| Auth Logic | ✅ | ✅ | ❌ | `@picture/shared` | ✅ Implemented |
|
|
| Image Utils | ✅ | ✅ | ❌ | `@picture/shared` | ✅ Implemented |
|
|
| Validation | ✅ | ✅ | ❌ | `@picture/shared` | ✅ Implemented |
|
|
| Date Utils | ✅ | ✅ | ✅ | `@picture/shared` | ✅ Implemented |
|
|
| **Design System** |
|
|
| Design Tokens | ✅ | ✅ | ✅ | `@memoro/design-tokens` | 🔨 Planned |
|
|
| Colors | ✅ | ✅ | ✅ | `@memoro/design-tokens` | 🔨 Planned |
|
|
| Spacing | ✅ | ✅ | ✅ | `@memoro/design-tokens` | 🔨 Planned |
|
|
| Typography | ✅ | ✅ | ✅ | `@memoro/design-tokens` | 🔨 Planned |
|
|
| **UI Components** |
|
|
| UI Components | ❌ | ❌ | ❌ | Framework-specific | ⚠️ Cannot share |
|
|
| Mobile UI | ✅ | ❌ | ❌ | `@memoro/mobile-ui` | ✅ Implemented |
|
|
| Web UI | ❌ | ✅ | ❌ | Custom Svelte | ✅ Implemented |
|
|
| Landing UI | ❌ | ❌ | ✅ | Custom Astro | ✅ Implemented |
|
|
|
|
### Code Reuse Statistik
|
|
|
|
**Shared Code:** ~35-40%
|
|
- Backend Logic: 100% geteilt
|
|
- Types: 100% geteilt
|
|
- Utils: 80% geteilt
|
|
- UI Components: 0% geteilt
|
|
|
|
**Vorteile:**
|
|
- ✅ Single Source of Truth für Business Logic
|
|
- ✅ Type Safety über alle Apps
|
|
- ✅ Konsistente API Calls
|
|
- ✅ Weniger Bugs durch geteilte Utils
|
|
|
|
**Nachteile:**
|
|
- ❌ UI Components müssen separat implementiert werden
|
|
- ⚠️ Design Konsistenz erfordert manuelle Synchronisation (ohne Design Tokens)
|
|
|
|
---
|
|
|
|
## Recommendations & Future Options
|
|
|
|
### Current Approach (Implemented) ✅
|
|
|
|
**Strategie:** Framework-spezifische UI Components
|
|
|
|
**Pros:**
|
|
- ✅ Einfach zu verstehen
|
|
- ✅ Framework-optimierte Components
|
|
- ✅ Keine zusätzliche Komplexität
|
|
- ✅ Schnelle Entwicklung
|
|
|
|
**Cons:**
|
|
- ❌ Doppelte Implementierung von UI
|
|
- ❌ Manuelle Design Synchronisation
|
|
- ❌ Mehr Maintenance
|
|
|
|
**Status:** Production-ready
|
|
|
|
---
|
|
|
|
### Option 1: Design Tokens (Empfohlen für nächste Phase) 🎯
|
|
|
|
**Strategie:** Geteilte Design Values, eigene Components
|
|
|
|
**Implementierung:**
|
|
```
|
|
packages/
|
|
└── design-tokens/
|
|
├── colors.ts
|
|
├── spacing.ts
|
|
├── typography.ts
|
|
├── breakpoints.ts
|
|
└── tailwind.preset.js
|
|
```
|
|
|
|
**Verwendung:**
|
|
```tsx
|
|
// Mobile
|
|
import { colors, spacing } from '@memoro/design-tokens';
|
|
|
|
// Web
|
|
import { colors, spacing } from '@memoro/design-tokens';
|
|
|
|
// Landing
|
|
import { colors, spacing } from '@memoro/design-tokens';
|
|
```
|
|
|
|
**Pros:**
|
|
- ✅ Visuelle Konsistenz (colors, spacing, typography)
|
|
- ✅ Single Source of Truth für Design
|
|
- ✅ Einfach zu updaten (Branding)
|
|
- ✅ Geringe Komplexität
|
|
|
|
**Cons:**
|
|
- ⚠️ Components müssen noch separat implementiert werden
|
|
|
|
**Empfehlung:** ⭐ **Implementieren in Phase 6**
|
|
|
|
**Timeline:** ~3-4h
|
|
|
|
---
|
|
|
|
### Option 2: Headless UI + Adapters (Erweitert) 🚀
|
|
|
|
**Strategie:** Geteilte Business Logic, Framework-spezifisches Rendering
|
|
|
|
**Architektur:**
|
|
```
|
|
packages/
|
|
├── ui-core/ # Headless logic (TypeScript)
|
|
│ ├── useButton.ts
|
|
│ ├── useSelect.ts
|
|
│ └── useModal.ts
|
|
├── mobile-ui/ # React Native rendering
|
|
├── web-ui/ # Svelte rendering
|
|
└── landing-ui/ # Astro rendering
|
|
```
|
|
|
|
**Beispiel:**
|
|
```typescript
|
|
// packages/ui-core/useButton.ts
|
|
export function useButton(props: ButtonProps) {
|
|
return {
|
|
isPressed: state.pressed,
|
|
isHovered: state.hovered,
|
|
handlePress: () => { /* logic */ },
|
|
ariaProps: { /* a11y */ }
|
|
};
|
|
}
|
|
|
|
// Mobile (React Native)
|
|
const ButtonRN = (props) => {
|
|
const { isPressed, handlePress, ariaProps } = useButton(props);
|
|
return <Pressable onPress={handlePress} {...ariaProps} />;
|
|
};
|
|
|
|
// Web (Svelte)
|
|
const ButtonSvelte = (props) => {
|
|
const { isPressed, handlePress, ariaProps } = useButton(props);
|
|
return <button onclick={handlePress} {...ariaProps} />;
|
|
};
|
|
```
|
|
|
|
**Pros:**
|
|
- ✅ Geteilte Business Logic
|
|
- ✅ Konsistentes Verhalten
|
|
- ✅ Framework-optimiertes Rendering
|
|
- ✅ A11y einmal implementiert
|
|
|
|
**Cons:**
|
|
- ❌ Hohe Komplexität
|
|
- ❌ Mehr Packages zu managen
|
|
- ❌ Longer Development Time
|
|
- ❌ Overhead für kleine Teams
|
|
|
|
**Empfehlung:** ⚠️ **Nur wenn UI Konsistenz kritisch wird**
|
|
|
|
**Timeline:** ~2-3 Wochen
|
|
|
|
---
|
|
|
|
### Recommended Roadmap
|
|
|
|
#### Phase 1-4: ✅ **DONE**
|
|
- Monorepo Setup
|
|
- Apps (Mobile, Web, Landing)
|
|
- Shared Package
|
|
- Mobile UI Library
|
|
|
|
#### Phase 5: 🎯 **NEXT** (3-4h)
|
|
**Design Tokens Package**
|
|
- Extract colors, spacing, typography
|
|
- Create `@memoro/design-tokens`
|
|
- Integrate in all apps
|
|
- Visual consistency ohne Component Sharing
|
|
|
|
#### Phase 6: 🔮 **FUTURE** (Optional)
|
|
**Headless UI** (nur bei Bedarf)
|
|
- Nur wenn UI Consistency kritisch wird
|
|
- Nur wenn Team wächst
|
|
- Nur wenn Budget vorhanden
|
|
|
|
---
|
|
|
|
## Timeline Summary
|
|
|
|
### Completed ✅
|
|
|
|
- **Phase 1:** Monorepo Setup (3h)
|
|
- **Phase 2:** Shared Package (4h)
|
|
- **Phase 3:** SvelteKit App (10h)
|
|
- **Phase 4:** Astro Landing (6h)
|
|
- **Phase 5:** Mobile UI Library (bereits vorhanden)
|
|
|
|
**Total:** ~23h Development Time
|
|
|
|
### Next Steps 🎯
|
|
|
|
- **Phase 6:** Design Tokens Package (3-4h)
|
|
- **Phase 7:** Deployment Setup (4h)
|
|
- **Phase 8:** CI/CD Pipeline (6h)
|
|
|
|
**Estimated Total:** ~36-40h für komplettes Setup
|
|
|
|
---
|
|
|
|
## Advantages of Current Architecture
|
|
|
|
### ✅ Maximale Unabhängigkeit
|
|
- Jede App kann unabhängig deployed werden
|
|
- Kein Vendor Lock-in
|
|
- Web Standards überall
|
|
|
|
### ✅ Code Reuse (~40%)
|
|
- Types einmal definieren
|
|
- API Logic zentral
|
|
- Utils geteilt
|
|
- Validation zentral
|
|
|
|
### ✅ Optimal für Zweck
|
|
- Mobile: Native Experience mit Expo
|
|
- Web: Full App mit SSR (SEO)
|
|
- Landing: Ultraschnell, Static (Marketing)
|
|
|
|
### ✅ Einfache Wartung
|
|
- Clear Separation of Concerns
|
|
- Shared Logic zentral
|
|
- Easy Updates
|
|
- Framework-agnostic Backend
|
|
|
|
### ✅ Skalierbar
|
|
- Neue Apps einfach hinzufügen
|
|
- Packages wachsen organisch
|
|
- CI/CD pro App
|
|
- Independent Teams möglich
|
|
|
|
---
|
|
|
|
## Tech Stack Summary
|
|
|
|
```yaml
|
|
Mobile (React Native):
|
|
Framework: Expo SDK 54
|
|
Routing: Expo Router
|
|
Styling: NativeWind
|
|
State: Zustand
|
|
UI: @memoro/mobile-ui (17 components)
|
|
Deploy: EAS Build → App Store / Google Play
|
|
|
|
Web (SvelteKit):
|
|
Framework: SvelteKit 2.x / Svelte 5
|
|
Styling: Tailwind CSS v4
|
|
UI: Custom Svelte Components
|
|
Build: Vite
|
|
Deploy: Cloudflare Pages
|
|
|
|
Landing (Astro):
|
|
Framework: Astro 5.x
|
|
Styling: Tailwind CSS v3
|
|
UI: Custom Astro Components
|
|
Output: Static Site
|
|
Deploy: Cloudflare Pages
|
|
|
|
Shared:
|
|
Language: TypeScript 5.x
|
|
Backend: Supabase
|
|
Package Manager: PNPM
|
|
Workspace: PNPM Workspaces
|
|
Version Control: Git
|
|
```
|
|
|
|
---
|
|
|
|
## Support & Resources
|
|
|
|
### Documentation
|
|
- [PNPM Workspaces](https://pnpm.io/workspaces)
|
|
- [Expo Documentation](https://docs.expo.dev/)
|
|
- [SvelteKit Documentation](https://kit.svelte.dev/)
|
|
- [Astro Documentation](https://docs.astro.build/)
|
|
- [Supabase Documentation](https://supabase.com/docs)
|
|
|
|
### Tools
|
|
- `@memoro/mobile-ui` CLI: `node packages/mobile-ui/cli/bin/cli.js`
|
|
- Supabase CLI: `npx supabase`
|
|
- Expo CLI: `npx expo`
|
|
|
|
### Commands Quick Reference
|
|
|
|
```bash
|
|
# Development
|
|
pnpm dev # All apps
|
|
pnpm dev:mobile # Mobile only
|
|
pnpm dev:web # Web only
|
|
pnpm dev:landing # Landing only
|
|
|
|
# Building
|
|
pnpm build # All apps
|
|
pnpm build:mobile # Mobile build
|
|
pnpm build:web # Web build
|
|
pnpm build:landing # Landing build
|
|
|
|
# Quality
|
|
pnpm lint # Lint all
|
|
pnpm type-check # Type check all
|
|
pnpm test # Test all (if configured)
|
|
|
|
# Maintenance
|
|
pnpm clean # Clean all node_modules
|
|
```
|
|
|
|
---
|
|
|
|
## Authors & Changelog
|
|
|
|
**Initial Documentation:** 2025-10-08
|
|
**Consolidated Guide:** 2025-10-09
|
|
|
|
**Authors:**
|
|
- Claude Code (AI Assistant)
|
|
- Till Schneider (Project Owner)
|
|
|
|
**Status:** Production Ready ✅
|
|
|
|
---
|
|
|
|
**🚀 Ready to build amazing things!**
|