mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
148 lines
6.0 KiB
Markdown
148 lines
6.0 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Sauci is a couples intimacy app featuring swipeable question packs with partner matching. Users swipe on questions (yes/no/maybe), and when both partners answer positively, a "match" is created that unlocks a chat thread for that question.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Install dependencies (from root)
|
|
npm install
|
|
|
|
# Start all apps in development
|
|
npm run dev
|
|
|
|
# Run specific apps
|
|
cd apps/mobile && npm run dev # Expo mobile app
|
|
cd apps/admin && npm run dev # React Admin dashboard
|
|
|
|
# Type checking
|
|
npm run typecheck
|
|
|
|
# Linting
|
|
npm run lint
|
|
|
|
# Build all
|
|
npm run build
|
|
```
|
|
|
|
### Mobile-specific commands
|
|
```bash
|
|
cd apps/mobile
|
|
npm run ios # Run on iOS simulator
|
|
npm run android # Run on Android emulator
|
|
npm run web # Run in browser
|
|
```
|
|
|
|
### Supabase commands
|
|
```bash
|
|
supabase start # Start local Supabase
|
|
supabase db reset # Reset DB and run all migrations
|
|
supabase functions serve # Run edge functions locally
|
|
supabase migration new <name> # Create new migration
|
|
```
|
|
|
|
### Supabase Environments
|
|
|
|
There are two Supabase projects configured via MCP servers:
|
|
|
|
| Environment | Project Ref | URL | MCP Server |
|
|
|-------------|-------------|-----|------------|
|
|
| **Production** | `ckjcrkjpmhqhiucifukx` | https://ckjcrkjpmhqhiucifukx.supabase.co | `sauci-prod` |
|
|
| **Non-Production** | `itbzhrvlgvdmzbnhzhyx` | https://itbzhrvlgvdmzbnhzhyx.supabase.co | `sauci-non-prod` |
|
|
|
|
When using Claude Code with MCP tools:
|
|
- Use `mcp__sauci-prod__*` tools for production database operations
|
|
- Use `mcp__sauci-non-prod__*` tools for development/staging database operations
|
|
- **Always verify which environment you're targeting before running migrations or destructive operations**
|
|
|
|
## Architecture
|
|
|
|
### Monorepo Structure (Turborepo)
|
|
- `apps/mobile` - Expo React Native app (expo-router for navigation)
|
|
- `apps/admin` - React Admin dashboard for content management
|
|
- `apps/supabase` - Database migrations and edge functions
|
|
- `packages/shared` - Shared TypeScript types (`@sauci/shared`)
|
|
|
|
### Mobile App Architecture
|
|
- **Routing**: Expo Router with file-based routing (`app/` directory)
|
|
- `(auth)/` - Authentication screens
|
|
- `(app)/` - Main app screens (protected)
|
|
- **State Management**: Zustand stores in `src/store/index.ts`
|
|
- `useAuthStore` - User, couple, partner state
|
|
- `useMatchStore` - Matches and notifications
|
|
- `usePacksStore` - Question packs and enabled packs per couple
|
|
- `useMessageStore` - Chat messages and unread counts
|
|
- `useSubscriptionStore` - RevenueCat subscription state
|
|
- **Backend**: Supabase client in `src/lib/supabase.ts`
|
|
- **UI Components**: Glass-morphism themed components in `src/components/ui/`
|
|
|
|
### Data Model (Core Entities)
|
|
- **Profile** - User profile extending Supabase auth (has `couple_id`)
|
|
- **Couple** - Two users linked via invite code
|
|
- **QuestionPack** - Collection of questions (can be premium)
|
|
- **Question** - Individual question with intensity level (1-5)
|
|
- **Response** - User's answer (yes/no/maybe) to a question
|
|
- **Match** - Created when both partners answer positively (yes_yes, yes_maybe, maybe_maybe)
|
|
|
|
### Edge Functions
|
|
Edge functions in `apps/supabase/functions/` handle complex operations:
|
|
- `submit-response` - Saves response, checks for matches, triggers notifications
|
|
- `manage-couple` - Join/leave couple operations
|
|
- `send-notification` - Push notifications for matches
|
|
- `revenuecat-webhook` - Subscription webhook handler
|
|
- `sync-subscription` - Syncs RevenueCat subscription status
|
|
|
|
#### Edge Function Deployment Guidelines
|
|
When deploying edge functions via MCP tools (`mcp__sauci-*__deploy_edge_function`):
|
|
|
|
**IMPORTANT: Always use `verify_jwt: false`** for all edge functions. Supabase's built-in JWT verification causes 401 errors even with valid tokens. Instead, handle authentication manually in the function code using:
|
|
```typescript
|
|
const { data: { user }, error: authError } = await supabase.auth.getUser(
|
|
authHeader.replace("Bearer ", "")
|
|
);
|
|
```
|
|
|
|
This approach:
|
|
- Gives better error messages
|
|
- Allows custom auth handling
|
|
- Avoids mysterious 401 failures
|
|
|
|
**Current function settings (all should be verify_jwt: false):**
|
|
| Function | verify_jwt | Auth Method |
|
|
|----------|------------|-------------|
|
|
| `manage-couple` | false | Manual via getUser() |
|
|
| `submit-response` | false | Manual via getUser() |
|
|
| `sync-subscription` | false | Manual via getUser() |
|
|
| `delete-relationship` | false | Manual via getUser() |
|
|
| `revenuecat-webhook` | false | Webhook signature validation |
|
|
| `send-notification` | false | Internal trigger (no auth) |
|
|
| `send-message-notification` | false | Internal trigger (no auth) |
|
|
|
|
### Database Best Practices
|
|
- **Always use `.maybeSingle()` instead of `.single()`** when the row might not exist. `.single()` throws an error if 0 or >1 rows are returned.
|
|
- **Profile creation trigger**: The `on_auth_user_created` trigger automatically creates a profile when a user signs up. Never assume a profile exists without checking.
|
|
- **Check for null profiles** in edge functions before performing operations.
|
|
|
|
### Key Patterns
|
|
- Responses use UPSERT with `onConflict: "user_id,question_id"`
|
|
- Match detection happens in `submit-response` edge function after each response
|
|
- Real-time subscriptions used for chat messages
|
|
- RevenueCat handles in-app purchases and subscription management
|
|
- RLS policies enforce couple-level data isolation
|
|
|
|
## Mobile UI - DO NOT CHANGE
|
|
|
|
### Tab Bar Background
|
|
**NEVER set `backgroundColor: 'transparent'` on the tab bar.** Always use a semi-transparent solid color:
|
|
```typescript
|
|
backgroundColor: 'rgba(18, 18, 18, 0.85)',
|
|
```
|
|
|
|
The `BlurView` in `tabBarBackground` is unreliable and can fail during re-renders/transitions, causing a fully transparent tab bar. The solid rgba background acts as a fallback while still allowing the blur effect on top.
|
|
|
|
**Location:** `apps/mobile/app/(app)/_layout.tsx` - `tabBarStyle`
|