Platform Architecture
This page describes how the Rhino Group Documentation Platform is structured, what technology it runs on, and how clients are auto-discovered.
Technology Stack
| Component | Version / Detail |
|---|---|
| Framework | Docusaurus 3.x (TypeScript config) |
| React | 18 |
| TypeScript | 5.3 |
| Node.js | ≥ 20 |
| Search | Typesense 27.1 (self-hosted via Docker) |
| Web Server | nginx on self-hosted VPS |
| Authentication | HTTP Basic Auth (nginx level) |
| Scraper | typesense/docsearch-scraper Docker image |
Auto-Discovery Multi-Client Model
Unlike a traditional Docusaurus multi-instance setup (where each instance is manually declared in config), this platform auto-discovers clients from the filesystem.
At build time, docusaurus.config.ts scans the clients/ directory and creates a plugin-content-docs instance for each client it finds. No config file changes are needed when adding a new client.
clients/
{client-slug}/
index.md ← Client landing page (slug: /)
{site-slug}/
_category_.json ← Label, position, collapsed state
intro.md ← Site root doc
{section}/
_category_.json
doc-page.md
Key Functions in docusaurus.config.ts
| Function | Purpose |
|---|---|
buildClientDocsPlugin(slug) | Creates a docs plugin instance for a client |
slugToLabel(slug) | Converts a slug to a display label (checks customClientLabels first) |
customClientLabels | Override map for slugs that don't title-case correctly (e.g. gsm-outdoors → GSM Outdoors) |
URL Structure
/{client-slug}/ → Client landing page
/{client-slug}/{site-slug}/ → Site root doc
/{client-slug}/{site-slug}/{section}/{page} → Individual doc page
Examples:
/scottsdale-mint/→ Scottsdale Mint landing page/scottsdale-mint/retail/intro→ Retail site documentation/gsm-outdoors/middleware/features/orders-page→ GSM Outdoors middleware feature doc
Directory Layout
docs/ ← Repository root
├── clients/
│ ├── gsm-outdoors/
│ │ ├── index.md
│ │ └── middleware/
│ ├── scottsdale-mint/
│ │ ├── index.md
│ │ ├── retail/
│ │ ├── dealers/
│ │ └── middleware/
│ └── rhinogroup/
│ ├── index.md
│ └── documentation/ ← This section
├── src/
│ ├── css/custom.css
│ ├── pages/index.tsx ← Homepage with client cards
│ └── theme/SearchBar/index.tsx ← Faceted search bar
├── plugins/
│ └── docsearch-meta-plugin/ ← Injects client/site meta tags
├── sidebars/
│ └── autogenerated.ts ← Shared sidebar config
├── typesense/
│ ├── config.json ← Scraper config
│ ├── docker-compose.yml ← Typesense server + scraper
│ └── scrape.sh ← Scraper runner script
├── scripts/
│ └── create-new-client-site.ps1 ← Client/site creation wizard
├── docusaurus.config.ts ← Auto-discovery config
└── Agents.md ← Project documentation
Sidebar Management
Sidebars are auto-generated from the filesystem using _category_.json files and sidebar_position frontmatter. There are no manually-maintained sidebar TypeScript files per client.
_category_.json
Each category directory contains a _category_.json that defines its label and position:
{
"label": "🚀 Getting Started",
"position": 2,
"collapsed": false
}
sidebar_position Frontmatter
Each markdown file uses sidebar_position in its frontmatter to control ordering within its category:
---
sidebar_position: 1
id: overview
title: Architecture Overview
sidebar_label: Overview
---
Search Architecture
Search uses Typesense with faceted filtering by client and site:
- The
docsearch-meta-plugininjects<meta name="docsearch:client_tag">and<meta name="docsearch:site_tag">into built HTML - The scraper indexes these as faceted fields
- The swizzled
SearchBarcomponent provides client/site dropdown filters - Filters are applied as
filter_byparameters in Typesense queries
See Typesense Search for the full setup guide.
Build Pipeline
npm run build → build/ → deploy to /var/www/html/
The docsearch-meta-plugin runs as a postBuild hook — it modifies the HTML after Docusaurus generates it, injecting client and site meta tags for the search scraper.
sidebar_position: 1 id: architecture title: Documentation Site Architecture sidebar_label: Architecture
Documentation Site Architecture
This page describes how the Scottsdale Mint Documentation Portal is structured, what technology it runs on, and how the four independent documentation instances are wired together.
Technology Stack
| Component | Version / Detail |
|---|---|
| Framework | Docusaurus 3.x (TypeScript config) |
| React | 18 |
| TypeScript | 5.3 |
| Node.js | ≥ 18 |
| Search | Typesense OSS (self-hosted) |
| Web Server | Apache httpd on Amazon Linux 2023 |
| Authentication | HTTP Basic Auth (via Apache) |
| Hosting | EC2 — scottsdale.rhinogroup.com |
Multi-Instance Docusaurus
Docusaurus supports running multiple independent documentation collections from a single site. Each instance has its own:
- Content directory — where the markdown files live
- Sidebar configuration — which pages appear and in what order
- URL route prefix — the base path under which all pages in that instance are served
The four instances are:
scottsdale-documentation/
├── docs/ → serves at /retail/
├── middleware-docs/ → serves at /middleware/
├── dealers-docs/ → serves at /dealers/
└── documentation-docs/ → serves at /documentation/
The retail instance is configured as the preset-classic docs plugin. The other three are registered as separate @docusaurus/plugin-content-docs plugins in docusaurus.config.ts.
See Configuration Reference for the full config walkthrough.
Directory Structure
scottsdale-documentation/
├── docs/ # Retail docs content
├── middleware-docs/ # Middleware docs content
├── dealers-docs/ # Dealers docs content
├── documentation-docs/ # This section — docs about the docs site
├── src/
│ ├── css/custom.css # Global CSS (brand colours, table overrides)
│ └── pages/
│ ├── index.tsx # Homepage (hero + 4 category cards)
│ └── index.module.css # Scoped CSS for the homepage
├── static/
│ └── img/
│ ├── logo.png # Rhino Group logo (navbar)
│ └── favicon.ico
├── scripts/
│ └── update-docs.sh # EC2 deploy + Typesense re-index script
├── docusaurus.config.ts # Main site config
├── sidebars.ts # Retail sidebar
├── sidebars-middleware.ts # Middleware sidebar
├── sidebars-dealers.ts # Dealers sidebar
├── sidebars-documentation.ts # Documentation sidebar (this section)
├── typesense-scraper-config.json # Typesense DocSearch scraper config
└── AGENTS.md # Contributor and agent rules
Request Flow
Browser
└── HTTPS → scottsdale.rhinogroup.com (port 443)
└── Apache httpd
├── /typesense/* → ProxyPass → localhost:8108 (Typesense — no Basic Auth)
└── /* → /var/www/html (Docusaurus static files — Basic Auth required)
The Typesense /typesense path is intentionally exempted from HTTP Basic Auth so the browser-side search JavaScript can call it without credentials. See Typesense Search for details.
Build Pipeline
The site is a static site — there is no runtime server component. The build process compiles all markdown and React pages into plain HTML/CSS/JS in the build/ directory, which is then copied directly to /var/www/html.
npm run build → build/ → cp -R build/* /var/www/html/
Builds are triggered manually by running update-docs.sh on the EC2 instance. There is no automated CI/CD for this repository.