Wordloop Platform
Platform ServicesApp (Next.js)

App Architecture Rules

Frontend Architecture & Codebase Conventions for Wordloop App

Architecture Rules: App Service (Next.js)

wordloop-app is a Next.js 16 App Router application. While frontend frameworks dictate specific file-system routing, we still deeply adhere to our overarching Service Architecture Principles by mapping Hexagonal concepts to our React file tree. Strict adherence to these boundaries is mandatory.

1. Core Tooling

  • Package Manager: Use pnpm exclusively.
  • Component Testing: Use Vitest and React Testing Library. All asynchronous state mutations must be wrapped in act(...) to prevent race conditions.
  • Icons: Use lucide-react exclusively.
  • Tailwind v4: No tailwind.config.ts. All configuration sits in app/globals.css using @theme blocks.

2. Inward Dependencies & Routing (The Ports & Adapters Mapping)

The codebase follows a strict inward-facing dependency graph.

  • Entrypoints (app/): React Server Components (RSC) act as the primary inbound adapters, parsing URL parameters and streaming Server Actions.
  • UI & Features (components/): Client and Server components. Cannot house business logic APIs.
  • Service/Domain (hooks/ & lib/core/): Local state execution, custom hooks, and pure utilities.
  • Providers (lib/providers/): Secondary adapters. Schemas (Zod) and API generated clients that reach out to our backend. Cannot import from components/ or app/.

3. The Backend API Proxy

To ensure environment-agnostic Docker deployments without build-time variable inlining:

  • All Orval-generated Next.js clients fetch relative URLs (/api/...).
  • A Next.js Route Handler interceptor (app/api/[...proxy]/route.ts) acts as a server-side reverse proxy.
  • It proxies incoming requests to the URL specified by CORE_API_URL at runtime.

4. Authentication (Clerk)

  • Identity: We utilize @clerk/nextjs for all interactive flows.
  • Token passing: The Orval fetcher instance intercepts requests to /api/... and injects the Clerk JWT inside the Authorization header.

5. State & Data Validation

  • Server Actions: All mutations use React Server Actions returning the Result pattern ({ data: T, error: string | null }).
  • Zod Schemas: API contracts dictate the interface. Do not write handwritten TypeScript definitions. Always z.infer from the generated Zod schemas.
  • Exhaustive Matching: switch statements must terminate with an exhaustive default: never check.

On this page