Skip to main content

Evolve Candidate Frontend Architecture

System Overview​

Candidates authenticate, land on an applications/rounds shell, and move through test rounds (MCQ, coding, personality, prompt). Exam security is a cross-cutting layer that wraps every round's page. Submissions go to the backend API directly from the client; MCQ submission additionally triggers a server-side webhook proxy that notifies an n8n workflow to auto-assign the candidate to their next round.

Architecture Diagram​

graph TB
subgraph FE["Frontend: evolve-candidate-fe"]
Auth["Login / Register / Reset Password"]
Rounds["applications/rounds shell"]
MCQ["test/mcq"]
Coding["test/coding<br/>(Monaco editor)"]
Personality["test/personality"]
Prompt["test/prompt"]
Security["examSecurity.js<br/>(fullscreen, key-block, tab/devtools detect)"]
Store["useTestStore.js<br/>(Zustand + localStorage)"]
WebhookProxy["api/webhook/auto-assign<br/>(server route)"]
end
EvolveAPI["Evolve backend API<br/>(campus-recruitment-2.0-be)"]
N8N["n8n auto-assign workflow"]

Auth -->|"authenticates"| EvolveAPI
Rounds -->|"fetch rounds/status"| EvolveAPI
Rounds --> MCQ
Rounds --> Coding
Rounds --> Personality
Rounds --> Prompt
Security -.->|"wraps"| MCQ
Security -.->|"wraps"| Coding
Security -.->|"wraps"| Personality
Security -.->|"wraps"| Prompt
MCQ -->|"tracks context"| Store
MCQ -->|"on submit"| EvolveAPI
MCQ -->|"on submit"| WebhookProxy
WebhookProxy -->|"basic-auth POST"| N8N

How to read this diagram​

Arrows mean flow / dependency / "talks to", not button clicks. Dotted lines mean a cross-cutting wrapper, not a data flow.

Core Components​

Exam security (src/lib/examSecurity.js)​

Central module for keyboard-shortcut blocking, right-click blocking, fullscreen enforcement, tab/window-switch and dev-tools detection, and the two-tier warning system (blocking modal for critical violations, auto-dismissing toast for minor ones with a 10-second per-message cooldown).

Test state (src/store/useTestStore.js)​

Zustand store persisted to localStorage: test name/ID, full rounds payload, and which round is currently active. The security logger reads this store to attach test/round context to each violation log.

Webhook proxy (src/app/api/webhook/auto-assign/route.js)​

A Next.js route handler, not a client-side fetch, so the n8n webhook URL and basic-auth credentials (NEXT_PUBLIC_N8N_BASIC_AUTH_USER/PASS) never need to touch the browser bundle at request time - the browser calls this same-origin route, which then calls n8n server-side.

Test rounds (src/app/test/*)​

Each round type (mcq, coding, personality, prompt) is its own route segment. Coding uses @monaco-editor/react; prompt enforces a minimum length/word count client-side before submit is enabled.

Data Flow​

sequenceDiagram
participant Candidate
participant FE as Candidate Frontend
participant API as Evolve Backend
participant Proxy as api/webhook/auto-assign
participant N8N

Candidate->>FE: Log in (email may be pre-filled from query param)
FE->>API: authenticate
API-->>FE: session + refresh token

Candidate->>FE: Start MCQ round
FE->>Store: load/track round context
Candidate->>FE: Submit MCQ
FE->>API: submit answers
FE->>Proxy: POST auto-assign
Proxy->>N8N: POST (basic auth)
N8N-->>Proxy: 200/failure
Proxy-->>FE: {ok: true/false}

Design Decisions​

Server-side proxy for the n8n webhook​

Context: Calling the n8n webhook directly from the browser would expose its URL and basic-auth credentials in client code.

Decision: Route the call through a same-origin Next.js API route (api/webhook/auto-assign) that holds the credentials server-side and forwards the request.

Two-tier security warnings (modal vs. toast)​

Context: Not all rule violations carry the same severity - blocking the exam on every accidental right-click would be disruptive.

Decision: Tab/window switching and dev-tools detection block via a modal that must be acknowledged; copy/paste and keyboard-shortcut attempts show a non-blocking, auto-dismissing toast with a cooldown to prevent log spam.

Allow-list specific interactive elements during lockdown​

Context: Blanket-blocking selection/copy-paste everywhere would break normal form inputs and the code editor.

Decision: examSecurity.js explicitly allow-lists input, textarea, select, button, a, contenteditable elements, and the Monaco editor (when allowCodeEditor is true) while still blocking the right-click context menu everywhere.

Technology Stack​

LayerTechnology
FrameworkNext.js App Router
LanguageJavaScript
StateZustand + localStorage persistence
Code editorMonaco (@monaco-editor/react)
Notificationsreact-toastify
Default branchmain

Next Steps​