

# **WORKFORCEOS**

**FRONTEND GUIDE FOR AI CODING AGENTS - PART 1 - Project Introduction &amp; Setup**

This is the introductory document for the **workforceos** frontend project. It is designed for AI agents that will generate frontend code to consume the project's backend. Read it carefully — it describes the project scope, architecture, API conventions, and initial screens you must build before proceeding to the feature-specific prompts that follow.

This prompt will help you set up the project infrastructure, create the initial layout, home page, navigation, and any dummy screens. The subsequent prompts will provide detailed API documentation for each feature area.

## Project Introduction

WorkforceOS is a unified, web-based platform that enables businesses to efficiently manage employees, schedules, attendance, tasks, and workforce operations with full company-level data isolation. Designed for multi-role access, internal departments, AI-driven insights, and integrated communication via email and in-app notifications.




## Project Services Overview

The project has **1 auth service**, **1 notification service**, **1 BFF service**, and **10 business services**, plus other helper services such as bucket and realtime.

Each service is a separate microservice application and listens for HTTP requests at different service URLs.

| # | Service | Description | API Prefix |
|---|---------|-------------|------------|
| 1 | auth | Authentication and user management | `/auth-api` |
| 2 | employeeProfile | Manages extended employee profile data, employment/tax details, and employee-rel... | `/employeeProfile-api` |
| 3 | scheduleManagement | Microservice managing shift scheduling, shift templates, assignment of users/dep... | `/scheduleManagement-api` |
| 4 | attendanceManagement | Handles employee attendance logging (check-in/out), attendance rules (lateness/a... | `/attendanceManagement-api` |
| 5 | taskManagement | Handles creation, assignment, update, and tracking of tasks tied to employees, s... | `/taskManagement-api` |
| 6 | leaveManagement | Handles employee leave/absence requests, review/approval workflows, and automati... | `/leaveManagement-api` |
| 7 | payrollReporting | Handles payroll report records for employees based on calculated hours, overtime... | `/payrollReporting-api` |
| 8 | announcementManagement | Handles company-wide and department-specific announcements, supporting scheduled... | `/announcementManagement-api` |
| 9 | aiWorkforceAnalytics | Microservice for computing and delivering AI-powered workforce analytics (e.g., ... | `/aiWorkforceAnalytics-api` |
| 10 | subscriptionManagement | Manages company AI subscriptions through Stripe payments. Companies must pay via... | `/subscriptionManagement-api` |
| 11 | agentHub | AI Agent Hub | `/agentHub-api` |

Detailed API documentation for each service will be given in the following prompts. In this document, you will build the initial project structure, home pages, and navigation.

## API Structure

### Object Structure of a Successful Response

When the service processes requests successfully, it wraps the requested resource(s) within a JSON envelope. This envelope includes the data and essential metadata such as configuration details and pagination information, providing context to the client.

**HTTP Status Codes:**

* **200 OK**: Returned for successful GET, LIST, UPDATE, or DELETE operations, indicating that the request was processed successfully.
* **201 Created**: Returned for CREATE operations, indicating that the resource was created successfully.

**Success Response Format:**

For successful operations, the response includes a `"status": "OK"` property, signaling that the request executed successfully. The structure of a successful response is outlined below:

```json
{
  "status":"OK",
  "statusCode": 200,
  "elapsedMs":126,
  "ssoTime":120,
  "source": "db",
  "cacheKey": "hexCode",
  "userId": "ID",
  "sessionId": "ID",
  "requestId": "ID",
  "dataName":"products",
  "method":"GET",
  "action":"list",
  "appVersion":"Version",
  "rowCount":3,
  "products":[{},{},{}],
  "paging": {
    "pageNumber":1,
    "pageRowCount":25,
    "totalRowCount":3,
    "pageCount":1
  },
  "filters": [],
  "uiPermissions": []
}
```

* **`products`**: In this example, this key contains the actual response content, which may be a single object or an array of objects depending on the operation.

### Additional Data

Each API may include additional data besides the main data object, depending on the business logic of the API. These will be provided in each API's response signature.

### Error Response

If a request encounters an issue—whether due to a logical fault or a technical problem—the service responds with a standardized JSON error structure. The HTTP status code indicates the nature of the error, using commonly recognized codes for clarity:

* **400 Bad Request**: The request was improperly formatted or contained invalid parameters.
* **401 Unauthorized**: The request lacked a valid authentication token; login is required.
* **403 Forbidden**: The current token does not grant access to the requested resource.
* **404 Not Found**: The requested resource was not found on the server.
* **500 Internal Server Error**: The server encountered an unexpected condition.

Each error response is structured to provide meaningful insight into the problem, assisting in efficient diagnosis and resolution.

```js
{
  "result": "ERR",
  "status": 400,
  "message": "errMsg_organizationIdisNotAValidID",
  "errCode": 400,
  "date": "2024-03-19T12:13:54.124Z",
  "detail": "String"
}
```

  
## Accessing the Backend Using Rest API

Each backend service has its own URL for each deployment environment. Users may want to test the frontend in one of the three deployments—preview, staging, or production. 
Please ensure that the home page includes a deployment server selection option so that, as the frontend coding agent, you can set the base URL for all services.

The base URL of the application in each environment is as follows:

* **Preview:** `https://workforceos.prw.mindbricks.com`
* **Staging:** `https://workforceos-stage.mindbricks.co`
* **Production:** `https://workforceos.mindbricks.co`

For the auth service, the base URLs are:

* **Preview:** `https://workforceos.prw.mindbricks.com/auth-api`
* **Staging:** `https://workforceos-stage.mindbricks.co/auth-api`
* **Production:** `https://workforceos.mindbricks.co/auth-api`

For each other service, append `/{serviceName}-api` to the environment base URL.

Any request that requires login must include a valid token in the Bearer authorization header.

Please note that for each service in the project (which will be introduced in following prompts) will use a different address so it is a good practice to define a separate client for each service in the frontend application lib source. Not only the different base urls, some services even may need different access rules when shaping the request. 

Services may be deployed to the preview server, staging server, or production server. Therefore, each service has 3 access URLs.
The frontend application must support all deployment environments during development, and the user should be able to select the target API server on the home page.



## Multi-Tenancy Management

**THIS APPLICATION IS MULTI-TENANT**

This application is multi-tenant. Tenant data is isolated per `company`, and tenant-level records are attached to `companyId`.
For frontend, tenant context is resolved from frontend routing context (URL prefix in preview/test, subdomain in production) and then forwarded to backend through header.

### Tenant Routing Contract (Required)

- SaaS pages: `/`
- Tenant pages: `/{tenantCodename}/...`
- Example: `/babil/login`
- All tenant-specific pages must keep `/{tenantCodename}` prefix.

In preview/test, URL prefix simulates tenant selection. In production, tenant is usually resolved from subdomain (e.g. `babil.appname...`).
In both modes, backend tenant targeting must always be done by header.

```js
headers["mbx-company-codename"] = tenantCodenameFromUrl;
```

URL/subdomain is only a frontend tenant selection mechanism. Backend API calls must always claim tenant with header.
If no tenant codename is sent, backend assumes SaaS/root tenant (`root`).

### Sample Company Tenant

The application backend also includes a sample tenant created with a sample tenant owner, who has the same email and password of the superadmin. This sample is created in the backend to be able to test the multi-tenant behaviour of the frontend at the beginning.

The sample company has codename `babil`. Use `/babil/...` prefixed pages and send `mbx-company-codename: babil` in tenant-scoped requests for testing.


## Home Page

First build a home page which shows some static content about the application, and has got login and registration (if is public) buttons. The home page should be updated later according to the content that each service provides, as a frontend developer use best and common practices to reflect the service content to the home page. User may also give extra information for the home page content in addition to this prompt.

Note that this page should include a deployment (environment) selection option to set the base URL. Set the default to `production`.

After user logs in, page header should show the current login state as in modern web pages, logged in user fullname, avatar, email and with a logout link, make a fancy current user component. The home page may have different views before and after login.


Since this is a multi-tenant application, SaaS home and tenant home should be different.

### SaaS Home (`/`)

Build a landing page with:
- Left area: project full name and project description
- Two primary buttons:
  - **Login To SaaS** (root tenant login entry)
  - **Register New Company** (show only when tenant owner registration is public)
- Bottom small link: **See Companies**

When user clicks **See Companies**, open a left sliding drawer and fetch tenant list with `listBriefCompanies`.
Clicking a tenant should navigate to `/{tenantCodename}` tenant homepage.

### Tenant Home (`/{tenantCodename}`)

Create a simple tenant homepage that shows tenant name/fullname/avatar and includes:
- Login button
- Register button only when tenant-user registration is public

Tenant homepage data should be fetched with tenant-level public API `getCompanyHome` while sending `mbx-company-codename` from URL context.

All tenant pages should keep tenant context in frontend routing. Regardless of routing method, all backend calls from tenant context must include `mbx-company-codename` header.

### Tenant API Contract (Current)

Use the following auth APIs for tenant information access:

- Public brief list for landing/tenant selection: `listBriefCompanies`
- Public brief single tenant: `getBriefCompany` (`/briefcompanies/:codename`)
- Public tenant-home read in tenant scope: `getCompanyHome` (`/companyhome/:codename`)
- Logged-in tenant-level read: `getCompany` (`/companies`, tenant id resolved from tenant context/session)
- Tenant profile read for tenant managers: `getCompanyProfile` (`/companyprofile`, id resolved from tenant header/session)
- SaaS-level tenant account read/list: `getCompanyAccount` and `listCompaniesAccounts`


### `List Briefcompanies` API
Get a list of companies, this route can be called by public, no login required


**Rest Route**

The `listBriefCompanies` API REST controller can be triggered via the following route:

`/v1/briefcompanies`


**Rest Request Parameters**
The `listBriefCompanies` api has got no request parameters.    




**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/briefcompanies**
```js
  axios({
    method: 'GET',
    url: '/v1/briefcompanies',
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**

This route's response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "companies",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"companies": [
		{
			"isActive": true
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```




### `Get Companyhome` API
Get public tenant-home information in tenant level.


**Rest Route**

The `getCompanyHome` API REST controller can be triggered via the following route:

`/v1/companyhome/:codename`


**Rest Request Parameters**


The `getCompanyHome` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| codename  | String  | true | request.params?.["codename"] |
**codename** : The codename of the company to fetch



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/companyhome/:codename**
```js
  axios({
    method: 'GET',
    url: `/v1/companyhome/${codename}`,
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**

This route's response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "company",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"company": {
		"isActive": true
	}
}
```




### `Get Company` API
Get a company in current tenant scope. A protected tenant-level route for logged-in users.


**Rest Route**

The `getCompany` API REST controller can be triggered via the following route:

`/v1/companies`


**Rest Request Parameters**
The `getCompany` api has got no request parameters.    




**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/companies**
```js
  axios({
    method: 'GET',
    url: '/v1/companies',
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "company",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"company": {
		"id": "ID",
		"name": "String",
		"codename": "String",
		"fullname": "String",
		"avatar": "String",
		"ownerId": "ID",
		"industry": "String",
		"companySize": "String",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```




### `Get Companyprofile` API
Get tenant profile information in tenant level. A private route for tenantOwner and tenantAdmin.


**Rest Route**

The `getCompanyProfile` API REST controller can be triggered via the following route:

`/v1/companyprofile`


**Rest Request Parameters**
The `getCompanyProfile` api has got no request parameters.    




**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/companyprofile**
```js
  axios({
    method: 'GET',
    url: '/v1/companyprofile',
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "company",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"company": {
		"id": "ID",
		"name": "String",
		"codename": "String",
		"fullname": "String",
		"avatar": "String",
		"ownerId": "ID",
		"industry": "String",
		"companySize": "String",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```




### `Get Companyaccount` API
Get tenant account information by id. A private SaaS-level route for superAdmin, saasAdmin and saasUser.


**Rest Route**

The `getCompanyAccount` API REST controller can be triggered via the following route:

`/v1/companyaccounts/:companyId`


**Rest Request Parameters**


The `getCompanyAccount` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| companyId  | ID  | true | request.params?.["companyId"] |
**companyId** : The id of the company account to fetch



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/companyaccounts/:companyId**
```js
  axios({
    method: 'GET',
    url: `/v1/companyaccounts/${companyId}`,
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "company",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"company": {
		"id": "ID",
		"name": "String",
		"codename": "String",
		"fullname": "String",
		"avatar": "String",
		"ownerId": "ID",
		"industry": "String",
		"companySize": "String",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```




### `List Companiesaccounts` API
List tenant accounts in SaaS level for superAdmin, saasAdmin and saasUser.


**Rest Route**

The `listCompaniesAccounts` API REST controller can be triggered via the following route:

`/v1/companyaccounts`


**Rest Request Parameters**



**Filter Parameters**

The `listCompaniesAccounts` api supports 5 optional filter parameters for filtering list results:

**name** (`String`): A string value to represent one word name of the company

- Single (partial match, case-insensitive): `?name=<value>`
- Multiple: `?name=<value1>&name=<value2>`
- Null: `?name=null`


**codename** (`String`): A string value to represent a unique code name for the company which is generated automatically using name

- Single (partial match, case-insensitive): `?codename=<value>`
- Multiple: `?codename=<value1>&codename=<value2>`
- Null: `?codename=null`


**fullname** (`String`): A string value to represent the fullname of the company

- Single (partial match, case-insensitive): `?fullname=<value>`
- Multiple: `?fullname=<value1>&fullname=<value2>`
- Null: `?fullname=null`


**avatar** (`String`): A string value represent the url of the company avatar. Keep null for random avatar.

- Single (partial match, case-insensitive): `?avatar=<value>`
- Multiple: `?avatar=<value1>&avatar=<value2>`
- Null: `?avatar=null`


**ownerId** (`ID`): An ID value to represent the user id of company owner who created the tenant

- Single: `?ownerId=<value>`
- Multiple: `?ownerId=<value1>&ownerId=<value2>`
- Null: `?ownerId=null`



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/companyaccounts**
```js
  axios({
    method: 'GET',
    url: '/v1/companyaccounts',
    data: {
    
    },
    params: {
    
        // Filter parameters (see Filter Parameters section above)
        // name: '<value>' // Filter by name
        // codename: '<value>' // Filter by codename
        // fullname: '<value>' // Filter by fullname
        // avatar: '<value>' // Filter by avatar
        // ownerId: '<value>' // Filter by ownerId
            }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "companies",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"companies": [
		{
			"id": "ID",
			"name": "String",
			"codename": "String",
			"fullname": "String",
			"avatar": "String",
			"ownerId": "ID",
			"industry": "String",
			"companySize": "String",
			"isActive": true,
			"recordVersion": "Integer",
			"createdAt": "Date",
			"updatedAt": "Date",
			"_owner": "ID"
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```




Do not use deprecated tenant APIs such as `getCompanyByCodename` or `listRegisteredCompanies`.



## Initial Navigation Structure

Build the initial navigation/sidebar with placeholder pages for each area of the application. These will be implemented in detail by the subsequent prompts:

**SaaS Level:**
- Home / Landing
- Login (SaaS)
- Dashboard (after login)

**Tenant Level (`/{tenantCodename}/...`):**
- Tenant Home
- Login
- Register
- Verification
- Profile
- User Management (admin)
- EmployeeProfile Service Pages
- ScheduleManagement Service Pages
- AttendanceManagement Service Pages
- TaskManagement Service Pages
- LeaveManagement Service Pages
- PayrollReporting Service Pages
- AnnouncementManagement Service Pages
- AiWorkforceAnalytics Service Pages
- SubscriptionManagement Service Pages
- AgentHub Service Pages

Create these as placeholder/dummy pages with a title and "Coming soon" note. They will be filled in by the following prompts.

## What To Build Now

With this prompt, build:
1. **Project infrastructure** — routing (using `react-router` v7 — import from `react-router`, not `react-router-dom`), layout, environment config, API client setup (one client per service)
2. **Home page** with environment selector, login/register buttons, project description
3. **SaaS landing** and **Tenant home** pages with tenant selection drawer
4. **Placeholder pages** for all navigation items listed above
5. **Common components** — header with user info, navigation sidebar/menu, layout wrapper

Do **not** implement authentication flows, registration, or any service-specific features yet — those will be covered in the next prompts.

## Common Reminders

1. When the application starts, please ensure that the `baseUrl` is set to the production server URL, and that the environment selector dropdown has the **Production** option selected by default.
2. Note that any API call to the application backend is based on a service base URL. Auth APIs use `/auth-api` prefix, and each business service uses `/{serviceName}-api` prefix after the application's base URL.
3. The deployment environment selector will only be used in the home page. If any page is called directly bypassing the home page, the page will use the stored or default environment.
