Software Design
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

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

Description:
Shows how users access the site, switch languages, and navigate to external pages.
Ticket Purchase & Delivery (US 2.01, 2.02, 2.03)

Description:
Shows ticket selection, payment processing, and ticket delivery by email.
Author Directory Browse & Filter (US 3.01, 3.02, 3.03, 3.04)

Description:
Shows browsing, filtering authors, and viewing author profiles.
Events Discovery & Details (US 4.01, 4.02, 4.03, 4.04)

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)

Description:
Shows admin login, content management, and educator access to restricted resources.
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:
- The frontend sends an HTTP request to the Express API.
- Express routes the request to the appropriate endpoint.
- Middleware verifies authentication and permissions when required.
- Zod validates request data.
- Prisma queries or updates the PostgreSQL database.
- 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.