Technology

September 25, 2026

Building a Context-Aware Help System That Scales Across Tenants

← Back to Blog

The Problem with Help Content

Every SaaS platform faces the same documentation dilemma: help content that lives in a wiki or PDF quickly drifts out of sync with the actual application. But help content embedded directly in the app can't account for tenant-specific customizations — renamed fields, hidden features, or different workflows.

Our incentive management platform serves dozens of tenants, each with their own field labels, required fields, and role configurations. A static help article that says "Enter the Account ID" is useless when a tenant has renamed that field to "Customer Number." And showing documentation for features a user's role can't access just creates confusion.

We needed a help system that is:

  • Version-controlled — help content lives in the same repo as the code it documents
  • Tenant-aware — field names and descriptions reflect each tenant's customizations
  • Role-aware — users see which roles can access each feature
  • Low-friction — adding help for a new screen shouldn't require a deployment

The Architecture

We settled on a three-layer approach:

1. Markdown in the Repo

Help articles are written as markdown files and stored in a Help/ folder in the API project. Each file follows a standard structure with sections for Overview, Why Use This Feature, Field Descriptions, Actions, and Notes. A manifest file maps each article to its corresponding function ID in the system.

This gives us version control, code review, and the ability to update help content in the same pull request that changes the feature.

2. Startup Seeding

When the API starts, a hosted service reads the help manifest and upserts each article into the database. If the article already exists, it updates the content. If the function doesn't have an article yet, it creates one and links them. This means help content deploys with the application — no separate publishing step.

3. Runtime Merging

When a user clicks the help button, the API fetches the base article and then enriches it:

  • Field descriptions are merged with the tenant's DataColumn customizations. If a tenant has renamed "Account ID" to "Customer Number" and added their own description, that's what the user sees. Fields the tenant has disabled are hidden.
  • Roles are pulled from the tenant's role configuration. Users see which roles in their organization have access to this feature.

The Markdown Format

Each help file uses a simple structure that's easy to write and parse:

### Overview

Create a new Commercial or Residential Account.

### Why Use This Feature

Accounts are the central entity for linking incentives, 
managing users, and tracking activity...

### Field Descriptions

| Field | Description |
|-------|-------------|
| Account Type | Select Commercial or Residential... |
| Account ID | Enter a unique identifier... |

### Actions

| Action | Description |
|--------|-------------|
| Validate Address | Verifies the address via USPS... |
| Save | Creates the new account... |

The API parses these sections and returns structured JSON that the frontend renders in a modal. Tables become lists with labels and descriptions. This separation means we can change how help is displayed without touching the content.

The Merge Logic

The interesting part is how we merge system defaults with tenant customizations without losing either.

The manifest file specifies which database table each help article relates to. When a user requests help, we:

  1. Fetch the tenant's active DataColumns for that table, ordered by their configured position
  2. Build a lookup of default descriptions from the markdown, normalized by field name
  3. Walk through the tenant's columns: use the tenant's label, and prefer the tenant's description if set, otherwise fall back to the default

This means a tenant who hasn't customized anything sees the standard documentation. A tenant who has renamed fields and added descriptions sees their version. And if we update the default description in a future release, tenants who haven't overridden it automatically get the improvement.

The Frontend Component

On the React side, a HelpButton component takes a function ID and handles everything:

  • Clicking the button fetches help from the BFF (which proxies to the API)
  • The response is cached so subsequent clicks are instant
  • Content is rendered in a modal with sections for overview, fields, actions, and roles
  • The modal shows when the content was last updated

Adding help to a new screen is a one-liner: <HelpButton functionId="..." />

What We Learned

Start with structure. The temptation is to allow freeform help content. But structured sections (overview, fields, actions) make the content easier to write, easier to display consistently, and easier to merge with tenant data.

Seed on startup, not on deploy. We originally considered a separate migration step to load help content. Running it on startup is simpler — the content is always in sync with the deployed code, and there's no extra step to remember.

Field name normalization matters. Tenant column names might be "AccountID", "Account ID", or "Account_ID". The merge logic strips whitespace and special characters before matching. Small detail, but it makes the difference between help that works and help that's blank.

Show what's relevant. Displaying the roles that have access to a feature turned out to be more useful than we expected. Users frequently ask "why can't I see this?" The help modal now answers that question directly.

What's Next

We're extending this pattern to include:

  • Video embeds for complex workflows
  • Links to related help articles
  • Search across all help content
  • Analytics on which help articles users access most (to prioritize improvements)

The foundation is solid: structured content in the repo, runtime enrichment from tenant config, and a simple component to surface it all. Everything else builds on that.

Related to Technology

Learn more about our solutions for this market.

View Technology →

Ready to Transform Your Incentive Programs?

Let's discuss how Incentit can help streamline your rebate and spiff management.

Contact Us← Back to Blog
Building a Context-Aware Help System That Scales Across Tenants