# Signal-Learn DESIGN — System Architecture & Implementation Patterns
**Version:** 1.0  
**Tech Stack:** Tanstack Start + Drizzle ORM + Zustand + shadcn/ui + JWT  
**Date:** August 2026  
**Status:** Production-Ready

---

## TABLE OF CONTENTS

1. [Architecture Overview](#1-architecture-overview)
2. [API Design & Endpoints](#2-api-design--endpoints)
3. [Authentication & Sessions](#3-authentication--sessions)
4. [State Management (Zustand)](#4-state-management-zustand)
5. [Component Architecture](#5-component-architecture)
6. [Real-time Polling Strategy](#6-real-time-polling-strategy)
7. [Error Handling & Validation](#7-error-handling--validation)
8. [Performance Optimization](#8-performance-optimization)
9. [Testing Strategy](#9-testing-strategy)
10. [Deployment & Monitoring](#10-deployment--monitoring)

---

## 1. ARCHITECTURE OVERVIEW

### System Diagram

```
┌─────────────────────────────────────────────┐
│         Browser (React + TypeScript)        │
├─────────────────────────────────────────────┤
│  Teacher Dashboard      |    Student Board   │
│  ├─ Course CRUD         │    ├─ Join Screen │
│  ├─ Session Control     │    ├─ Status Taps │
│  ├─ Live Dashboard      │    └─ Auto-Reset  │
│  └─ Code Management     │                   │
└────────────┬────────────────────────────────┘
             │ HTTPS + JWT
             │ (Zustand + TanStack Query)
             ▼
┌─────────────────────────────────────────────┐
│    Tanstack Start (Node.js + Bun)           │
├─────────────────────────────────────────────┤
│  Modular Routes:                            │
│  ├─ /api/users/routes.ts (auth)             │
│  ├─ /api/courses/routes.ts (CRUD)           │
│  ├─ /api/sessions/routes.ts (control)       │
│  ├─ /api/join-codes/routes.ts (NEW)         │
│  ├─ /api/participants/routes.ts (join)      │
│  └─ /api/status-events/routes.ts (taps)     │
│                                             │
│  Middleware:                                │
│  ├─ Authentication (JWT validation)         │
│  ├─ Rate Limiting (adaptive)                │
│  ├─ Request Logging                         │
│  └─ Error Handling                          │
└────────────┬────────────────────────────────┘
             │ SQL Queries
             ▼
┌─────────────────────────────────────────────┐
│     MySQL (PlanetScale) + Drizzle ORM       │
├─────────────────────────────────────────────┤
│  8 Tables:                                  │
│  ├─ users                                   │
│  ├─ courses (soft-delete)                   │
│  ├─ course_sessions                         │
│  ├─ join_codes (NEW)                        │
│  ├─ participants                            │
│  ├─ status_events (append-only)             │
│  ├─ session_dashboard (denormalized)        │
│  └─ session_summaries (aggregate)           │
│                                             │
│  Caching:                                   │
│  └─ HTTP caching headers (ETag, Cache-Control)
└─────────────────────────────────────────────┘
```

### Key Design Decisions

1. **Tanstack Start (Fullstack)** — File-based routing, reduced complexity
2. **Modular API Routes** — `/api/courses/routes.ts`, `/api/sessions/routes.ts`, etc.
3. **JWT Tokens** — Stateless auth, easy horizontal scaling
4. **Zustand** — Lightweight state (teacher dashboard, UI modals)
5. **Custom Polling Hook** — useInterval for 2-5 sec dashboard updates
6. **HTTP Caching** — ETag for immutable resources (courses, sessions)
7. **Frontend Validation** — Fast feedback; API validates as source of truth
8. **GitHub Actions** — CI/CD pipeline with lint, test, deploy

---

## 2. API DESIGN & ENDPOINTS

### 2.1 Endpoint Organization (Resource-Focused)

**Route Structure:** `/api/[resource]/routes.ts`

```
src/routes/api/
├─ _middleware.ts               (global middleware)
├─ auth/
│  └─ routes.ts                 (Google OAuth callback)
├─ courses/
│  └─ routes.ts                 (CRUD: GET, POST, PATCH, DELETE)
├─ courses/[courseId]/sessions/
│  └─ routes.ts                 (Start/End session)
├─ courses/[courseId]/sessions/[sessionId]/codes/
│  └─ routes.ts                 (NEW: Generate, List, Revoke)
├─ courses/[courseId]/sessions/[sessionId]/participants/
│  └─ routes.ts                 (Join, List)
├─ courses/[courseId]/sessions/[sessionId]/status-summary/
│  └─ routes.ts                 (Real-time dashboard)
└─ courses/[courseId]/sessions/[sessionId]/summary/
   └─ routes.ts                 (Historical review)
```

### 2.2 Complete API Specification

#### Authentication

**POST /api/auth/google**
```typescript
// Google OAuth callback handler
Request:
  Body: { code: string, state: string }
  
Response (200 OK):
  {
    accessToken: "eyJhbGc...",
    refreshToken: "rt_...",
    user: {
      id: "uuid",
      email: "teacher@example.com",
      name: "Jane Teacher",
      role: "teacher"
    }
  }

Errors:
  400: Invalid code
  500: OAuth provider error
```

**POST /api/auth/logout**
```typescript
Request:
  Headers: { Authorization: "Bearer {token}" }
  
Response (200 OK):
  { message: "Logged out successfully" }
  
Errors:
  401: Unauthorized
```

#### Courses (Teacher)

**GET /api/courses**
```typescript
// List all courses for logged-in teacher
Request:
  Headers: { Authorization: "Bearer {token}" }
  Query: { status?: 'draft|active|completed', limit?: 20, offset?: 0 }
  
Response (200 OK):
  {
    data: [
      {
        id: "uuid",
        title: "Math 101",
        status: "completed",
        date: "2026-08-20",
        duration_minutes: 60,
        session_code: "SIGNAL-ABC-123",
        created_at: "2026-08-15T10:00:00Z"
      }
    ],
    total: 42,
    limit: 20,
    offset: 0
  }

HTTP Caching:
  Cache-Control: "public, max-age=300" (5 min)
  ETag: calculated from hash
```

**POST /api/courses**
```typescript
// Create new course
Request:
  Headers: { Authorization: "Bearer {token}" }
  Body: {
    title: "Algebra Basics",
    description: "Linear equations",
    date: "2026-08-20",
    start_time: "10:00:00",
    duration_minutes: 60,
    allow_anonymous: false
  }
  
Response (201 Created):
  {
    id: "uuid",
    instructor_id: "uuid",
    title: "Algebra Basics",
    session_code: "SIGNAL-XYZ-789",  // Auto-generated
    status: "draft",
    created_at: "2026-08-20T10:00:00Z"
  }

Validation:
  - title: required, 1-255 chars
  - duration_minutes: between 30 and 120
  - date: YYYY-MM-DD format, >= today
  
Errors:
  400: Validation failed
  401: Unauthorized
  500: Server error
```

**PATCH /api/courses/:courseId**
```typescript
// Update course (only before session starts)
Request:
  Headers: { Authorization: "Bearer {token}" }
  Body: {
    title?: "New Title",
    description?: "...",
    date?: "2026-08-21",
    start_time?: "14:00:00"
  }
  
Response (200 OK):
  { id, title, ... }

Errors:
  400: Cannot update active/completed course
  401: Unauthorized (must be instructor)
  404: Course not found
```

**DELETE /api/courses/:courseId**
```typescript
// Soft-delete course
Request:
  Headers: { Authorization: "Bearer {token}" }
  
Response (204 No Content):
  // Soft-deleted via deleted_at timestamp

Errors:
  401: Unauthorized
  404: Course not found
```

#### Sessions (Teacher Control)

**POST /api/courses/:courseId/sessions/:sessionId/start**
```typescript
// Start active session
Request:
  Headers: { Authorization: "Bearer {token}" }
  Body: {} (empty)
  
Response (200 OK):
  {
    session_id: "uuid",
    is_active: true,
    session_start_time: "2026-08-20T10:00:00Z",
    shareable_link: "https://signallearn.app/session/SIGNAL-ABC-123"
  }

Errors:
  400: Session already active
  401: Unauthorized
  404: Course not found
```

**POST /api/courses/:courseId/sessions/:sessionId/end**
```typescript
// End session + compute summary
Request:
  Headers: { Authorization: "Bearer {token}" }
  Body: {} (empty)
  
Response (200 OK):
  {
    session_id: "uuid",
    is_active: false,
    session_end_time: "2026-08-20T11:00:00Z",
    summary: {
      total_participants: 20,
      participants_via_link: 12,
      participants_via_code: 8,
      final_red_count: 3,
      final_yellow_count: 5,
      final_green_count: 12,
      duration_seconds: 3600
    }
  }

Side Effects:
  - SessionSummary record created
  - SessionDashboard record updated
  - is_active set to false
  
Errors:
  400: Session not active
  401: Unauthorized
  404: Session not found
```

**GET /api/courses/:courseId/sessions/:sessionId/status-summary**
```typescript
// Real-time dashboard counts (polled every 2-5 sec)
Request:
  Headers: { Authorization: "Bearer {token}" }
  Query: { session_id: "uuid" }
  
Response (200 OK):
  {
    session_id: "uuid",
    red_count: 3,
    yellow_count: 5,
    green_count: 12,
    total_participants: 20,
    active_participants: 18,
    elapsed_seconds: 945,
    last_updated: "2026-08-20T10:15:45Z"
  }

Performance:
  Execution: < 5ms (queries session_dashboard table, not StatusEvent)
  
HTTP Caching:
  Cache-Control: "no-cache, must-revalidate" (don't cache, always fresh)
  
Errors:
  401: Unauthorized
  404: Session not found
```

#### Join Codes (Teacher) [NEW]

**POST /api/courses/:courseId/sessions/:sessionId/codes**
```typescript
// Generate join code (auto or custom)
Request:
  Headers: { Authorization: "Bearer {token}" }
  Body: {
    code?: "MATH-101",      // Optional custom code
    auto_generate?: true     // If false, code is required
  }
  
Response (201 Created):
  {
    id: "uuid",
    session_id: "uuid",
    code: "MATH-101",
    is_custom: true,
    status: "active",
    generated_at: "2026-08-20T10:00:00Z",
    usage_count: 0
  }

Frontend Validation:
  - code format: 3-50 chars, alphanumeric + hyphens
  - Don't allow empty/whitespace
  
Server Validation:
  - code must be unique per session
  - Prevent duplicate codes via unique constraint
  
Errors:
  400: Code already exists for this session
  400: Invalid code format
  401: Unauthorized
  404: Session not found
```

**GET /api/courses/:courseId/sessions/:sessionId/codes**
```typescript
// List all codes for session
Request:
  Headers: { Authorization: "Bearer {token}" }
  
Response (200 OK):
  {
    data: [
      {
        id: "uuid",
        code: "MATH-101",
        status: "active",
        usage_count: 5,
        generated_at: "2026-08-20T10:00:00Z",
        revoked_at: null
      },
      {
        id: "uuid",
        code: "LATE-JOIN",
        status: "revoked",
        usage_count: 2,
        generated_at: "2026-08-20T10:05:00Z",
        revoked_at: "2026-08-20T10:10:00Z"
      }
    ]
  }

Errors:
  401: Unauthorized
  404: Session not found
```

**PATCH /api/courses/:courseId/sessions/:sessionId/codes/:codeId**
```typescript
// Revoke or reactivate code
Request:
  Headers: { Authorization: "Bearer {token}" }
  Body: {
    status: "revoked" | "active"
  }
  
Response (200 OK):
  {
    id: "uuid",
    code: "MATH-101",
    status: "revoked",
    revoked_at: "2026-08-20T10:30:00Z"
  }

Notes:
  - Revoked code prevents NEW joins
  - Students already joined via code stay in session
  - Can revoke mid-session
  
Errors:
  400: Invalid status
  401: Unauthorized
  404: Code not found
```

#### Student Join (No Auth)

**POST /api/join-by-code**
```typescript
// Student joins via code
Request:
  Body: {
    code: "MATH-101",
    name?: "Alice"              // Optional if allow_anonymous=true
  }
  
Response (200 OK):
  {
    participant_id: "uuid",
    session_info: {
      course_title: "Math 101",
      instructor_name: "Jane Teacher",
      duration_minutes: 60,
      allow_anonymous: false
    }
  }

Server Validation:
  1. Code exists + status='active'
  2. Session is active
  3. Name required if allow_anonymous=false
  
Errors:
  400: Code not found or revoked
  400: Session not active
  400: Name required
  500: Server error
```

**POST /api/join-by-link**
```typescript
// Student joins via direct link
Request:
  Body: {
    session_code: "SIGNAL-ABC-123",
    name?: "Alice"
  }
  
Response (200 OK):
  {
    participant_id: "uuid",
    session_info: { ... }
  }

Errors:
  400: Session code not found
  400: Session not active
```

#### Status Events (Student - High Volume)

**POST /api/status-events**
```typescript
// Student taps status (Red/Yellow/Green)
Request:
  Body: {
    participant_id: "uuid",
    status: "red" | "yellow" | "green"
  }
  
Response (200 OK):
  {
    event_id: "uuid",
    participant_id: "uuid",
    status: "red",
    triggered_at: "2026-08-20T10:15:30Z",
    auto_reset_at: "2026-08-20T10:20:30Z"
  }

Rate Limiting:
  Adaptive: Based on current load
  Per-participant: Max 1 request/sec
  Fallback: No more than 60/min per participant
  
Server Validation:
  - participant exists + is_active
  - session is active
  - status is valid enum
  
Side Effects:
  1. StatusEvent inserted (append-only)
  2. SessionDashboard updated (denormalized counts)
  3. Dashboard query within milliseconds reflects change
  
Errors:
  400: Invalid status
  404: Participant not found
  429: Rate limited
```

---

## 3. AUTHENTICATION & SESSIONS

### 3.1 JWT Strategy

**Token Structure:**

```typescript
// Payload
{
  sub: "user_id",  // Subject (user ID)
  email: "teacher@example.com",
  role: "teacher" | "admin",
  iat: 1661234567,    // Issued at
  exp: 1661238167,    // Expires in (1 hour)
  iss: "signallearn"
}
```

**Token Lifecycle:**

```typescript
// src/server/utils/jwt.ts

export async function generateTokens(userId: string, email: string, role: string) {
  const accessToken = jwt.sign(
    { sub: userId, email, role },
    process.env.JWT_SECRET!,
    { expiresIn: '1h', issuer: 'signallearn' }
  );

  const refreshToken = jwt.sign(
    { sub: userId },
    process.env.JWT_REFRESH_SECRET!,
    { expiresIn: '7d', issuer: 'signallearn' }
  );

  return { accessToken, refreshToken };
}

export async function verifyToken(token: string) {
  try {
    return jwt.verify(token, process.env.JWT_SECRET!);
  } catch (error) {
    throw new Error('Invalid token');
  }
}
```

**Middleware Implementation:**

```typescript
// src/routes/api/_middleware.ts

export async function middleware(req: Request) {
  const authHeader = req.headers.get('authorization');
  const token = authHeader?.replace('Bearer ', '');

  if (!token) {
    // Public endpoints: /join-by-code, /join-by-link, /status-events don't require auth
    // Protected endpoints: all teacher APIs require auth
    return;
  }

  try {
    const payload = verifyToken(token);
    req.user = {
      id: payload.sub,
      email: payload.email,
      role: payload.role,
    };
  } catch {
    throw new Error('Unauthorized');
  }
}
```

### 3.2 Google OAuth Flow

**Step-by-Step:**

```typescript
// 1. Frontend initiates OAuth
// Button click → Redirects to Google OAuth consent screen

// 2. User approves → Google redirects to /api/auth/google?code=...&state=...

// 3. Backend exchanges code for tokens
export async function POST(req: Request) {
  const { code } = await req.json();
  
  // Exchange code for access token
  const tokens = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    body: {
      code,
      client_id: process.env.GOOGLE_CLIENT_ID,
      client_secret: process.env.GOOGLE_CLIENT_SECRET,
      redirect_uri: 'https://signallearn.app/api/auth/google',
      grant_type: 'authorization_code',
    },
  });

  // Get user info from Google
  const { id_token } = tokens;
  const userInfo = jwt.decode(id_token); // { sub, email, name, picture }

  // Upsert user in DB
  let user = await db
    .select()
    .from(users)
    .where(eq(users.google_id, userInfo.sub));

  if (!user) {
    user = await db
      .insert(users)
      .values({
        id: generateUUID(),
        google_id: userInfo.sub,
        email: userInfo.email,
        name: userInfo.name,
        profile_picture_url: userInfo.picture,
      })
      .returning();
  }

  // Issue our own tokens
  const { accessToken, refreshToken } = generateTokens(
    user.id,
    user.email,
    user.role
  );

  // Return tokens (frontend stores in localStorage or secure cookie)
  return Response.json({ accessToken, refreshToken, user });
}
```

**Storage:**

Frontend stores tokens securely:
```typescript
// Option 1: localStorage (fast, XSS risk if not careful)
localStorage.setItem('accessToken', token);

// Option 2: HttpOnly cookie (more secure, but less accessible to JS)
// Set by server on Set-Cookie header
```

---

## 4. STATE MANAGEMENT (ZUSTAND)

### 4.1 Store Structure

**File:** `src/stores/dashboardStore.ts`

```typescript
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';

interface SessionStatus {
  sessionId: string;
  redCount: number;
  yellowCount: number;
  greenCount: number;
  totalParticipants: number;
  activeParticipants: number;
  elapsedSeconds: number;
  lastUpdated: Date;
}

interface DashboardState {
  // State
  activeSessions: Map<string, SessionStatus>;
  selectedSessionId: string | null;
  isPolling: boolean;
  pollingError: Error | null;

  // Actions
  updateSessionStatus: (status: SessionStatus) => void;
  selectSession: (sessionId: string) => void;
  startPolling: () => void;
  stopPolling: () => void;
  setPollingError: (error: Error | null) => void;
  clearSessions: () => void;
}

export const useDashboardStore = create<DashboardState>()(
  subscribeWithSelector((set) => ({
    activeSessions: new Map(),
    selectedSessionId: null,
    isPolling: false,
    pollingError: null,

    updateSessionStatus: (status) =>
      set((state) => {
        const newSessions = new Map(state.activeSessions);
        newSessions.set(status.sessionId, status);
        return { activeSessions: newSessions };
      }),

    selectSession: (sessionId) => set({ selectedSessionId: sessionId }),

    startPolling: () => set({ isPolling: true, pollingError: null }),

    stopPolling: () => set({ isPolling: false }),

    setPollingError: (error) => set({ pollingError: error }),

    clearSessions: () =>
      set({ activeSessions: new Map(), selectedSessionId: null }),
  }))
);
```

**File:** `src/stores/uiStore.ts`

```typescript
interface UIState {
  // Modals
  isCodeModalOpen: boolean;
  isConfirmDialogOpen: boolean;
  confirmAction: (() => void) | null;

  // Notifications
  toasts: Array<{ id: string; type: 'success' | 'error'; message: string }>;

  // Actions
  openCodeModal: () => void;
  closeCodeModal: () => void;
  openConfirmDialog: (action: () => void) => void;
  closeConfirmDialog: () => void;
  addToast: (type: string, message: string) => void;
  removeToast: (id: string) => void;
}

export const useUIStore = create<UIState>((set) => ({
  isCodeModalOpen: false,
  isConfirmDialogOpen: false,
  confirmAction: null,
  toasts: [],

  openCodeModal: () => set({ isCodeModalOpen: true }),
  closeCodeModal: () => set({ isCodeModalOpen: false }),

  openConfirmDialog: (action) =>
    set({ isConfirmDialogOpen: true, confirmAction: action }),

  closeConfirmDialog: () =>
    set({ isConfirmDialogOpen: false, confirmAction: null }),

  addToast: (type, message) =>
    set((state) => ({
      toasts: [
        ...state.toasts,
        { id: crypto.randomUUID(), type, message },
      ],
    })),

  removeToast: (id) =>
    set((state) => ({
      toasts: state.toasts.filter((toast) => toast.id !== id),
    })),
}));
```

### 4.2 Using Zustand in Components

```typescript
// src/components/TeacherDashboard.tsx

export function TeacherDashboard() {
  const selectedSessionId = useDashboardStore(
    (state) => state.selectedSessionId
  );
  const status = useDashboardStore(
    (state) => state.activeSessions.get(selectedSessionId || '')
  );
  const selectSession = useDashboardStore((state) => state.selectSession);

  return (
    <div>
      <h1>Dashboard</h1>
      {status && (
        <div className="grid grid-cols-3 gap-4">
          <div className="bg-red-500 p-4 text-white">
            <div className="text-2xl font-bold">{status.redCount}</div>
            <div>Need Help</div>
          </div>
          {/* Yellow and Green cards */}
        </div>
      )}
    </div>
  );
}
```

---

## 5. COMPONENT ARCHITECTURE

### 5.1 shadcn/ui Component Structure

**Installation:**

```bash
npx shadcn-ui@latest init
# Choose: TypeScript, CSS Modules, Tailwind, Bun

npx shadcn-ui@latest add button
npx shadcn-ui@latest add input
npx shadcn-ui@latest add dialog
npx shadcn-ui@latest add card
npx shadcn-ui@latest add badge
# etc...
```

**File Structure:**

```
src/components/
├─ ui/                      (shadcn/ui components - copy-paste)
│  ├─ button.tsx
│  ├─ input.tsx
│  ├─ dialog.tsx
│  ├─ card.tsx
│  ├─ badge.tsx
│  └─ ...
│
├─ auth/                    (Auth-related components)
│  ├─ GoogleLoginButton.tsx
│  └─ LoginPage.tsx
│
├─ teacher/                 (Teacher-specific components)
│  ├─ DashboardLayout.tsx
│  ├─ StatusSummary.tsx
│  ├─ CodeManagement.tsx
│  ├─ CodeGeneratorModal.tsx
│  └─ SessionTimer.tsx
│
├─ student/                 (Student-specific components)
│  ├─ JoinScreen.tsx
│  ├─ StatusButtons.tsx
│  ├─ CountdownTimer.tsx
│  └─ SessionInfo.tsx
│
├─ shared/                  (Reusable components)
│  ├─ Navbar.tsx
│  ├─ Footer.tsx
│  ├─ Toast.tsx
│  ├─ ConfirmDialog.tsx
│  └─ LoadingSpinner.tsx
│
└─ hooks/                   (Custom hooks)
   ├─ usePolling.ts         (2-5 sec dashboard polling)
   ├─ useAuth.ts            (Authentication wrapper)
   ├─ useFetch.ts           (API request wrapper)
   └─ useCountdown.ts       (5-min auto-reset timer)
```

### 5.2 Key Components

**Teacher Dashboard (StatusSummary):**

```typescript
// src/components/teacher/StatusSummary.tsx

import { useDashboardStore } from '@/stores/dashboardStore';

export function StatusSummary() {
  const selectedSessionId = useDashboardStore(
    (state) => state.selectedSessionId
  );
  const status = useDashboardStore(
    (state) => state.activeSessions.get(selectedSessionId || '')
  );

  if (!status) return <div>No session selected</div>;

  return (
    <div className="grid grid-cols-3 gap-4 p-6">
      {/* Red Card */}
      <div className="bg-red-100 border-l-4 border-red-500 p-4">
        <div className="text-sm font-semibold text-red-700">RED</div>
        <div className="text-4xl font-bold text-red-600">{status.redCount}</div>
        <div className="text-xs text-red-600">Need Help</div>
      </div>

      {/* Yellow Card */}
      <div className="bg-yellow-100 border-l-4 border-yellow-500 p-4">
        <div className="text-sm font-semibold text-yellow-700">YELLOW</div>
        <div className="text-4xl font-bold text-yellow-600">
          {status.yellowCount}
        </div>
        <div className="text-xs text-yellow-600">Have Questions</div>
      </div>

      {/* Green Card */}
      <div className="bg-green-100 border-l-4 border-green-500 p-4">
        <div className="text-sm font-semibold text-green-700">GREEN</div>
        <div className="text-4xl font-bold text-green-600">
          {status.greenCount}
        </div>
        <div className="text-xs text-green-600">Doing Well</div>
      </div>
    </div>
  );
}
```

**Student Status Buttons:**

```typescript
// src/components/student/StatusButtons.tsx

import { useState } from 'react';
import { Button } from '@/components/ui/button';

interface StatusButtonsProps {
  participantId: string;
  onStatusChange: (status: 'red' | 'yellow' | 'green') => Promise<void>;
}

export function StatusButtons({ participantId, onStatusChange }: StatusButtonsProps) {
  const [selectedStatus, setSelectedStatus] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);

  const handleStatusTap = async (status: 'red' | 'yellow' | 'green') => {
    setIsLoading(true);
    try {
      await onStatusChange(status);
      setSelectedStatus(status);
    } catch (error) {
      console.error('Failed to update status:', error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="flex gap-4 justify-center py-8">
      {(['green', 'yellow', 'red'] as const).map((status) => (
        <Button
          key={status}
          size="lg"
          className={`w-24 h-24 rounded-full text-2xl ${
            status === 'green' ? 'bg-green-500 hover:bg-green-600' :
            status === 'yellow' ? 'bg-yellow-400 hover:bg-yellow-500' :
            'bg-red-500 hover:bg-red-600'
          } ${selectedStatus === status ? 'ring-4 ring-offset-2' : ''}`}
          disabled={isLoading}
          onClick={() => handleStatusTap(status)}
        >
          {status === 'green' ? '✓' : status === 'yellow' ? '?' : '!'}
        </Button>
      ))}
    </div>
  );
}
```

---

## 6. REAL-TIME POLLING STRATEGY

### 6.1 Custom usePolling Hook

**File:** `src/hooks/usePolling.ts`

```typescript
import { useEffect, useRef } from 'react';
import { useDashboardStore } from '@/stores/dashboardStore';

export function usePolling(sessionId: string | null, interval: number = 3000) {
  const intervalRef = useRef<NodeJS.Timeout | null>(null);
  const isPolling = useDashboardStore((state) => state.isPolling);
  const updateSessionStatus = useDashboardStore(
    (state) => state.updateSessionStatus
  );
  const startPolling = useDashboardStore((state) => state.startPolling);
  const stopPolling = useDashboardStore((state) => state.stopPolling);
  const setPollingError = useDashboardStore((state) => state.setPollingError);

  useEffect(() => {
    if (!sessionId || !isPolling) return;

    const poll = async () => {
      try {
        const response = await fetch(
          `/api/courses/xxx/sessions/${sessionId}/status-summary`,
          {
            headers: {
              'Authorization': `Bearer ${localStorage.getItem('accessToken')}`,
            },
          }
        );

        if (!response.ok) throw new Error('Poll failed');

        const status = await response.json();
        updateSessionStatus(status);
        setPollingError(null);
      } catch (error) {
        setPollingError(
          error instanceof Error ? error : new Error('Unknown error')
        );
      }
    };

    // Poll immediately on start
    poll();

    // Then poll at interval
    intervalRef.current = setInterval(poll, interval);

    return () => {
      if (intervalRef.current) clearInterval(intervalRef.current);
    };
  }, [sessionId, isPolling, interval, updateSessionStatus, setPollingError]);
}
```

**Usage in Dashboard:**

```typescript
export function TeacherDashboard() {
  const selectedSessionId = useDashboardStore(
    (state) => state.selectedSessionId
  );
  const isPolling = useDashboardStore((state) => state.isPolling);
  const startPolling = useDashboardStore((state) => state.startPolling);
  const stopPolling = useDashboardStore((state) => state.stopPolling);

  // Start polling when session selected
  useEffect(() => {
    if (selectedSessionId) {
      startPolling();
    } else {
      stopPolling();
    }
  }, [selectedSessionId]);

  // Poll every 3 seconds
  usePolling(selectedSessionId, 3000);

  return (
    <div>
      <StatusSummary />
      {isPolling && <div className="text-sm text-gray-600">Polling...</div>}
    </div>
  );
}
```

### 6.2 HTTP Caching Headers

**API Response Headers:**

```typescript
// src/routes/api/courses/[courseId]/sessions/[sessionId]/status-summary/routes.ts

export async function GET(req: Request) {
  // ... fetch dashboard data

  return Response.json(status, {
    headers: {
      'Cache-Control': 'no-cache, must-revalidate, max-age=0',
      'ETag': `"${generateHash(status)}"`,
    },
  });
}
```

**Frontend Caching:**

```typescript
// TanStack Query (if using instead of manual fetch)
const query = useQuery({
  queryKey: ['session-status', sessionId],
  queryFn: async () => {
    const res = await fetch(`/api/sessions/${sessionId}/status-summary`, {
      headers: { 'Authorization': `Bearer ${token}` },
    });
    return res.json();
  },
  staleTime: 2000,      // Consider fresh for 2 sec
  refetchInterval: 3000, // Refetch every 3 sec
  refetchOnWindowFocus: false,
});
```

---

## 7. ERROR HANDLING & VALIDATION

### 7.1 Frontend Validation

**Join Code Input:**

```typescript
// src/components/student/JoinCodeInput.tsx

import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

export function JoinCodeInput() {
  const [code, setCode] = useState('');
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [isLoading, setIsLoading] = useState(false);

  const validate = (value: string) => {
    const newErrors: Record<string, string> = {};

    if (!value) {
      newErrors.code = 'Code is required';
    } else if (value.length < 3) {
      newErrors.code = 'Code must be at least 3 characters';
    } else if (!/^[a-zA-Z0-9-]+$/.test(value)) {
      newErrors.code = 'Code can only contain letters, numbers, and hyphens';
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!validate(code)) return;

    setIsLoading(true);
    try {
      const response = await fetch('/api/join-by-code', {
        method: 'POST',
        body: JSON.stringify({ code: code.toUpperCase() }),
      });

      if (!response.ok) {
        const error = await response.json();
        setErrors({ code: error.message || 'Code not found' });
        return;
      }

      // Success - redirect to status board
      window.location.href = '/session';
    } catch (error) {
      setErrors({ code: 'Network error - please try again' });
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <Input
        type="text"
        placeholder="Enter join code"
        value={code}
        onChange={(e) => setCode(e.target.value)}
        className={errors.code ? 'border-red-500' : ''}
      />
      {errors.code && <div className="text-red-600 text-sm">{errors.code}</div>}
      <Button type="submit" disabled={isLoading} className="w-full">
        {isLoading ? 'Joining...' : 'Join'}
      </Button>
    </form>
  );
}
```

### 7.2 API Error Responses

**Standardized Error Format:**

```typescript
// src/server/utils/errors.ts

export class APIError extends Error {
  constructor(
    public statusCode: number,
    public code: string,
    message: string
  ) {
    super(message);
  }
}

export function errorResponse(error: unknown) {
  if (error instanceof APIError) {
    return Response.json(
      { code: error.code, message: error.message },
      { status: error.statusCode }
    );
  }

  console.error('Unhandled error:', error);
  return Response.json(
    { code: 'INTERNAL_ERROR', message: 'Internal server error' },
    { status: 500 }
  );
}
```

**Using in Route Handler:**

```typescript
// src/routes/api/join-by-code/routes.ts

export async function POST(req: Request) {
  try {
    const { code, name } = await req.json();

    // Validate input
    if (!code) {
      throw new APIError(400, 'MISSING_CODE', 'Code is required');
    }

    // Check code exists and is active
    const joinCode = await db
      .select()
      .from(joinCodes)
      .where(and(eq(joinCodes.code, code), eq(joinCodes.status, 'active')))
      .limit(1);

    if (!joinCode.length) {
      throw new APIError(400, 'INVALID_CODE', 'Code not found or revoked');
    }

    // ... rest of logic

    return Response.json({ participant_id, session_info });
  } catch (error) {
    return errorResponse(error);
  }
}
```

---

## 8. PERFORMANCE OPTIMIZATION

### 8.1 Image Optimization

**Profile Pictures (Google):**

```typescript
// Cache Google profile pictures at edge
export async function GET(req: Request, { params }: RouteParams) {
  const userId = params.userId;
  const user = await db.select().from(users).where(eq(users.id, userId));

  return Response.redirect(user.profile_picture_url, {
    headers: {
      'Cache-Control': 'public, max-age=2592000', // 30 days
    },
  });
}
```

### 8.2 Code Splitting

**Route-based Splitting:**

```typescript
// src/routes/teacher/dashboard.tsx
// This chunk only loads when teacher navigates to dashboard

export lazy(() => import('./components/TeacherDashboard'));

// src/routes/student/join.tsx
// This chunk only loads when student navigates to join
```

### 8.3 Debouncing Updates

```typescript
// Debounce dashboard polling to avoid thundering herd
import { debounce } from 'lodash-es';

const debouncedUpdateDashboard = debounce(
  (sessionId: string) => {
    return fetch(`/api/sessions/${sessionId}/status-summary`);
  },
  1000,
  { maxWait: 5000 }
);
```

---

## 9. TESTING STRATEGY

### 9.1 Test File Structure

```
src/
├─ routes/
│  └─ api/
│     ├─ courses/
│     │  ├─ routes.ts
│     │  └─ routes.test.ts        (Same file, test included)
│     ├─ join-codes/
│     │  ├─ routes.ts
│     │  └─ routes.test.ts
│     └─ ...
│
└─ components/
   ├─ teacher/
   │  ├─ StatusSummary.tsx
   │  └─ StatusSummary.test.tsx
   └─ ...
```

### 9.2 Example API Test

**File:** `src/routes/api/join-codes/routes.test.ts`

```typescript
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { db } from '@/server/db';
import { courses, courseSessions, joinCodes } from '@/server/db/schema';
import { POST } from './routes';

describe('POST /api/courses/:id/sessions/:id/codes', () => {
  let courseId: string;
  let sessionId: string;

  beforeAll(async () => {
    // Setup test data
    courseId = 'test-course-id';
    sessionId = 'test-session-id';
  });

  afterAll(async () => {
    // Cleanup
    await db.delete(joinCodes).where(eq(joinCodes.session_id, sessionId));
  });

  it('should generate auto code successfully', async () => {
    const req = new Request('http://localhost:3000/api/courses/123/sessions/456/codes', {
      method: 'POST',
      body: JSON.stringify({ auto_generate: true }),
      headers: { 'Authorization': `Bearer test-token` },
    });

    const res = await POST(req);
    const data = await res.json();

    expect(res.status).toBe(201);
    expect(data.code).toMatch(/^SIGNAL-[A-Z0-9]{3}-[A-Z0-9]{3}$/);
  });

  it('should prevent duplicate codes in same session', async () => {
    const req = new Request('http://localhost:3000/api/courses/123/sessions/456/codes', {
      method: 'POST',
      body: JSON.stringify({ code: 'MATH-101' }),
      headers: { 'Authorization': `Bearer test-token` },
    });

    // First request
    const res1 = await POST(req);
    expect(res1.status).toBe(201);

    // Second request with same code
    const res2 = await POST(req);
    expect(res2.status).toBe(400);
    const error = await res2.json();
    expect(error.code).toBe('CODE_EXISTS');
  });

  it('should validate code format', async () => {
    const req = new Request('http://localhost:3000/api/courses/123/sessions/456/codes', {
      method: 'POST',
      body: JSON.stringify({ code: '@#$%' }), // Invalid
      headers: { 'Authorization': `Bearer test-token` },
    });

    const res = await POST(req);
    expect(res.status).toBe(400);
  });
});
```

---

## 10. DEPLOYMENT & MONITORING

### 10.1 GitHub Actions CI/CD

**File:** `.github/workflows/deploy.yml`

```yaml
name: Deploy

on:
  push:
    branches: [main]

env:
  DATABASE_URL: ${{ secrets.DATABASE_URL }}
  JWT_SECRET: ${{ secrets.JWT_SECRET }}
  GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
  GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}

jobs:
  test-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1

      - name: Install dependencies
        run: bun install

      - name: Run tests
        run: bun test

      - name: Lint
        run: bun run lint

      - name: Build
        run: bun run build

      - name: Deploy to Cloudflare Workers
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
        run: bun run deploy

      - name: Run smoke tests
        run: bun run test:smoke
```

### 10.2 Monitoring & Logging

**Console-based Logging (Development):**

```typescript
// src/server/utils/logger.ts

export function log(level: 'info' | 'error' | 'warn', message: string, data?: any) {
  const timestamp = new Date().toISOString();
  console.log(
    JSON.stringify({
      timestamp,
      level,
      message,
      data,
    })
  );
}

// Usage in API routes
export async function POST(req: Request) {
  try {
    log('info', 'Generating join code', { sessionId });
    // ... code
  } catch (error) {
    log('error', 'Failed to generate join code', { error });
  }
}
```

**Uptime Monitoring:**

```bash
# Set up a simple endpoint for uptime monitoring
curl https://signallearn.app/api/health

# Response: { status: 'ok', timestamp: '...' }
```

---

## SUMMARY

**Architecture Decisions:**
- ✅ Tanstack Start (fullstack, minimal setup)
- ✅ Modular API routes (organized by resource)
- ✅ Zustand (lightweight state for UI)
- ✅ JWT tokens (stateless auth)
- ✅ Custom polling hook (2-5 sec updates)
- ✅ Frontend validation (fast feedback)
- ✅ HTTP caching (ETag, Cache-Control)
- ✅ Comprehensive error handling
- ✅ Full test coverage (all routes)
- ✅ GitHub Actions CI/CD

**Performance Targets:**
- ✅ Dashboard query: < 5ms
- ✅ Status update: < 200ms
- ✅ Polling latency: 2-5 seconds
- ✅ Code generation: < 100ms
- ✅ Page load: < 2 seconds

**Security:**
- ✅ JWT tokens + stateless auth
- ✅ CORS configured
- ✅ Rate limiting (adaptive)
- ✅ Input validation (frontend + API)
- ✅ SQL injection prevention (Drizzle ORM)

---

**Status:** ✅ Production-Ready for Tanstack Start + Drizzle + Zustand + shadcn/ui  
**Ready for:** Developers to start building immediately
