---
trigger: always_on
description:
globs:
---
## Project Structure
Compass (compassmeet.com) is a transparent dating platform for forming deep, authentic 1-on-1 connections.
- **Next.js React frontend** `/web`
- Pages, components, hooks, lib
- **Express Node API server** `/backend/api`
- **Shared backend utilities** `/backend/shared`
- **Email functions** `/backend/email`
- **Database schema** `/backend/supabase`
- Supabase-generated types in `/backend/supabase/schema.ts`
- **Files shared between frontend and backend** `/common`
- Types (User, Profile, etc.) and utilities
- Try not to add package dependencies to common
- **Android app** `/android`
## Deployment
- Both dev and prod environments
- Backend on GCP (Google Cloud Platform)
- Frontend on Vercel
- Database on Supabase (PostgreSQL)
- Firebase for authentication and storage
## Code Guidelines
### Component Example
```tsx
import clsx from 'clsx'
import Link from 'next/link'
import {User} from 'common/user'
import {ProfileRow} from 'common/profiles/profile'
import {useUser} from 'web/hooks/use-user'
import {useT} from 'web/lib/locale'
interface ProfileCardProps {
user: User
profile: ProfileRow
}
export function ProfileCard({user, profile}: ProfileCardProps) {
const t = useT()
return (
{user.name}
{profile.bio}
)
}
```
We prefer many smaller components that each represent one logical unit, rather than one large component.
Export the main component at the top of the file. Name the component the same as the file (e.g., `profile-card.tsx` →
`ProfileCard`).
### API Calls
**Server-side (getStaticProps):**
```typescript
import {api} from 'web/lib/api'
export async function getStaticProps() {
const profiles = await api('get-profiles', {})
return {
props: {profiles},
revalidate: 30 * 60, // 30 minutes
}
}
```
**Client-side - use hooks:**
```typescript
import {useAPIGetter} from 'web/hooks/use-api-getter'
function ProfileList() {
const {data, refresh} = useAPIGetter('get-profiles', {})
if (!data) return
return (