Skip to main content

Web App Architecture

The Ever Works web dashboard (apps/web/) is a Next.js 16 application using the App Router with React 19. This page covers its internal architecture, component model, data flow, and internationalization approach.

Application Layout

apps/web/
src/
app/ # Next.js App Router pages
[locale]/ # Dynamic locale segment
(auth)/ # Route group: authentication pages
(dashboard)/ # Route group: protected dashboard pages
actions/ # Server Actions
api/ # API route handlers
components/ # React components by feature area
i18n/ # Internationalization config
lib/ # Utilities, hooks, API clients, constants
proxy.ts # Middleware (auth + i18n)
global.ts # Global type augmentations
messages/ # Translation JSON files per locale
public/ # Static assets (logos, favicons)
next.config.ts # Next.js configuration

Server and Client Components

The dashboard follows the React Server Components (RSC) model:

  • Server components (default) -- pages and layouts fetch data on the server without shipping JavaScript to the client. Most page-level components are server components.
  • Client components ('use client') -- interactive components that use React hooks, event handlers, or browser APIs are marked with the 'use client' directive.

Convention

// Server component (default) -- page.tsx
export default async function WorksPage() {
const works = await fetchWorks(); // Server-side data fetch
return <WorkList works={works} />;
}

// Client component -- WorkCard.tsx
'use client';
export function WorkCard({ work }) {
const [expanded, setExpanded] = useState(false);
// Interactive UI with event handlers
}

Routing

Locale Routing

All pages are nested under app/[locale]/, enabling URL-based locale switching. The next-intl middleware detects the locale from the URL prefix, cookie, or Accept-Language header.

Supported locales are defined in lib/constants.ts (21 locales) and registered in i18n/routing.ts:

export const routing = defineRouting({
locales: LOCALES, // ['en', 'ar', 'bg', 'de', ...]
defaultLocale: DEFAULT_LOCALE // 'en'
});

Route Groups

Next.js route groups (parenthesized works) organize pages without affecting URL structure:

  • (auth)/ -- login, register, forgot-password, reset-password
  • (dashboard)/ -- home, works, plugins, settings

Each group has its own layout.tsx that provides the appropriate UI shell (auth layout vs. dashboard sidebar layout).

Dynamic Routes

Work detail pages use the [id] dynamic segment:

app/[locale]/(dashboard)/works/[id]/
layout.tsx # Work detail layout with tabs
page.tsx # Overview tab
items/page.tsx # Items tab
generator/page.tsx # Generator tab
...

The work layout loads the work entity and provides it to all child pages via WorkDetailContext.

Middleware

The proxy.ts file exports the Next.js middleware function, handling three concerns in sequence:

  1. Internationalization -- next-intl/middleware rewrites URLs to include the locale prefix and sets locale cookies.
  2. Public route check -- routes in PUBLIC_ROUTES (auth pages, static pages) bypass authentication.
  3. Authentication gate -- reads the encrypted auth cookie via getAuthFromCookie(). Unauthenticated requests are redirected to /login.

The middleware matcher ensures only page routes are processed:

export const config = {
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)'
};

Data Fetching

API Client

Server-side API calls go through utilities in lib/api/. The API URL is constructed from the API_URL environment variable:

const API_URL = apiUrl.endsWith('/api') ? apiUrl : `${apiUrl}/api`;

Authentication tokens are extracted from the encrypted cookie and passed as Bearer tokens in API requests.

Server Actions

The app/actions/ work contains Next.js Server Actions for form submissions and mutations that need to run on the server.

Internationalization with next-intl

Translation Files

Translations are stored as JSON in the messages/ work:

messages/
en.json
ar.json
de.json
es.json
...

The i18n/navigation.ts module provides locale-aware navigation helpers (Link, redirect, usePathname) that automatically prefix URLs with the current locale.

Request Configuration

The i18n/request.ts module configures per-request locale resolution for server components.

Theme Support

The dashboard supports light and dark themes:

  • theme-toggle.tsx -- toggles between light/dark/system themes.
  • lib/theme-init.ts -- initializes the theme from localStorage or system preference.
  • Logo and favicon variants are selected based on the active theme via NEXT_PUBLIC_LOGO_LIGHT, NEXT_PUBLIC_LOGO_DARK, etc.

Image Configuration

Remote image domains are whitelisted in next.config.ts:

  • github.com -- repository images
  • lh3.googleusercontent.com -- Google OAuth avatars
  • avatars.githubusercontent.com -- GitHub user avatars

Build Modes

The NEXT_BUILD_OUTPUT environment variable controls the build output:

ModeDescription
(default)Standard Next.js output with SSR
standaloneSelf-contained server for Docker
exportStatic HTML export (no SSR)

Permissions

The lib/permissions.ts module defines client-side permission checks for UI visibility:

  • Whether a user can edit a work
  • Whether a user can manage members
  • Whether settings should be shown

These mirror the backend's ownership/membership checks but are used for conditional rendering in the dashboard UI.