Slefhostet und postgres
This commit is contained in:
194
CLAUDE.md
194
CLAUDE.md
@@ -1,102 +1,92 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Commands
|
||||
|
||||
### Mobile App (Expo)
|
||||
```bash
|
||||
npm install # Install dependencies
|
||||
npm run start # Start Expo dev server (offline mode)
|
||||
npm run android # Start on Android
|
||||
npm run ios # Start on iOS
|
||||
npm run test # Run Jest tests
|
||||
```
|
||||
|
||||
### Server (Express)
|
||||
```bash
|
||||
cd server
|
||||
npm install
|
||||
npm run start # Start Express server
|
||||
npm run rebuild:batches # Rebuild plant catalog from batch constants
|
||||
npm run diagnostics # Check duplicates and import audits
|
||||
```
|
||||
|
||||
### Production Builds (EAS)
|
||||
```bash
|
||||
npx eas-cli build:version:set -p ios # Bump iOS build number
|
||||
npx eas-cli build -p ios --profile production
|
||||
npx eas-cli submit -p ios --latest # Submit to TestFlight
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Mobile App
|
||||
Expo Router with file-based routing. Entry point is `app/_layout.tsx`.
|
||||
|
||||
- **`app/(tabs)/`** — Tab navigation: Home (`index.tsx`), Search, Profile
|
||||
- **`app/scanner.tsx`** — Plant scan modal
|
||||
- **`app/lexicon.tsx`** — Plant encyclopedia
|
||||
- **`app/plant/`** — Plant detail screens
|
||||
- **`app/auth/`** — Login / Signup screens
|
||||
- **`app/onboarding.tsx`** — First-launch onboarding
|
||||
|
||||
Global state lives in `context/AppContext.tsx` (plants, user, billing, language).
|
||||
|
||||
### Services Layer (Mobile)
|
||||
- `services/storageService.ts` — AsyncStorage persistence for user plants
|
||||
- `services/plantRecognitionService.ts` — Calls `/v1/scan` on backend
|
||||
- `services/plantDatabaseService.ts` — Local static plant data
|
||||
- `services/authService.ts` — JWT auth against backend
|
||||
- `services/backend/backendApiClient.ts` — HTTP client for all `/v1/*` calls
|
||||
- `services/backend/mockBackendService.ts` — In-app mock if `EXPO_PUBLIC_BACKEND_URL` is not set
|
||||
|
||||
### Backend (Express — `server/`)
|
||||
Single `server/index.js` with all routes. Libs in `server/lib/`:
|
||||
|
||||
- `sqlite.js` — SQLite wrapper (`openDatabase`, `run`, `get`, `all`)
|
||||
- `plants.js` — Plant catalog CRUD + semantic search
|
||||
- `auth.js` — JWT-based signup/login
|
||||
- `billing.js` — Credits, idempotency, Stripe webhooks
|
||||
- `openai.js` — Plant identification + health analysis via OpenAI
|
||||
- `storage.js` — MinIO/S3 image upload (`uploadImage`, `ensureStorageBucket`)
|
||||
|
||||
Key env vars for server:
|
||||
```
|
||||
PLANT_DB_PATH # SQLite file path (default: server/data/greenlns.sqlite)
|
||||
OPENAI_API_KEY
|
||||
STRIPE_SECRET_KEY
|
||||
JWT_SECRET
|
||||
MINIO_ENDPOINT / MINIO_ACCESS_KEY / MINIO_SECRET_KEY / MINIO_BUCKET / MINIO_PUBLIC_URL
|
||||
```
|
||||
|
||||
### Landing Page (`greenlns-landing/`)
|
||||
Next.js 16 app with `output: 'standalone'` for Docker. Runs independently from the mobile app.
|
||||
|
||||
Has its own `docker-compose.yml` that spins up:
|
||||
- Next.js app (Landing Page)
|
||||
- PostgreSQL 16 (persistent DB for the backend)
|
||||
- MinIO (persistent image storage)
|
||||
- Nginx (reverse proxy + SSL)
|
||||
|
||||
### Infrastructure Plan
|
||||
**Current state:** Server runs on Railway with SQLite (ephemeral).
|
||||
|
||||
**Target state (not yet migrated):**
|
||||
- Express Server moves OFF Railway → runs on the landing page server via `docker-compose.yml`
|
||||
- PostgreSQL + MinIO replace SQLite + Railway hosting entirely
|
||||
|
||||
**When migrating to PostgreSQL (do all of these together):**
|
||||
1. Remove `server/lib/sqlite.js` and `server/data/` entirely
|
||||
2. Remove Railway service for the Express server (no longer needed)
|
||||
3. Add `pg` package to `server/package.json`
|
||||
4. Replace all SQLite calls with `pg` and `DATABASE_URL` env var
|
||||
5. Change all SQL placeholders from `?` to `$1, $2, ...` (SQLite → PostgreSQL syntax)
|
||||
6. Add Express server as a service in `greenlens-landing/docker-compose.yml`
|
||||
7. Use `JSONB` columns in PostgreSQL for nested data (e.g. `careInfo`, `categories`) instead of serialized strings — enables fast querying and filtering directly on JSON fields
|
||||
|
||||
### Key Patterns
|
||||
- SQL placeholders: SQLite uses `?`, PostgreSQL uses `$1, $2, ...` — important when migrating
|
||||
- Translations: `utils/translations.ts` supports `de` / `en` / `es`
|
||||
- Colors: `constants/Colors.ts` with light/dark mode tokens
|
||||
- Image URIs: App sends base64 to `/v1/upload/image`, gets back a public MinIO URL
|
||||
# CLAUDE.md
|
||||
|
||||
This repository contains the GreenLens mobile app, the Express backend, and the self-hosted landing/deployment stack.
|
||||
|
||||
## Commands
|
||||
|
||||
### Mobile app
|
||||
```bash
|
||||
npm install
|
||||
npm run start
|
||||
npm run android
|
||||
npm run ios
|
||||
npm run test
|
||||
```
|
||||
|
||||
### Backend
|
||||
```bash
|
||||
cd server
|
||||
npm install
|
||||
npm run start
|
||||
npm run rebuild:batches
|
||||
npm run diagnostics
|
||||
```
|
||||
|
||||
### Production iOS builds
|
||||
```bash
|
||||
npx eas-cli build:version:set -p ios
|
||||
npx eas-cli build -p ios --profile production
|
||||
npx eas-cli submit -p ios --latest
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Mobile app
|
||||
- Expo Router entrypoint: `app/_layout.tsx`
|
||||
- Global app state: `context/AppContext.tsx`
|
||||
- Backend HTTP client: `services/backend/backendApiClient.ts`
|
||||
- In-app fallback mock: `services/backend/mockBackendService.ts`
|
||||
|
||||
### Backend
|
||||
Single Express server in `server/index.js` with supporting modules in `server/lib/`:
|
||||
|
||||
- `postgres.js` for PostgreSQL access
|
||||
- `sqlite.js` as a compatibility shim re-exporting the PostgreSQL layer
|
||||
- `plants.js` for plant catalog persistence and diagnostics
|
||||
- `auth.js` for JWT auth
|
||||
- `billing.js` for credits, RevenueCat, Stripe, and idempotency
|
||||
- `openai.js` for scan and health-check model calls
|
||||
- `storage.js` for MinIO/S3 object uploads
|
||||
|
||||
Primary backend environment variables:
|
||||
|
||||
```bash
|
||||
DATABASE_URL
|
||||
POSTGRES_HOST
|
||||
POSTGRES_PORT
|
||||
POSTGRES_DB
|
||||
POSTGRES_USER
|
||||
POSTGRES_PASSWORD
|
||||
JWT_SECRET
|
||||
OPENAI_API_KEY
|
||||
STRIPE_SECRET_KEY
|
||||
MINIO_ENDPOINT
|
||||
MINIO_ACCESS_KEY
|
||||
MINIO_SECRET_KEY
|
||||
MINIO_BUCKET
|
||||
MINIO_PUBLIC_URL
|
||||
```
|
||||
|
||||
### Landing and deployment
|
||||
`greenlns-landing/` is a Next.js 16 app built with `output: 'standalone'`.
|
||||
|
||||
The production-style stack lives in `greenlns-landing/docker-compose.yml` and includes:
|
||||
|
||||
- `caddy` for TLS and reverse proxy
|
||||
- `landing` for the Next.js app
|
||||
- `api` for the Express backend
|
||||
- `postgres` for persistent app data
|
||||
- `minio` for object storage
|
||||
|
||||
`greenlns-landing/Caddyfile` routes:
|
||||
|
||||
- `/` to the landing app
|
||||
- `/api/*`, `/auth/*`, `/v1/*`, `/health`, `/plants/*` to the Express API
|
||||
- `/storage/*` to MinIO
|
||||
|
||||
## Data model notes
|
||||
|
||||
- PostgreSQL is the source of truth for server persistence.
|
||||
- Nested plant metadata such as `categories` and `careInfo` uses `JSONB`.
|
||||
- Billing idempotency responses also use `JSONB`.
|
||||
- SQL placeholders use PostgreSQL syntax: `$1`, `$2`, ...
|
||||
|
||||
Reference in New Issue
Block a user