Skip to main content

Documentation Site — Setup & Administration

This guide covers how to set up the Bestway BC documentation site from scratch, configure the Azure deployment pipeline, manage authentication, and keep the site content current.

Architecture Overview

The documentation site is a static website built with Docusaurus and hosted on Azure Static Web Apps. All access requires Entra ID (Azure AD) authentication — there is no anonymous access.

Docs Site Build Pipeline

Content lives where developers write it — extension READMEs, CHANGELOGs, CHANGE documents, and test plans stay in their extension folders. The sync script copies them into the Docusaurus content tree at build time. Purpose-written pages (landing page, stakeholder portal, deployment guide) live directly in docs-site/docs/.

Azure Infrastructure Reference

The documentation site runs on the following Azure resources. All resources are in the Bestway Pay-As-You-Go subscription under tenant 823af2fd-2570-49e5-b22c-1614ac645202.

Static Web App

PropertyValue
Namebestway-bc-docs
Resource Grouprg-bestway-docs
SKUStandard (required for custom Entra authentication)
RegionEast US 2
Custom Domainhttps://devdocs.bestwaycorp.us
Default URLhttps://agreeable-river-053a1760f.2.azurestaticapps.net
Application SettingsAAD_CLIENT_ID, AAD_CLIENT_SECRET (secret — stored in SWA config, not in source)

Entra App Registration

PropertyValue
Display NameBestway BC Docs
Application (Client) IDe0536e61-e0e8-48ac-87d9-4d047c80b81d
Sign-in AudienceSingle tenant (AzureADMyOrg)
Redirect URIshttps://devdocs.bestwaycorp.us/.auth/login/aad/callback and https://agreeable-river-053a1760f.2.azurestaticapps.net/.auth/login/aad/callback
Client Secret ExpiryMarch 2028 — set a calendar reminder to rotate 30 days before

Azure DevOps Pipeline

PropertyValue
Pipeline NameDeploy Docs Site
OrganizationBestwayUSA
ProjectBestway BC Development
RepositoryBestway BC Development
YAML Pathdocs-site/azure-pipelines.yml
Branch Triggermain
Secret VariableAZURE_STATIC_WEB_APPS_API_TOKEN (deployment token — stored as secret pipeline variable)

Resource Relationships

Azure DevOps Pipeline ("Deploy Docs Site")
│ uses AZURE_STATIC_WEB_APPS_API_TOKEN

Static Web App (bestway-bc-docs)
│ authenticates via AAD_CLIENT_ID / AAD_CLIENT_SECRET

Entra App Registration (Bestway BC Docs)
│ validates tokens against tenant 823af2fd-...

Bestway Entra Directory (employees + B2B vendor guests)

Initial Azure Setup

1. Create the Azure Static Web App Resource

  1. Sign in to the Azure Portal
  2. Create a resource → search for Static Web AppCreate
  3. Configure:
SettingValue
SubscriptionBestway's Azure subscription
Resource GroupSelect or create a resource group (e.g., rg-bestway-docs)
Namebestway-bc-docs
Plan typeStandard (required for custom Entra authentication)
RegionEast US (or nearest to Bestway's primary user base)
SourceAzure DevOps
OrganizationBestway's Azure DevOps organization
ProjectThe project containing the BC Development repository
RepositoryBestway BC Development
Branchmain
  1. Under Build Details:
SettingValue
Build PresetsCustom
App locationdocs-site
API location(leave blank)
Output locationbuild
  1. Click Review + createCreate

  2. After creation, navigate to the resource and note:

    • The URL (e.g., https://happy-river-0a1b2c3d4.azurestaticapps.net)
    • The Deployment token (under Manage deployment token on the Overview page)

2. Create the Entra App Registration

  1. Sign in to the Entra admin center
  2. Navigate to IdentityApplicationsApp registrationsNew registration
  3. Configure:
SettingValue
NameBestway BC Docs
Supported account typesAccounts in this organizational directory only (Single tenant)
Redirect URIWeb — https://<your-swa-domain>/.auth/login/aad/callback

Replace <your-swa-domain> with the URL from step 1.6 (e.g., https://happy-river-0a1b2c3d4.azurestaticapps.net).

  1. Click Register
  2. On the app's Overview page, copy the Application (client) ID
  3. Navigate to Certificates & secretsNew client secret
    • Description: SWA Auth
    • Expiry: 24 months (set a calendar reminder to rotate before expiry)
    • Copy the Value immediately — it won't be shown again

3. Configure Static Web App Application Settings

  1. In the Azure Portal, navigate to the Static Web App resource (bestway-bc-docs)
  2. Go to ConfigurationApplication settings
  3. Add two settings:
NameValue
AAD_CLIENT_IDThe Application (client) ID from step 2.5
AAD_CLIENT_SECRETThe client secret value from step 2.6
  1. Click Save

These values are referenced by staticwebapp.config.json in the repo — the config file uses clientIdSettingName and clientSecretSettingName to point to these application settings rather than hardcoding credentials.

4. Configure the Azure DevOps Pipeline

  1. In Azure DevOps, navigate to PipelinesNew pipeline
  2. Select Azure Repos Git → select the Bestway BC Development repository
  3. Select Existing Azure Pipelines YAML file
  4. Set the path to docs-site/azure-pipelines.yml
  5. Click ContinueVariablesNew variable:
NameValueKeep this value secret
AZURE_STATIC_WEB_APPS_API_TOKENThe deployment token from step 1.6Yes
  1. Click SaveRun

The pipeline will run, build the site, and deploy it to Azure Static Web Apps.

5. Verify the Deployment

  1. Open the Static Web App URL in an incognito/private browser window
  2. You should be redirected to the Microsoft login page
  3. Sign in with a Bestway Entra account
  4. After authentication, the documentation site should load with the landing page

If authentication fails, check:

  • The redirect URI in the Entra app registration matches the SWA URL exactly (including https://)
  • Both AAD_CLIENT_ID and AAD_CLIENT_SECRET are set in the SWA application settings
  • The openIdIssuer in staticwebapp.config.json uses the correct tenant ID (823af2fd-2570-49e5-b22c-1614ac645202)

Granting Vendor Access

Vendors access the site through Entra B2B guest accounts.

  1. In the Entra admin center, navigate to IdentityUsersInvite external user
  2. Enter the vendor's email address
  3. Add a personal message explaining what the site is and how to access it
  4. Click Invite

The vendor will receive an email invitation. After accepting, they can sign in to the documentation site with their own email credentials.

To revoke access, delete the guest user from Entra.

How the Build Pipeline Works

The pipeline is defined in docs-site/azure-pipelines.yml and triggers automatically on pushes to main that modify:

  • Any file in docs-site/
  • Any .md file anywhere in the repo
  • Any app.json file (version bumps update the Extension Directory page)

Pipeline Steps

StepWhat It DoesDuration
CheckoutClones the full repo (with fetchDepth: 0 for git history)~10s
Install Node.jsSets up Node.js 20 LTS~5s
Install dependenciesRuns npm ci in docs-site/~15s
Sync contentRuns npm run sync — discovers markdown files, classifies them, injects frontmatter, copies to the Docusaurus content tree~5s
Build siteRuns npm run build — Docusaurus generates static HTML~30s
DeployPushes the build/ output to Azure Static Web Apps~15s

Total pipeline duration: approximately 60-90 seconds.

Manual Rebuild

To trigger a rebuild without a code change:

  1. In Azure DevOps, navigate to Pipelines
  2. Select the docs site pipeline
  3. Click Run pipelineRun

This is useful after converting a Word document to markdown or after making changes that don't trigger the automatic path filters.

Content Management

How Content Gets on the Site

There are two types of content:

Synced content — Markdown files that live in extension folders and are auto-discovered by the sync script. When you add or edit a .md file in any extension folder, the site picks it up on the next build.

You write...It appears at...
{ext}/README.md/extensions/{slug}/
{ext}/docs/CHANGELOG.md/extensions/{slug}/changelog
{ext}/docs/CHANGE-v*.md/extensions/{slug}/changes/{version}
{ext}/test/README.md/extensions/{slug}/testing/
{ext}/docs/*.md/extensions/{slug}/docs/{name}
docs/STATUS-UPDATE-*.md/stakeholders/status-updates/{name}
docs/CONTRIBUTING.md/development/contribution-guidelines
tools/README.md/tooling/test-plan-library

Purpose-written content — Pages authored directly in docs-site/docs/ that don't exist elsewhere in the repo. These are committed to git normally.

PageFile
Landing pagedocs-site/docs/home/index.md
Stakeholder overviewdocs-site/docs/stakeholders/overview.md
Extension directorydocs-site/docs/stakeholders/extension-directory.md
Recent changesdocs-site/docs/stakeholders/recent-changes.md
Deployment guidedocs-site/docs/development/deployment-guide.md
This pagedocs-site/docs/development/docs-site-admin.md

Adding a New Extension's Docs

When a new extension is added to the repo:

  1. Create a README.md in the extension's root folder — this becomes the extension's overview page
  2. Create a docs/CHANGELOG.md if the extension has releases
  3. Push to main — the sync script auto-discovers the new files

The extension will appear in the sidebar automatically. To control its display name, sidebar position, or group it with related extensions, edit docs-site/content-map.yaml.

Customizing the Sidebar

The sidebar is controlled by docs-site/content-map.yaml. Three types of customization:

Grouping related extensions:

groups:
- label: "Nextiva Integration"
slug: nextiva-integration
description: "Phone and email integration with Nextiva"
extensions:
- "Cambay Solutions_BC Dialing Application"
- "BCDialingAzure"

Overriding display names:

labels:
"Cambay Solutions_BC Dialing Application": "BC Dialing Application"

Controlling order:

order:
extensions:
- "BestwayUSA"
- "nextiva-integration"
- "Service Order Lockout"

Extensions not listed in the order section appear alphabetically after the listed ones.

Updating the Extension Directory

The Extension Directory page (docs-site/docs/stakeholders/extension-directory.md) lists all extensions with their current versions. When an extension version is bumped in app.json, update the version in this page as well.

Updating Recent Changes

The Recent Changes page (docs-site/docs/stakeholders/recent-changes.md) is manually maintained. When a new version of an extension is released, add an entry at the top of the page with the version, date, and key changes (pulled from the extension's CHANGELOG).

Local Development

To preview the site locally before pushing:

cd docs-site
npm install # first time only
npm run dev # dev server + file watcher at http://localhost:3000

npm run dev starts two things:

  1. The Docusaurus dev server with hot reload
  2. A file watcher that monitors all markdown and app.json files across the repo

When you edit any markdown file — whether it's a purpose-written page in docs-site/docs/ or a synced file like an extension README or CHANGELOG — the watcher detects the change, re-runs the sync script, and the browser updates automatically.

CommandBehavior
npm run devDev server + file watcher (recommended for authoring)
npm startDev server only — syncs once at startup, no live watching
npm run watchFile watcher only — useful if the dev server is already running

To build the production site locally:

cd docs-site
npm run build
npx serve build # serves at http://localhost:3000

Troubleshooting

Build fails with MDX parsing errors

The Docusaurus config uses markdown.format: 'md' to treat all .md files as standard CommonMark instead of MDX. If a synced markdown file contains JSX-like syntax ({variables}, <angle brackets>, etc.), this setting prevents parsing errors. If you need MDX features (React components), use the .mdx extension for that specific file.

Sync script reports "Unclassified" files

The sync script classifies files by path pattern. If a markdown file in the repo doesn't match any classification rule, it's logged as unclassified and skipped. To fix: either move the file to a recognized location or add a new classification rule to docs-site/scripts/sync-content.js.

Authentication redirect loop

If the site redirects to login repeatedly without loading:

  1. Verify AAD_CLIENT_ID and AAD_CLIENT_SECRET in the SWA application settings
  2. Verify the redirect URI in the Entra app registration matches the SWA URL
  3. Check that the client secret hasn't expired
  4. Clear browser cookies for the SWA domain

Pipeline fails at "Deploy to Azure Static Web Apps"

The deployment token may have been rotated. Regenerate it from the SWA resource in the Azure Portal (Manage deployment token) and update the AZURE_STATIC_WEB_APPS_API_TOKEN pipeline variable in Azure DevOps.

Search returns no results

The search index is built at build time by the @easyops-cn/docusaurus-search-local plugin. If search returns nothing:

  1. Verify search-index.json exists in the build/ output
  2. Try a full rebuild (npm run build from scratch)
  3. Check that the search plugin is configured in docusaurus.config.js

Key Files Reference

FilePurpose
docs-site/docusaurus.config.jsSite configuration — title, theme, navbar, search, markdown format
docs-site/sidebars.jsSidebar structure — 4 named sidebars (stakeholders, extensions, development, tooling)
docs-site/content-map.yamlSidebar customization — groups, labels, order, exclusions
docs-site/scripts/sync-content.jsContent discovery and sync engine
docs-site/staticwebapp.config.jsonAzure Static Web Apps auth configuration
docs-site/azure-pipelines.ymlAzure DevOps CI/CD pipeline
docs-site/src/css/custom.cssTheme overrides — Roboto font, Bestway navy/blue colors
docs-site/src/components/UatTestRunner/Interactive UAT test runner React component
docs-site/src/data/extensions.jsonAuto-generated extension metadata (from sync script)

Client Secret Rotation

The Entra app registration client secret expires after the period set during creation (default: 24 months). To rotate:

  1. In the Entra admin center, navigate to the Bestway BC Docs app registration
  2. Go to Certificates & secretsNew client secret
  3. Create a new secret, copy the value
  4. In the Azure Portal, update the AAD_CLIENT_SECRET application setting on the Static Web App resource
  5. Delete the old secret from the Entra app registration

Set a calendar reminder for 30 days before expiry.