Skip to main content

Frontend Architecture

Purpose

This document describes the frontend architecture for Chilarai.

It defines the structure, patterns, and decisions for building the web application using Next.js.

The frontend architecture is designed to support:

  • School administrators
  • Teachers
  • Parents
  • Platform administrators
  • Future student-facing experiences
  • Future agent-assisted experiences

The frontend must remain simple, modular, permission-driven, and aligned with the backend domain model.


Technology Stack

Framework

  • Next.js

Language

  • TypeScript

Styling

  • Tailwind CSS

Component Foundation

  • shadcn/ui

Server State

  • TanStack Query

Application State

  • React Context

Forms

  • React Hook Form

Validation

  • Zod

Authentication

  • Keycloak

API Style

  • REST APIs

Architecture Goals

The frontend architecture should:

  • Stay aligned with backend domain modules
  • Avoid unnecessary frontend complexity
  • Support permission-driven navigation
  • Support users with multiple school memberships
  • Support school context switching
  • Keep server state and application state separate
  • Provide a consistent application shell
  • Support future agent experiences
  • Remain ready for internationalization
  • Support responsive web experiences

Rendering Strategy

Chilarai uses a hybrid Next.js rendering strategy.

Public Pages

Public pages may use static rendering or server-side rendering.

Examples:

  • Landing Page
  • Pricing Page
  • Public Help Pages
  • Marketing Pages

Authenticated Application Pages

Authenticated application pages primarily use client-side rendering because they depend on:

  • Active user
  • Active school context
  • Permissions
  • Dynamic data
  • User-specific navigation

Examples:

  • Dashboard
  • Students
  • Admissions
  • Attendance
  • Fees
  • Administration

Application Structure

The frontend is organized by business capability.

Example structure:

src

├── app
├── modules
├── providers
├── shared
└── api

app

Contains routing, route layouts, and application initialization.

modules

Contains business capability implementations.

Examples:

modules

├── students
├── admissions
├── academics
├── attendance
├── fees
├── staff
└── administration

providers

Contains application-level providers.

Examples:

providers

├── school-context
├── auth-context
├── theme-context
└── query-provider

shared

Contains reusable UI components, hooks, utilities, and shared frontend infrastructure.

api

Contains REST API client wrappers.

UI components must not call fetch directly.


Frontend Module Structure

Each frontend module should follow a consistent structure.

Example:

modules/students

├── pages
├── components
├── hooks
├── api
└── schemas

pages

Module-specific route-level pages.

components

Module-specific UI components.

hooks

Module-specific React hooks.

api

Module-specific API access wrappers.

schemas

Module-specific frontend validation schemas or references to shared schemas.


Module Boundary Principle

Frontend modules should mirror backend domain modules where practical.

Examples:

Backend Student Module

Frontend Students Module

Backend Admission Module

Frontend Admissions Module

Backend Fees Module

Frontend Fees Module

This keeps the mental model consistent across frontend and backend development.


State Management

Frontend state is divided into two categories:

  • Server State
  • Application State

These categories must not be mixed.


Server State

Server State is data that originates from backend APIs.

Examples:

  • Students
  • Admissions
  • Staff
  • Attendance
  • Fees
  • Academic Years
  • Academic Structure
  • School Configuration

Server State is managed using TanStack Query.

TanStack Query is responsible for:

  • Fetching data
  • Caching data
  • Loading states
  • Error states
  • Refetching
  • Query invalidation
  • Pagination
  • Background refresh

Application State

Application State is state that exists only in the browser.

Examples:

  • Active School Context
  • Theme
  • Sidebar State
  • Right Workspace Panel State
  • Session UI Preferences

Application State is managed using React Context.


State Management Diagram


State Ownership Rules

TanStack Query Owns

  • Business data
  • API results
  • Lists
  • Details
  • Search results
  • Paginated results

Examples:

students
student-details
admissions
fees
attendance

React Context Owns

  • Current school
  • Theme
  • Layout state
  • UI preferences

Prohibited Pattern

Business data must not be copied from TanStack Query into React Context or another frontend store.

Invalid example:

Students fetched by TanStack Query

Copied into Context

This creates multiple sources of truth and must be avoided.


School Context Management

A user may belong to multiple schools.

The frontend maintains a single active school context.

Example:

User
├── School A
├── School B
└── School C

At any point in time:

Active School = School A

All application pages operate within the active school context.


School Switching

Users must be able to switch school context from the global application shell.

When the active school changes:

  • Active school context is updated
  • User permissions are refreshed
  • Navigation is rebuilt
  • TanStack Query cache keys change
  • Relevant queries are invalidated
  • Page data is reloaded

School Context Query Pattern

Queries that are school-specific must include schoolId in the query key.

Example:

["students", schoolId]
["admissions", schoolId]
["fees", schoolId]
["attendance", schoolId]

This ensures that cached data from one school is not reused for another school.


School Context Diagram


API Communication

The frontend communicates with the backend through REST APIs.

GraphQL is not used for the initial implementation.

All API communication must go through API client wrappers.

Example:

api

├── students-api.ts
├── admissions-api.ts
├── attendance-api.ts
├── fees-api.ts
└── staff-api.ts

UI components must not directly call backend endpoints.


API Client Responsibilities

API client wrappers are responsible for:

  • Calling REST endpoints
  • Passing school context where required
  • Handling request serialization
  • Handling response deserialization
  • Returning typed data
  • Normalizing API errors where appropriate

Forms Strategy

Chilarai uses React Hook Form for forms.

Examples:

  • Student Form
  • Admission Form
  • Staff Form
  • Fee Structure Form
  • School Settings Form

React Hook Form is responsible for:

  • Field state
  • Dirty state
  • Touched state
  • Form submission
  • Reset behavior
  • Nested form structures
  • Field arrays

Validation Strategy

Chilarai uses Zod for validation.

Validation is split into three layers.

Shared Structural Validation

Shared Zod schemas validate:

  • Required fields
  • Field formats
  • Length constraints
  • Object structure
  • Basic enum values

These schemas live in shared-validation.

They are used by both:

  • Frontend forms
  • Backend request validation

Backend Business Validation

Business rules that require database access or module coordination are enforced only on the backend.

Examples:

  • Student already enrolled in academic year
  • Admission class does not belong to school
  • Fee structure does not exist
  • User does not have required school membership

Backend Authorization Validation

Authorization is always enforced on the backend.

Frontend checks are only used to improve the user experience.


Forms and Validation Diagram


Authentication

Authentication is handled by Keycloak.

The frontend is responsible for:

  • Redirecting users to login
  • Handling authentication callback
  • Maintaining authenticated session state
  • Passing access tokens to API clients
  • Handling logout

The frontend must not manage passwords or authentication secrets.


Authorization

Authorization is permission-driven.

The frontend uses permissions to determine:

  • Visible navigation items
  • Visible buttons
  • Available actions
  • Accessible screens

The backend remains the final authority for authorization.


Roles vs Permissions

Roles are administrative groupings.

Examples:

  • Parent
  • Teacher
  • School Admin
  • Principal
  • Accountant

Permissions drive UI behavior.

Examples:

  • students.read
  • students.manage
  • admissions.review
  • fees.manage
  • attendance.manage
  • school.settings.manage

Frontend rendering must depend on permissions, not raw role names.


Permission Driven Navigation

The left navigation is built from a navigation configuration.

Each navigation item declares the required permission.

Example:

Students
Required Permission:
students.read

If the user has the permission, the item is visible.

If the user does not have the permission, the item is hidden.


Permission Driven Navigation Diagram


Multi-Role Navigation

A user may have multiple roles in the same school.

Example:

User
├── Parent
└── Teacher

The navigation must show the union of permissions granted to all roles.

The frontend must not force the user to switch between role modes such as:

  • Parent Mode
  • Teacher Mode
  • Admin Mode

Instead, the user sees all capabilities allowed by their permissions.


Application Shell

The application uses a single shared shell.

The shell contains:

  • Header
  • Left Navigation
  • Main Workspace
  • Right Workspace Panel
  • Footer

Modules render inside the shell.

Modules must not create their own top-level application shells.


Layout Model


The header contains global actions.

Examples:

  • School Switcher
  • Notifications
  • User Menu
  • Future Global Search

The header remains visible across authenticated pages.


Left Navigation

The left navigation is:

  • Grouped by business capability
  • Permission-driven
  • Dynamic
  • School context aware

Example groups:

  • Dashboard
  • Students
  • Academics
  • Attendance
  • Fees
  • Administration

When school context changes, left navigation is recalculated.


Main Workspace

The main workspace is used for primary workflows.

Examples:

  • Student Management
  • Admission Management
  • Fee Structure Management
  • Attendance Entry
  • Reports
  • Settings

Complex workflows should use dedicated pages.


Right Workspace Panel

The right workspace panel is used for lightweight and contextual experiences.

Examples:

  • Notifications
  • Agent Conversations
  • Quick Views
  • Tasks
  • Approvals
  • Help
  • Activity Feed

The right workspace panel is not intended for heavy data-entry workflows.


Workspace Usage Rules

Use dedicated pages for:

  • Create Student
  • Edit Student
  • Create Admission
  • Edit Admission
  • Fee Structure Management
  • Attendance Entry
  • School Settings

Use the right workspace panel for:

  • Notifications
  • Agent
  • Quick Student Preview
  • Approval Queue Preview
  • Help
  • Contextual Activity

A small footer is included in the application shell.

Examples:

  • Copyright
  • Version
  • Legal Links

The footer should remain visually minimal and unobtrusive.


Design System

Tailwind CSS is used for styling.

shadcn/ui is used as the component foundation.

Shared components should be built on top of shadcn/ui primitives.

Examples:

  • Data Table
  • Form Field
  • Page Header
  • Empty State
  • Confirm Dialog
  • Status Badge
  • Permission Gate

Component Architecture

Components should be organized into three categories.

Shared Components

Reusable across the application.

Examples:

  • Button wrappers
  • Data table
  • Page header
  • Permission guard
  • Loading state
  • Empty state

Module Components

Specific to a domain module.

Examples:

  • StudentCard
  • AdmissionStatusBadge
  • FeeSummaryCard

Page Components

Route-level composition components.

Examples:

  • StudentListPage
  • AdmissionReviewPage
  • FeeStructurePage

Frontend Caching

TanStack Query is the only frontend caching mechanism.

Custom frontend caches should not be introduced.

The frontend must not directly use Redis.

Redis is a backend concern.


Cache Invalidation

Mutations must invalidate affected queries.

Examples:

Create Student

Invalidate students query

Approve Admission

Invalidate admissions query

Invalidate students query

Record Payment

Invalidate student fees query

Error Handling

Frontend error handling should support:

  • Field-level validation errors
  • Form submission errors
  • Page-level data loading errors
  • Authorization errors
  • Unexpected failures

Common error UI components should be shared.

Examples:

  • Error Alert
  • Forbidden Page
  • Not Found Page
  • Retry Panel

File Uploads

File upload flows are required for:

  • Student Photos
  • Staff Photos
  • Admission Documents
  • Certificates
  • School Assets

The frontend should upload files only through backend-supported upload flows.

The frontend should not directly expose storage provider details such as MinIO bucket names.

File downloads should use backend-generated pre-signed URLs.


Internationalization

The frontend must be internationalization-ready.

Initial language:

  • English

Future languages may include:

  • Assamese
  • Hindi
  • Bengali

User-facing strings should not be hardcoded deeply inside business logic.


Accessibility

The frontend should follow accessible UI practices.

Guidelines:

  • Keyboard navigable components
  • Visible focus states
  • Accessible labels
  • Semantic HTML
  • Sufficient color contrast
  • Screen-reader-friendly controls

shadcn/ui components should be used in an accessible manner.


Responsive Design

The primary target is desktop and tablet usage for school administration.

The application should remain usable on smaller screens where practical.

Mobile-first experiences may be introduced later for parent and student workflows.


Testing Strategy

The frontend should support:

  • Unit tests for utilities and hooks
  • Component tests for shared components
  • Integration tests for important workflows
  • End-to-end tests for critical journeys

Initial focus should be on:

  • Login
  • School switching
  • Student management
  • Admission workflow
  • Fee collection

Build and Deployment Considerations

The frontend is built as part of the Nx monorepo.

The frontend should be independently deployable from the backend.

Environment-specific configuration should be externalized.

Examples:

  • API base URL
  • Keycloak configuration
  • Feature flags
  • Public environment settings

Future Considerations

The following capabilities may be introduced later:

  • Agent-first workflows
  • Global search
  • Offline support
  • Mobile application
  • Parent-specific portal
  • Student portal
  • Advanced dashboards
  • Real-time notifications

These capabilities should not require a redesign of the frontend architecture.


Summary

Core decisions:

  • Use Next.js for the frontend.
  • Use TypeScript throughout the frontend codebase.
  • Use Tailwind CSS and shadcn/ui for UI development.
  • Organize modules by business capability.
  • Use TanStack Query for server state.
  • Use React Context for application state.
  • Use REST APIs for backend communication.
  • Use React Hook Form for forms.
  • Use shared Zod schemas for structural validation.
  • Keep business validation on the backend.
  • Use permission-driven navigation.
  • Use a single application shell.
  • Support school context switching.
  • Use a dynamic left navigation.
  • Use a right workspace panel for contextual experiences.
  • Use dedicated pages for complex workflows.
  • Keep the frontend internationalization-ready.