Files
Compass/web/README.md
MartinBraquet 7037362b40 Update docs
2026-03-01 05:35:46 +01:00

8.2 KiB

Web Application

The Compass web application built with Next.js, React, and TypeScript.

Overview

This is the frontend of the Compass platform, a transparent platform for forming deep, authentic 1-on-1 connections.

Tech Stack

  • Framework: Next.js 14.1.0
  • Language: TypeScript
  • UI Library: React 18.2.0
  • Styling: Tailwind CSS 3.3.3
  • State Management: React Context + Custom Hooks
  • Forms: React Hook Form
  • Rich Text: TipTap (ProseMirror)
  • Charts: Recharts
  • i18n: Custom solution with JSON message files

Project Structure

web/
├── components/           # React components
│   ├── auth-context.tsx   # Authentication state
│   ├── buttons/           # Button components
│   ├── chat/              # Chat/messaging components
│   ├── comments/          # Comment components
│   ├── editor/            # Rich text editor
│   ├── events/            # Event components
│   ├── filters/           # Search filters
│   ├── matches/           # Match components
│   ├── nav/               # Navigation components
│   ├── profile/           # Profile components
│   └── widgets/           # Reusable widgets
├── hooks/                 # Custom React hooks (50+)
├── lib/                  # Utilities and services
│   ├── api.ts            # API client
│   ├── firebase/         # Firebase configuration
│   ├── locale/           # Internationalization
│   ├── service/          # Analytics, push notifications
│   ├── supabase/         # Supabase client
│   └── logger.ts        # Structured logging
├── pages/                # Next.js pages
│   ├── api/              # API routes
│   ├── _app.tsx          # App wrapper
│   ├── _document.tsx     # Document setup
│   └── [username].tsx    # Dynamic routes
├── messages/             # Translation JSON files
├── public/               # Static assets
├── styles/              # Global CSS
├── tests/
│   ├── unit/            # Unit tests
│   └── integration/     # Integration tests
└── types/               # TypeScript type definitions

Getting Started

Prerequisites

  • Node.js 20.x or later
  • Yarn 1.x

Installation

# From root directory
yarn install

Development

# Run web app with hot reload
yarn dev

# Or from web directory
cd web
yarn serve

Visit http://localhost:3000

Build

# Production build
yarn build

# Start production server
yarn start

Testing

# Run tests
yarn test

# Run with coverage
yarn test --coverage

# Watch mode
yarn test --watch

Linting

# Check lint
yarn lint

# Fix lint issues
yarn lint-fix

Key Concepts

Components

Components are organized by feature in /components. Reusable widgets are in /components/widgets.

Example component:

// components/profile/profile-card.tsx
import {User} from 'common/src/user'

interface ProfileCardProps {
  user: User
  onLike?: (userId: string) => void
}

export function ProfileCard({user, onLike}: ProfileCardProps) {
  return (
    <div className="profile-card">
      <img src={user.avatarUrl} alt={user.name} />
      <h3>{user.name}</h3>
      <button onClick={() => onLike?.(user.id)}>Like</button>
    </div>
  )
}

Hooks

Use custom hooks for stateful logic. Common hooks:

  • useUser() - Get current user
  • useAPIGetter() - Fetch API data with caching
  • useMutation() - Handle form submissions
  • usePersistentInMemoryState() - Cache state across pages
import {useAPIGetter} from 'web/hooks/use-api-getter'

function ProfileList() {
  const {data, refresh} = useAPIGetter('get-profiles', {})

  if (!data) return <Loading />

  return (
    <div>
      {data.profiles.map((profile) => (
        <ProfileCard key={profile.id} user={profile} />
      ))}
      <button onClick={refresh}>Refresh</button>
    </div>
  )
}

API Calls

Backend API is called through the api helper:

import {api} from 'web/lib/api'

// Server-side (getStaticProps, getServerSideProps)
const profiles = await api('get-profiles', {})

// Client-side - use hooks
const {data} = useAPIGetter('get-profiles', {})

Internationalization

Translation files are in /messages (e.g., en.json, fr.json).

import {useT} from 'web/lib/locale'

function MyComponent() {
  const t = useT()

  return <h1>{t('welcome', 'Welcome to Compass')}</h1>
}

Styling

Tailwind CSS is used for styling. Use utility classes:

<div className="flex items-center justify-between p-4 bg-canvas-50 rounded-lg">
  <span className="text-ink-900 font-medium">Content</span>
</div>

Accessibility

The app includes several accessibility features:

Error Boundary

Catches React errors and shows user-friendly message:

import {ErrorBoundary} from 'web/components/error-boundary'

;<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

Live Region

Announces dynamic content changes to screen readers:

import {useLiveRegion} from 'web/components/live-region'

const {announce} = useLiveRegion()

// Announce status changes
announce('Profile liked', 'polite')

Priority levels:

  • polite - Waits for screen reader to finish (default)
  • assertive - Interrupts immediately

Keyboard users can skip to main content:

import {SkipLink, MainContent} from 'web/components/skip-link'

;<>
  <SkipLink />
  <MainContent>...</MainContent>
</>

Logging

Use the structured logger for debug logging that's filtered out in production:

import {debug, logApiError} from 'common/logger'

// Simple logging
debug('User logged in', {userId: '123'})

// API errors with context
try {
  await api('endpoint', {})
} catch (err) {
  logApiError('get-profiles', err, {userId: '123'})
}

Environment Variables

Key environment variables for the web app:

Variable Description
NEXT_PUBLIC_SUPABASE_URL Supabase project URL
NEXT_PUBLIC_SUPABASE_ANON_KEY Supabase anon key
NEXT_PUBLIC_FIREBASE_API_KEY Firebase API key
NEXT_PUBLIC_POSTHOG_KEY PostHog analytics key
NEXT_PUBLIC_VERCEL_ENV Vercel environment

Common Tasks

Adding a New Page

  1. Create file in /pages/:
// pages/new-page.tsx
import {Page} from 'web/components/page-base'

export default function NewPage() {
  return (
    <Page>
      <h1>New Page</h1>
    </Page>
  )
}

Adding a Component

  1. Create file in appropriate /components subdirectory
  2. Export the component
  3. Add to parent component

Adding a Hook

  1. Create file in /hooks/
  2. Follow naming convention:*.ts`

`use- Adding Translations

  1. Add key to /messages/en.json
  2. Add translations to other locale files

Troubleshooting

Slow local development

Running yarn dev:isolated uses local emulators and is faster.

Type errors

Run yarn typecheck to see all type errors.

Build failures

Check yarn lint first, as linting issues can cause build failures.

See Also

Setup

This is the setup for deployment on Vercel, which you only need to do if you create a new platform from scratch, not if you are contributing to Compass

Set up a Vercel account and link it to your GitHub repository.

Add the following environment variables and the ones in .env in the Vercel dashboard:

NEXT_PUBLIC_VERCEL=1

next version

The next version is 14.1.0, as we get the following error with 15.1.2 and above when accessing /[username] pages on Vercel:

Cannot find module 'next/dist/compiled/source-map'
Require stack:
- /var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js
- /var/task/web/___next_launcher.cjs
Did you forget to add it to "dependencies" in `package.json`?
Node.js process exited with exit status: 1. The logs above can help with debugging the issue.

TODO: investigate, find a fix and upgrade.