MOOC Utils

Utils like auto assignment solver extension and course notice announcment notification for MOOC courses

API integration

Introduction#

How the Next.js site calls the Notice Reminders API: client setup, cookies, React Query keys, and error handling.

Project structure#

The integration spans two primary areas:

  • Frontend API client and types: located under website/lib
  • Backend API routers and schemas: located under notice-reminders/app/api/routers and notice-reminders/app/schemas

Core components#

  • API client: centralized request wrapper with consistent headers, credentials, and error handling.
  • Endpoint functions: typed wrappers for each backend route.
  • TypeScript interfaces: strict data contracts mirroring backend schemas.
  • Authentication context: OTP-based session lifecycle and cookie-based auth propagation.
  • Backend routers: FastAPI endpoints implementing CRUD and orchestration.

Key responsibilities:

  • API client enforces JSON content type, includes credentials, and normalizes errors.
  • Endpoint functions encapsulate URL construction, HTTP verbs, and body serialization.
  • Types define request/response shapes and guard against runtime mismatches.
  • Auth context manages session hydration, OTP requests/verification, refresh, and logout.
  • Backend routers validate inputs, enforce permissions, and return Pydantic models.

Architecture overview#

The frontend communicates with the backend via HTTPS endpoints. The backend uses cookies for session management and CORS for cross-origin support. The frontend’s API client centralizes request configuration and error handling.

Detailed component analysis#

API client implementation#

The API client defines a generic request function and typed endpoint functions. It:

  • Sets base URL from environment.
  • Sends credentials with each request.
  • Enforces JSON content type.
  • Parses successful responses and handles 204 No Content.
  • Converts non-OK responses into a structured APIError with status and message.

Request/Response handling and error management#

  • Successful responses are parsed as JSON; 204 returns undefined.
  • Non-OK responses trigger APIError with status and detail.
  • The client does not implement retries or exponential backoff; these can be added at call sites if needed.

Recommendations:

  • Add retry logic with jitter for transient failures.
  • Implement rate-limit-aware backoff and queueing.
  • Surface easy to use messages while preserving error details.

TypeScript interfaces and data transformation#

Frontend types mirror backend schemas. The backend validates and serializes responses using Pydantic models. The frontend consumes these as strongly typed interfaces.

Authentication headers and session cookies#

  • The API client sends credentials with each request, enabling cookie-based session handling.
  • Backend sets HttpOnly, SameSite lax cookies for access and refresh tokens.
  • The frontend relies on the backend to manage session state via cookies.

Request interceptors and response parsing#

  • Interceptor pattern: a single request wrapper applies headers and credentials uniformly.
  • Response parsing: JSON parsing with 204 handling; errors normalized into APIError.

Possible follow-ups:

  • Add request/response logging for debugging.
  • Introduce a thin interceptor layer around fetch to centralize retry/backoff and rate-limit handling.

API endpoint specifications#

Below are the endpoint groups and their functions exposed by the frontend client and implemented by the backend.

  • Users

  • GET /users/{user_id}

  • PATCH /users/{user_id}

  • DELETE /users/{user_id}

  • POST /users/{user_id}/channels

  • GET /users/{user_id}/channels

  • Auth

  • POST /auth/request-otp

  • POST /auth/verify-otp

  • POST /auth/refresh

  • POST /auth/logout

  • GET /auth/me

  • Courses

  • GET /courses

  • GET /courses/{course_code}

  • Search

  • GET /search?q={query}

  • Announcements

  • GET /courses/{course_code}/announcements

  • Subscriptions

  • POST /subscriptions

  • GET /subscriptions

  • DELETE /subscriptions/{subscription_id}

  • Notifications

  • GET /notifications

  • GET /notifications/users/{user_id}

  • PATCH /notifications/{notification_id}/read

Note: All endpoints are protected by authentication where indicated. The frontend client wraps these in typed functions.

Parameter validation and error boundary handling#

  • Backend validation:
  • Pydantic models validate incoming payloads (e.g., email format, required fields).
  • Route-level checks enforce ownership and existence (e.g., 403 for unauthorized access, 404 for missing resources).
  • Frontend error boundaries:
  • APIError carries status and message; wrap calls in try/catch and surface easy to use messages.
  • Consider adding global error handlers to unify toast/snackbar notifications.

Rate limiting, retry logic, and offline handling#

Current client behavior:

  • No built-in rate-limit awareness or retry logic.
  • Uses standard fetch with credentials and JSON.

Recommended improvements:

  • Rate limiting:
  • Track recent request counts per time window.
  • Back off on 429 responses; parse Retry-After header if present.
  • Retry logic:
  • Retry transient network errors and 5xx responses with exponential backoff and jitter.
  • Idempotency keys for idempotent operations.
  • Offline handling:
  • Queue requests when offline; replay on reconnect.
  • Use service workers or local storage to persist pending mutations.
  • Show optimistic updates with rollback on failure.

Dependency analysis#

The frontend API client depends on:

  • Environment variable for base URL.
  • Typed interfaces for request/response shapes.
  • Auth context for session lifecycle.

The backend depends on:

  • Pydantic schemas for validation.
  • FastAPI routers for routing and dependency injection.
  • Cookie-based auth for session management.

Performance considerations#

  • Minimize redundant requests by coalescing frequent reads (e.g., deduplicate search queries).
  • Paginate long lists (notifications, subscriptions) to reduce payload sizes.
  • Cache immutable data (courses) locally with expiry to reduce network usage.
  • Use background refetch strategies to keep data fresh without blocking UI.

Troubleshooting guide#

Common issues and resolutions:

  • Authentication failures:
  • Verify cookies are being sent; ensure SameSite/Lax compatibility.
  • On 401/403, redirect to login or refresh session.
  • Network errors:
  • Wrap API calls in try/catch; display easy to use messages.
  • Implement retry with backoff for transient failures.
  • Backend validation errors:
  • Inspect APIError status and message; show specific field errors when available.
  • CORS issues:
  • Confirm backend allows frontend origin and credentials.

Conclusion#

Credentials include cookies; React Query owns cache keys. Fix CORS and base URL before rewriting fetch wrappers.