Skip to content

Software Design

High-Level Architecture Diagram

High-Level Architecture Diagram

Description:
The system uses a client server architecture. The Next.js frontend handles page rendering and user interaction. Requests are sent to an Express.js REST API where business logic and validation are performed. Prisma is used to interact with a PostgreSQL database. Authentication and third party services are handled at the API level, and the application is deployed using Docker behind Nginx.


Technologies

Frontend

Next.js is used for server side rendering and routing. TypeScript improves code safety. Tailwind CSS is used for responsive styling, and Axios handles API requests.

Backend

Express.js provides REST APIs. TypeScript is used for type safety, Zod validates request data, and Prisma manages database access.

Database

PostgreSQL stores all persistent application data.

DevOps & Deployment

Docker and Docker Compose are used for containerization. Nginx acts as a reverse proxy, and GitHub Actions handles CI/CD.

Package Management

npm is used to manage dependencies.


UML Diagram

UML Diagram


Sequence Diagrams

User Access & Navigation (US 1.01, 1.02, 1.03)

Sequence Diagram – User Access & Navigation

Description:
Shows how users access the site, switch languages, and navigate to external pages.


Ticket Purchase & Delivery (US 2.01, 2.02, 2.03)

Sequence Diagram – Ticket Purchase & Delivery

Description:
Shows ticket selection, payment processing, and ticket delivery by email.


Author Directory Browse & Filter (US 3.01, 3.02, 3.03, 3.04)

Sequence Diagram – Author Directory

Description:
Shows browsing, filtering authors, and viewing author profiles.


Events Discovery & Details (US 4.01, 4.02, 4.03, 4.04)

Sequence Diagram – Events Discovery

Description:
Shows how users find events, view details, and access event pages.


Admin & Content Management + Restricted Resources (US 7.01–7.11, US 8.01)

Sequence Diagram – Admin & Content Management

Description:
Shows admin login, content management, and educator access to restricted resources.


Low-Fidelity Wireframes

Low-Fidelity Wireframes

Description:
Basic layouts showing structure, navigation, and user flow. You may open the image in a new tab.


UI/UX Design Principles and Heuristics

Description:
The following section evaluates the user interface using established usability principles. Our design is guided by Nielsen’s 10 Usability Heuristics (Nielsen Norman Group), as well as WCAG 2.2 accessibility standards. Each principle is supported with concrete examples from the SILAB platform.

Reference: https://www.nngroup.com/articles/ten-usability-heuristics/


1. Accessibility (WCAG 2.2 Compliance)

The platform is designed to be inclusive and accessible to users from diverse backgrounds.

  • Language Accessibility:
    A persistent bilingual language toggle (English/French) is available on all pages. Users can seamlessly switch languages, and the system remembers their preference across sessions, reducing repeated actions.

  • Visual Accessibility:
    All UI colors meet WCAG 2.2 contrast requirements (minimum 4.5:1 ratio).
    Event detail pages clearly label fields such as City and Location, with bold formatting to improve readability and reduce ambiguity.


2. User Control and Freedom (Nielsen Heuristic #3)

Users are given control over their actions and can easily recover from mistakes.

  • Confirmation Prompts:
    Actions that modify data (e.g., submitting contact forms or editing events) include confirmation steps to prevent accidental submissions.

3. Consistency and Standards (Nielsen Heuristic #4)

The system maintains consistent design patterns across all pages to reduce cognitive load.

  • Consistent Styling:
    A unified green-blue color scheme is used across the application, aligning with the KAYANOU branding.

  • Reusable Layout Patterns:
    Pages such as Authors and Events follow similar grid-based layouts, and forms (e.g., Add/Edit Event) maintain identical field ordering and structure.


4. Visibility of System Status (Nielsen Heuristic #1)

The system provides feedback to users during interactions.

  • Loading Indicators:
    Pages such as the Authors page display a “Loading authors…” message while data is being fetched.

  • Error Feedback:
    If API requests fail, users are shown clear error messages instead of silent failures.


5. Error Prevention (Nielsen Heuristic #5)

The system actively prevents invalid input and user mistakes.

  • Form Validation:
    Input validation using Zod ensures required fields (e.g., name, bio) are completed before submission.

  • Input Constraints:
    Fields such as URLs (image/ticket links) are validated to prevent incorrect formats.


6. Recognition Rather Than Recall (Nielsen Heuristic #6)

The system minimizes the need for users to remember information.

  • Filter Visibility:
    Active filters on the Authors page are displayed as removable badges, allowing users to see and modify their selections easily.

  • Visual Author Cards:
    Author names and images are displayed directly, helping users recognize content rather than recall it from memory.


7. Flexibility and Efficiency of Use (Nielsen Heuristic #7)

The system is designed to accommodate both novice and experienced users.

  • Responsive Design:
    The platform supports both mobile and desktop views with consistent layouts, ensuring usability across devices without sacrificing functionality.

8. Aesthetic and Minimalist Design (Nielsen Heuristic #8)

The interface maintains a clean and professional appearance without unnecessary complexity.

  • Minimalist Layout:
    Pages use whitespace and structured layouts to reduce visual clutter and emphasize important content.

  • Focused Content Presentation:
    Key elements such as events and authors are prioritized, allowing users to quickly find relevant information.


9. Help Users Recognize, Diagnose, and Recover from Errors (Nielsen Heuristic #9)

The system provides clear guidance when errors occur.

  • Descriptive Error Messages:
    Users receive clear feedback when inputs are invalid or when requests fail, helping them understand and fix the issue.

  • Guided Recovery:
    Forms highlight problematic fields, allowing users to quickly correct mistakes.


10. Match Between System and the Real World (Nielsen Heuristic #2)

The system uses familiar language and concepts that align with user expectations.

  • Real-World Terminology:
    Labels such as “City,” “Location,” and “Event” reflect real-world concepts, making the interface intuitive.

  • Logical Organization:
    Information is structured in a way that mirrors how users expect to browse events and authors.


Overall, the SILAB platform applies established usability heuristics and accessibility standards to ensure a consistent, intuitive, and user-friendly experience across all interactions.


API Interfaces

Overview

The frontend communicates with the backend through a RESTful API implemented in Express.js. Requests are sent from the Next.js frontend to the backend service using HTTP. The backend validates incoming data using Zod, performs business logic in route handlers, and interacts with the PostgreSQL database through Prisma ORM.

Authentication is handled using JWT tokens stored in HTTP-only cookies. Protected routes use middleware to verify authentication and enforce role-based access control, such as admin-only permissions for author and event management.

The general interaction flow is:

  1. The frontend sends an HTTP request to the Express API.
  2. Express routes the request to the appropriate endpoint.
  3. Middleware verifies authentication and permissions when required.
  4. Zod validates request data.
  5. Prisma queries or updates the PostgreSQL database.
  6. A JSON response is returned to the frontend.

Swagger / OpenAPI Documentation

To improve maintainability and make the backend easier to test and review, the API is also documented using Swagger (OpenAPI 3.0). The documentation is generated from JSDoc-style annotations in the Express route files and is served through Swagger UI.

This provides: - interactive API documentation - request and response schema examples - endpoint grouping by module - documentation for protected routes and authentication requirements

The Swagger UI is available at:

  • Local development: http://localhost:8080/api-docs
  • Staging: https://stage.api.silab.website/api-docs
  • Production: https://api.silab.website/api-docs

API Modules

The backend API is divided into several modules, each responsible for a specific part of the system.

Module Responsibility
Auth API User signup, login, and session verification
Authors API Public author directory browsing and admin author management
Events API Event listing, filtering, detail retrieval, and admin event management
Contact API Handling user contact form submissions
Team API Retrieval and management of administrator/team member profiles
Works API Retrieval of individual work details and event-related works

Authentication API

Handles user signup, login, and session verification.

POST /auth/signup

Creates a new user account.

Request:

{
  "name": "John Doe",
  "email": "user@example.com",
  "password": "password123"
}

Response:

{
  "status": "ok",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "USER",
    "createdAt": "2026-03-22T20:00:00.000Z"
  }
}

POST /auth/login

Authenticates a user and creates a session by setting an authentication cookie.

Request:

{
  "email": "user@example.com",
  "password": "password123"
}

Response:

{
  "status": "ok",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "isAdmin": false
  }
}

GET /auth/me

Returns the currently authenticated user.

Response:

{
  "status": "ok",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "isAdmin": true
  }
}

This endpoint is used by the frontend to determine if a user has admin privileges.

Authors API

Manages the author directory and author profiles.

GET /authors

Returns a list of authors. Optional query parameters allow filtering by location, genre, language, and region.

Example:

GET /authors?location=Edmonton&genre=Fantasy

Response:

{
  "status": "ok",
  "data": [
    {
      "id": "author-id",
      "name": "William Shakespeare",
      "bio": "Fantasy author",
      "photoUrl": "...",
      "publishedWorks": ["Book A", "Book B"],
      "location": "Edmonton",
      "genre": "Fantasy",
      "language": "English",
      "region": "Alberta"
    }
  ]
}

GET /authors/:id

Returns a single author profile.

Example:

GET /authors/abc123

Response:

{
  "status": "ok",
  "data": {
    "id": "abc123",
    "name": "William Shakespeare",
    "bio": "Fantasy author",
    "photoUrl": "...",
    "publishedWorks": ["Book A", "Book B"],
    "location": "Edmonton",
    "genre": "Fantasy",
    "language": "English",
    "region": "Alberta"
  }
}

POST /authors (Admin Only)

Creates a new author profile.

Request:

{
  "name": "New Author",
  "bio": "Biography text",
  "location": "Edmonton",
  "photoUrl": "...",
  "genre": "Poetry",
  "language": "French",
  "region": "Alberta",
  "publishedWorks": ["Book One"]
}

PUT /authors/:id (Admin Only)

Updates an existing author profile.

Request:

{
  "name": "Updated Name",
  "bio": "Updated biography",
  "location": "Calgary"
}

Authorization is enforced using middleware that verifies the user has admin privileges. Validation is handled using Zod.

POST /authors/:id/photo

Uploads an author image and updates the stored photoUrl. This route accepts multipart/form-data and stores the uploaded image using Cloudinary integration.

Event API

Handles event browsing, event detail retrieval, and event management.

GET /events

Returns a list of events. Optional query parameters allow filtering by date, city, and audience.

Example:

GET /events?city=Edmonton

Response:

{
  "status": "ok",
  "data": [
    {
      "id": "event-id",
      "title": "Author Talk",
      "city": "Edmonton",
      "startTime": "2026-04-01T18:00:00Z",
      "endTime": "2026-04-01T20:00:00Z",
      "locationName": "Library Hall",
      "isFree": true,
      "ticketPrice": null,
      "currency": "CAD"
    }
  ]
}

GET /events/:id

Returns detailed event information.

Response:

{
  "status": "ok",
  "data": {
    "id": "event-id",
    "title": "Author Talk",
    "description": "...",
    "city": "Edmonton",
    "locationName": "Library Hall",
    "locationAddress": "123 Main St",
    "startTime": "2026-04-01T18:00:00Z",
    "endTime": "2026-04-01T20:00:00Z",
    "registrationsCount": 25
  }
}

POST /events (Admin Only)

Creates a new event record.

PUT /events/:id (Admin Only)

Updates an existing event.

DELETE /events/:id (Admin Only)

Deletes an event.

GET /events/:id/works

Returns works associated with a specific event.

Contact API

Handles contact form submissions from users.

POST /contact

Sends a contact request to the organizers.

Request:

{
  "name": "User Name",
  "email": "user@email.com",
  "requestTypeName": "General Inquiry",
  "location": "Edmonton",
  "message": "Hello"
}

Response:

{
  "status": "Created",
  "data": {
    "id": "contact-id",
    "name": "User Name",
    "email": "user@email.com",
    "requestTypeName": "General Inquiry",
    "location": "Edmonton",
    "message": "Hello"
  }
}

Team API

Handles retrieval and management of administrator/team member profiles.

GET /team

Returns all administrator/team member profiles.

GET /team/:id

Returns a single administrator/team member profile.

POST /team (Admin Only)

Creates a new administrator/team member profile.

PUT /team/:id (Admin Only)

Updates an existing administrator/team member profile.

DELETE /team/:id

Deletes a team member profile.

Works API

Handles individual work retrieval.

GET /works/:id

Returns details for a single work, including its associated event title.

Middleware Interfaces

Authentication Middleware

Verifies the user’s JWT token and attaches the user object to the request.

Example behavior:

Request → authMiddleware → route handler

If authentication fails, the request is rejected with HTTP 401.

Validation Middleware

Zod schemas validate incoming request bodies before they reach the business logic layer.

Example behavior:

Request → Zod validation → route handler → database

Invalid data results in HTTP 400 responses.

The SILAB webiste is designed in mind to look professional and clean, in contrast with the client/ KAYANOU's main website and also acts as a representation of their growth. This includes UI design principles such as: - Consistent color schemes The SILAB website has a consistent green-blue color scheme that matches with the KAYANOU logo. - Similar Look Webpages are made to look as similar as possible in other to keep consistency across the whole website and avoid confusion. This is seen in the similarities in look to the author and events pages, as well as how the add/edit event pages in that their input fields have the same order.

API Interfaces

Overview

The frontend communicates with the backend through a RESTful API implemented in Express.js. All requests are sent from the Next.js frontend to the backend server using HTTP. The backend validates incoming data using Zod, performs business logic, and interacts with the PostgreSQL database through Prisma ORM.

Authentication is handled through JWT tokens stored in cookies. Protected routes use middleware to verify authentication and enforce role-based access control (e.g., admin-only endpoints).

The general interaction flow is: 1. The frontend sends an HTTP request to the Express API. 2. Express routes the request to the appropriate controller. 3. Middleware verifies authentication and permissions. 4. Zod validates request data. 5. Prisma queries or updates the PostgreSQL database. 6. A JSON response is returned to the frontend.

API Modules

The backend API is divided into several modules, each responsible for a specific part of the system.

Module Responsibility
Auth API User login, signup, and authentication verification
Authors API Author directory browsing and admin author management
Events API Event listing, filtering, and event management
Contact API Handling user contact form submissions

Authentication API

Handles login, signup, and session verification.

POST /auth/signup

Creates a new user account.

Request:

{
  "name": "John Doe",
  "email": "user@example.com",
  "password": "password123"
}

Response:

{
  "status": "ok",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "isAdmin": false
  }
}

POST /auth/login

Authenticates a user and creates a session.

Request:

{
  "email": "user@example.com",
  "password": "password123"
}

Response:

{
  "status": "ok",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "isAdmin": false
  }
}

GET /auth/me

Returns the currently authenticated user.

Response:

{
  "status": "ok",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "isAdmin": true
  }
}

This endpoint is used by the frontend to determine if a user has admin privileges.

Authors API

Manages the author directory and author profiles.

GET /authors

Returns a list of authors. Optional query parameters allow filtering.

Example:

GET /authors?location=Edmonton&genre=Fantasy

Response:

{
  "status": "ok",
  "data": [
    {
      "id": "author-id",
      "name": "William Shakespeare",
      "bio": "Fantasy author",
      "photoUrl": "...",
      "publishedWorks": ["Book A", "Book B"]
    }
  ]
}

GET /authors/:id

Returns a single author profile.

Example:

GET /authors/abc123

Response:

{
  "status": "ok",
  "data": {
    "id": "abc123",
    "name": "William Shakespeare",
    "bio": "Fantasy author",
    "photoUrl": "...",
    "publishedWorks": ["Book A", "Book B"]
  }
}

POST /authors (Admin Only)

Creates a new author profile.

Request:

{
  "name": "New Author",
  "bio": "Biography text",
  "location": "Edmonton",
  "photoUrl": "...",
  "publishedWorks": ["Book One"]
}

Response:

{
  "status": "ok",
  "data": {
    "id": "generated-id",
    "name": "New Author"
  }
}

Authorization is enforced using middleware that verifies the user has admin privileges.

PUT /authors/:id (Admin Only)

Updates an existing author profile.

Request:

{
  "name": "Updated Name",
  "bio": "Updated biography",
  "location": "Calgary"
}

Response:

{
  "status": "ok",
  "data": {
    "id": "author-id",
    "name": "Updated Name"
  }
}

Required fields cannot be updated to blank values. Validation is handled using Zod.

Event API

Handles event browsing and event information.

GET /events

Returns a list of upcoming events.

Example:

GET /events?city=Edmonton

Response:

{
  "status": "ok",
  "data": [
    {
      "id": "event-id",
      "title": "Author Talk",
      "city": "Edmonton",
      "startTime": "2026-04-01T18:00:00Z"
    }
  ]
}

GET /events/:id

Returns detailed event information.

Response:

{
  "status": "ok",
  "data": {
    "id": "event-id",
    "title": "Author Talk",
    "description": "...",
    "locationName": "Library Hall"
  }
}

Contact API

Handles contact form submissions from users.

POST /contact

Sends a contact request to the organizers.

Request:

{
  "name": "User Name",
  "email": "user@email.com",
  "message": "Hello"
}

Response:

{
  "status": "ok"
}

Middleware Interfaces

Authentication Middleware

Verifies the user’s JWT token and attaches the user object to the request.

Example behavior:

Request → authMiddleware → route handler

If authentication fails, the request is rejected with HTTP 401.

Validation Middleware

Zod schemas validate incoming request bodies before they reach the business logic layer.

Example behavior:

Request → Zod validation → route handler → database

Invalid data results in HTTP 400 responses.