WORKFORCEOS

FRONTEND GUIDE FOR AI CODING AGENTS - PART 1 - Project Introduction & 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:

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:

{
  "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": []
}

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:

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

{
  "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:

For the auth service, the base URLs are:

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)

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.

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:

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:

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:

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

  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.

{
	"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

  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.

{
	"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

  axios({
    method: 'GET',
    url: '/v1/companies',
    data: {
    
    },
    params: {
    
        }
  });

REST Response

{
	"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

  axios({
    method: 'GET',
    url: '/v1/companyprofile',
    data: {
    
    },
    params: {
    
        }
  });

REST Response

{
	"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

  axios({
    method: 'GET',
    url: `/v1/companyaccounts/${companyId}`,
    data: {
    
    },
    params: {
    
        }
  });

REST Response

{
	"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

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

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

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

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

REST Request To access the api you can use the REST controller with the path GET /v1/companyaccounts

  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

{
	"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:

Tenant Level (/{tenantCodename}/...):

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.