4.0 KiB
4.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
Mobile App (Expo)
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)
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)
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, Profileapp/scanner.tsx— Plant scan modalapp/lexicon.tsx— Plant encyclopediaapp/plant/— Plant detail screensapp/auth/— Login / Signup screensapp/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 plantsservices/plantRecognitionService.ts— Calls/v1/scanon backendservices/plantDatabaseService.ts— Local static plant dataservices/authService.ts— JWT auth against backendservices/backend/backendApiClient.ts— HTTP client for all/v1/*callsservices/backend/mockBackendService.ts— In-app mock ifEXPO_PUBLIC_BACKEND_URLis 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 searchauth.js— JWT-based signup/loginbilling.js— Credits, idempotency, Stripe webhooksopenai.js— Plant identification + health analysis via OpenAIstorage.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):
- Remove
server/lib/sqlite.jsandserver/data/entirely - Remove Railway service for the Express server (no longer needed)
- Add
pgpackage toserver/package.json - Replace all SQLite calls with
pgandDATABASE_URLenv var - Change all SQL placeholders from
?to$1, $2, ...(SQLite → PostgreSQL syntax) - Add Express server as a service in
greenlens-landing/docker-compose.yml - Use
JSONBcolumns 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.tssupportsde/en/es - Colors:
constants/Colors.tswith light/dark mode tokens - Image URIs: App sends base64 to
/v1/upload/image, gets back a public MinIO URL