CHW Connect is a license-free, customizable digital platform designed to support Community Health Worker (CHWs) and the organizations that manage and support them.
Originally developed to support Grow Great Champions—community healthcare workers who conduct home visits with pregnant women, new mothers, and young children—the platform enables frontline workers to deliver high-quality care, identify risks early, and ensure clients receive appropriate support and referrals.
CHW Connect provides a complete digital ecosystem consisting of:
- A Progressive Web App (PWA) for Community Health Workers
- An Admin Portal for supervisors and team leads
Built with an offline-first approach, CHW Connect is designed for use in low-connectivity environments and supports organizations delivering maternal, child, and community healthcare programs at scale.
Email: help@ecdconnect.co.za
- Frontend PWA: React, Redux, TypeScript
- Admin Portal Website: React and Apollo Client
- Backend: .NET 10 Core, GraphQL (Hot Chocolate), Entity Framework, PostgreSQL.
- Training: Moodle - see below for details on the training module
- SMS Sending: BulkSMS, iTouch, or [SMSPortal] (https://smsportal.com/)
- Holidays: RapidAPI - an API to get the South African Holidays for attendance tracking purposes etc
- Analytics: Google Analytics, Google Tag Manager and Google Data Studio - for analytics, event tracking and reporting
- The App uses Service Workers and Redux to manage the offline capability.
- "Offline first" PWA, allowing a large portion of functionality to be used when offline
- Register new child clients and pregnant clients
- Complete pregnant client visits
- Complete child client visits, showing age-appropriate questions
- Automatic referrals and referral tracking
- Generate summaries to share with caregivers and clients
Grafana has been used but any reporting tool that can connect to a PostgreSQL database will work. Currently there is no integration with any reporting tool, i.e. single sign-on or permissioning.
- User based logins that allow any CHW to sign up to the system using the Frontend PWA.
- User based logins that allow any Administrator or Team Lead to login, invite new users & maintain the system.
- .NET 10 using the following to function:
- Hot Chocolate - A open-source GraphQL server
- Banana Cake Pop - This provides a playground and documentation layer for easy reading of the GraphQL end points
- Entity Framework Core
- ASP.NET Core Identity for authentication and User management
- PostgreSQL for the database
- Ionic React using Functional components, to support possible future migration to a native mobile application
- Redux Toolkit for state management with persistence
- TypeScript for improved syntax support
- Tailwind UI for Form layouts, tables, modal windows for clean & modern look
- heroicons for SVG icons
- React using Functional components
- Using Apollo Client GraphQL for declarative data fetching
- Tailwind UI for Form layouts, tables, modal windows for clean & modern look
- heroicons for SVG icons
The system was developed making use of Azure hosting. Azure resources that are used:
The Frontend, Admin Portal and API are all hosted on separate Azure Web Apps.
More details about the Azure setup can be found further below in the example setup.
The system can be hosted in other cloud providers as long as they provide PostgreSQL resources and the capability of running .NET code on Linux. Both AWS and GCP are capable. Currently the file storage for the system makes use of file system or Azure Storage. There isn't provision for AWS S3 or GCP storage but it is a relatively simple task to extend the system to support one or both of them.
The system can be hosted on-prem using PostgreSQL, IIS or Apache, and file system for storage.
- SSL certificates are recommended for the respective, frontend, Admin Portal and API url's
- JWT tokens for authorisation with refresh endpoints
Please note this is not a requirement to run the system. If the Moodle configuration in the system is not setup, the Training tab will not be available.
The app has a training module that can display Moodle training courses within an iframe.
In order to enable this functionality, the requirements are:
- Moodle 4.5
- PHP 8.3 or later (compatible with Moodle 4.5)
- Cohort enrolment enabled
- The Moodle database must be on PostgreSQL 13 or later
- The Moodle database must be accessible from the backend with read/insert/delete permission
- The Moodle UI theme needs to be as minimal as possible as it will be displayed within an iframe
When the Training module of the frontend is accessed, the backend is queried to create/update the current user in the Moodle database and enroll the user, using cohort enrolment, in the courses. The frontend then logs into Moodle in the iframe using the user's Moodle credentials and the courses assigned to the user will be display on the Moodle landing page.
Configuration of the backend for Moodle is discussed below.
If further assistance for setup of Moodle is required consider contacting a Moodle partner, e.g. Limina Education Services
Training courses have been developed for the CHW Connect offering. Email the email to find out more.
- Node version ^24.14.1 or up
- Lerna installed for multiple package management,
npm install --global lerna@4.0.0 - Yarn as an optional alternative to NPM,
npm install --global yarn@1.22.22 - .NET 10.0
- PostgreSQL Server - version 13 or later.
- Visual Studio Code for frontend development.
- Visual Studio 2026 Community Edition for backend development.
- Install VS Code
- Clone the repo.
- Install node 24.14.1 or later.
- In the root folder:
npm install --global lerna@4.0.0
npm install --global yarn@1.22.22 - Run
yarnto update/install the packages. - Run
yarn fixmodulesto correct modules using unsupported syntax - Run
yarn bootstrap. This will install all packages for the sub packages and src projects. After that it will build the packages for use and add them to the node modules of the projects have them as dependencies.
- Install PostgreSQL and create a database, e.g. ecdconnect. Run the sqlscripts/database.sql to create the initial database.
- Install VS 2026 Community Edition.
- VS solution file can be found in src/api.
- Update src/api/core-api/appsettings.json with the correct values for the database connection string.
- Start the PostgreSQL server
- Using Visual Studio run the solution. Verify that the browser page opens with the GraphQL schema.
- Ensure the backend is running
yarn appto run the Front End
- Ensure the backend is running
yarn portalto run the Admin Portal- Default username is Admin and password is Pass@123
There are currently two storage types: Azure Blob Storage or File System.
This is specified in the /src/api/core-api/appsettings.json file:
"Storage": {
"Type": "FileSystem",
"AzureBlob": {
},
"FileSystem": {
"Location": "\_Storage"
}
},
Storage.Type can be either FileSystem or AzureBlob
Storage.FileSystem.Location is the location for the file system store. This can be a rooted path, e.g. C:\Storage or relative path.
If Type is FileSystem, the following configuration should also be applied:
- Tenant table
- BlobStorageAddress should be the backend url, e.g. https://api.domain.co.za/storage or https://localhost:5001/storage
- ThemePath (if specified) should be be the backend url, e.g. https://api.domain.co.za/storage/theme/mytheme.json
- Settings.json files
- themeUrl should be https://api.domain.co.za/storage/theme/mytheme.json
If Type is AzureBlob:
- Tenant table
- BlobStorageAddress should be the blob storage url, e.g. https://mystorage.blob.core.windows.net
- ThemePath (if specified) should be be the backend url, e.g. https://mystorage.blob.core.windows.net/theme/mytheme.json
- Settings.json files
- themeUrl should be https://mystorage.blob.core.windows.net/theme/mytheme.json
Make sure that all references for the storage url are correct:
- ContentValue table
Check the Value column and update if necessary - Theme file
Make sure all urls to other files in the theme are correct.
Make the following changes if you will be using Moodle:
- Tenant table
- MoodleUrl = the url for the Moodle instance, e.g. https://moodle.mydomain.co.za
- MoodleConfig = json string as below, replacing as required:
{ "userTypes": [{ "userType": "*", "cohorts": ["course cohort name", "ui cohort name"] }], "database": { "type": "postgres", "connectionString": "Server=myserver.com;Database=moodle;Port=5432;User Id=admin@myserver;Password=123456;Ssl Mode=VerifyFull;" }, "site": { "address": "https://moodle.mydomain.co.za", "defaultPassword": "abc@1234", "emailFormatString": "{0}@mydomain.co.za" } }
The platform sends smses for certain notifications. To configure SMS capability values in the SystemSetting table need to be set.
- Update
Notifications.SMSProviders.Sms.ProvidertoNotifications.SMSProviders.BulkSms - Update the following rows:
Notifications.SMSProviders.BulkSms.BasicAuthToken
Notifications.SMSProviders.BulkSms.Name
Notifications.SMSProviders.BulkSms.TokenId
Notifications.SMSProviders.BulkSms.TokenSecret
- Update
Notifications.SMSProviders.Sms.ProvidertoNotifications.SMSProviders.SMSPortal - Update the following rows:
Notifications.SMSProviders.SMSPortal.ApiKey
Notifications.SMSProviders.SMSPortal.ApiSecret
- Update
Notifications.SMSProviders.Sms.ProvidertoNotifications.SMSProviders.iTouch - Update the following rows:
Notifications.SMSProviders.iTouch.Password
Notifications.SMSProviders.iTouch.Username
To configure the system to allow for the sending of emails, edit the Notifications.EmailProviders.Smtp.% rows in SystemSetting table as required.
-
Create a Resource Group, e.g. rg-myapp
-
Create a Storage Account resource, e.g. stgmyapp, in rg-myapp.
- Allow Blob anonymous access: Enabled
- Allow storage account key access: Enabled
- Blob access tier: Hot
- Setup CORS to allow GET for Blob service.
-
Upload data to stgmyapp storage account.
- Create a content-image container with Anonymous access Level = Blob Upload all the files in _src/api/core-api/Storage/content-image to the container
- Create a theme container with Anonymous access Level = Blob Upload all the files, sub folders included, in _src/api/core-api/Storage/theme to the container
-
Create a PostgreSQL Flexible Server resource, e.g. sql-myapp, in rg-myapp.
- Add a database.
- Use pgAdmin or another tool to restore the database using your own backup or sqlscripts/database.sql.
-
Create an App Service Plan, e.g. asp-myapp, in rg-myapp.
- Operating System: Linux
- Pricing Plan: For dev/test B1 should be sufficient initially.
-
Create backend App Service (Web App), e.g. api-myapp, in rg-myapp.
- Basics:
- Publish: Code
- Runtime Stack: .NET 10
- Linux Plan: select your app service plan created above, asp-myapp
- Deployment:
- Select options to suit your requirements
- Networking:
- Enable public access: On
- Enable virtual network integration: Off
- Monitor & Secure:
- Enable Application Insights: Yes
- Basics:
-
Configure api-myapp:
- Settings - Environment Variables
- DOTNET_ENVIRONMENT = Development (or as required)
- Settings - Configuration
- Always on: On
- API - Cors
- Enable Access-Control-Allow-Credentials: Yes
- Allowed Origins: http://localhost:3000, http://localhost:3003, https://*.azurewebsites.net
- Monitoring - App Service logs
- Application Logging: File System
- Quote: 100
- Retention Period: 7
- Settings - Environment Variables
-
Create portal App Service (Web App), e.g. portal-myapp, in rg-myapp
- Basics:
- Publish: Code
- Runtime Stack: Node 24
- Linux Plan: select your app service plan created above, asp-myapp
- Deployment:
- Select options to suit your requirements
- Networking:
- Enable public access: On
- Enable virtual network integration: Off
- Monitor & Secure:
- Enable Application Insights: No
- Basics:
-
Configure portal-myapp:
- Settings - Configuration
- Startup Command:
npm i -g http-server && node --max-http-header-size=80000 /usr/local/lib/node_modules/http-server/bin/http-server --proxy http://127.0.0.1:8080?
- Startup Command:
- Settings - Configuration
-
Create PWA app App Service (Web App), e.g. app-myapp, in rg-myapp
- Basics:
- Publish: Code
- Runtime Stack: Node 24
- Linux Plan: select your app service plan created above, asp-myapp
- Deployment:
- Select options to suit your requirements
- Networking:
- Enable public access: On
- Enable virtual network integration: Off
- Monitor & Secure:
- Enable Application Insights: No
- Basics:
-
Configure app-myapp:
- Settings - Configuration
- Startup Command:
npm i -g http-server && node --max-http-header-size=80000 /usr/local/lib/node_modules/http-server/bin/http-server --proxy http://127.0.0.1:8080?
- Startup Command:
- Settings - Configuration
-
Database Configuration
- Tenant table:
- Where SiteAddress = localhost:3000, update as follows:
- SiteAddress = https://app-myapp.azurewebsites.net
- AdminSiteAddress = https://portal-myapp.azurewebsites.net
- BlobStorageAddress = https://stgmyapp.blob.core.windows.net
- Where SiteAddress = localhost:5001:
- SiteAddress = https://api-myapp.azurewebsites.net
- BlobStorageAddress = https://stgmyapp.blob.core.windows.net
- Where SiteAddress = localhost:3000, update as follows:
- SystemSetting table:
- Where FullPath = General.Azure.BlobStorageConnection
- Value = set to the connection string from the storage account > Security + networking > Access keys
- Run the following script, updating the values as required:
UPDATE "SystemSetting" SET "Value" = REPLACE("Value",'http://localhost:3000','https://app-myapp.azurewebsites.net') WHERE "Value" ILIKE '%http://localhost:3000%';
UPDATE "SystemSetting" SET "Value" = REPLACE("Value",'http://localhost:3003','https://portal-myapp.azurewebsites.net') WHERE "Value" ILIKE '%http://localhost:3000%';
- Where FullPath = General.Azure.BlobStorageConnection
- Tenant table:
-
Deploy Code
Deploy the code for the backend, portal, and app to the respective app services.- When deploying the backend remember to update/replace values in appsettings.json as required, e.g. database connection string.
- When deploying the portal and app, remember to update all the settings.json files:
- graphQlApi = https://api-myapp.azurewebsites.net/graphql/
- authApi = https://api-myapp.azurewebsites.net
- themeUrl = https://stgmyapp.blob.core.windows.net/....
-
Is it running?
- backend - navigate to https://api-myapp.azurewebsites.net/graphql. If you're shown the GraphQL Playground and shown the schema then all is running fine.
- app & portal - should be shown the login screen. View the network calls to confirm requests to the backend are succeeding. There will be an "onlinecheck" call every few minutes.