This project is a Docusaurus v2 documentation site for the GlueOps platform. Docs live in docs/ and are rendered at https://docs.glueops.dev. The sidebar is manually defined in sidebars.js.
glueops-dev/
├── Dockerfile # Multi-stage production build (static HTML via nginx)
├── Dockerfile.dev # Development build (Docusaurus dev server with live reload)
├── nginx.conf # Nginx config for the production container
├── .dockerignore # Docker build context exclusions
├── docusaurus.config.js # Site config (routeBasePath: '/')
├── sidebars.js # Manual sidebar definition (NOT auto-generated)
├── docs/ # All documentation pages
│ ├── introduction.md # Landing page (id: introduction)
│ ├── cluster-domains.mdx # Captain domain explanation
│ ├── deploy-applications/ # Developer guides
│ │ ├── traefik/ # Traefik routing guides (17 pages)
│ │ ├── ingress/ # Legacy ingress docs
│ │ └── images/ # Screenshots for hello-world guides
│ └── glueops-platform-administrator/ # Platform admin guides
├── src/ # React components, CSS, custom pages
├── static/ # Static assets
└── analytics/ # Analytics scripts
There are two Dockerfiles for different purposes. Both expose port 80.
| File | Purpose | Base Image | Output |
|---|---|---|---|
Dockerfile |
Production | node:24-slim (build) → nginx:alpine-slim (serve) |
Static HTML served by nginx |
Dockerfile.dev |
Development | node:24-slim |
Docusaurus dev server with live reload |
Dockerfile— Multi-stage build. Stage 1 installs dependencies and runsyarn buildto produce static HTML. Stage 2 copies the output into an nginx container withnginx.conffor serving. This is what CI builds and deploys.Dockerfile.dev— Single-stage build. Runs the Docusaurus dev server (yarn start) for local development with hot module reloading. Mount your source code as a volume for live reload.nginx.conf— Nginx server config used by the production container. Includestry_filesfallback for client-side routing, gzip compression, and static asset caching.
Before creating or modifying any doc page, you must read:
.ai/patterns/— pick the skeleton that matches your doc type:traefik-crd.md— IngressRoute/Middleware/TLSOption guides (most common)standard-ingress.md— Standard Kubernetes Ingress guidesoverview.md— Concept/overview pagesmulti-app.md— Multi-app guides (e.g., canary routing)general.md— Non-Traefik deployment tutorials
.ai/reference.md— contains frontmatter rules, admonition syntax, sidebar conventions, and gotchassidebars.js— the manual sidebar config you must update
- Place the file in the appropriate
docs/subdirectory - Use the correct frontmatter (see
.ai/reference.mdfor rules) - Follow the page structure from the matching
.ai/patterns/skeleton
The sidebar is manually defined — new pages are NOT auto-discovered. You must add the doc id (prefixed with its relative path from docs/) to the correct position in sidebars.js.
Format: "<folder-path>/<doc-id>" — e.g., "deploy-applications/traefik/traefik-basic-ingressroute"
If the new page belongs to a section with an overview page (e.g., docs/deploy-applications/traefik/overview.md), add a link to the new page in the overview's "Guides" list.
- Confirm frontmatter
idmatches what's referenced insidebars.js - Confirm all internal links use relative paths (e.g.,
./traefik-basic-ingressroute) - Confirm admonitions use valid types:
:::note,:::info,:::tip,:::caution,:::warning - Confirm
import Tabsandimport TabItemare present if using<Tabs>components
| Category | Path | Sidebar Section | Description |
|---|---|---|---|
| Traefik guides | docs/deploy-applications/traefik/ |
Developers → Traefik Ingress | Routing, middleware, TLS, TCP examples |
| Deploy guides | docs/deploy-applications/ |
Developers | Hello world, app deployment basics |
| Platform admin | docs/glueops-platform-administrator/ |
Platform Administrators | Cluster setup, GitHub config |
| Top-level | docs/ |
Root sidebar | Introduction, captain domains |
- Dark mode default — the site defaults to dark mode (
colorMode.defaultMode: "dark") - No trailing slashes —
trailingSlash: false - Docs at root —
routeBasePath: '/'means docs are served from/, not/docs/ - Edit links — each page gets an "Edit this page" link pointing to the GitHub repo
- Broken links throw —
onBrokenLinks: "throw", so invalid internal links will break the build
The site has a dynamic domain replacement feature that lets readers type their cluster domain into a navbar input, which automatically updates all domain references across the docs. The default domain is nonprod.antoniostacos.onglueops.com.
| Layer | File | Purpose |
|---|---|---|
| React Context | src/contexts/CaptainDomainContext.tsx |
Stores domain in state + localStorage (key: glueops_captain_domain) |
| Provider | src/theme/Root.tsx |
Wraps the entire app with CaptainDomainProvider |
| Navbar Input | src/theme/NavbarItem/CaptainDomainInput.tsx |
Text input widget in the navbar |
| Navbar Registration | src/theme/NavbarItem/ComponentTypes.tsx |
Registers custom-captainDomainInput navbar item type |
| CodeBlock Swizzle | src/theme/CodeBlock/index.tsx |
Replaces CAPTAIN_DOMAIN sentinel in code fences |
| MDX Component | src/theme/MDXComponents.tsx |
Exports <CaptainDomain /> for prose usage and <CaptainDomainLink /> for clickable domain URLs |
| MDX Link Component | src/components/CaptainDomainLink.tsx |
Renders clickable <a> when domain is customized, styled text with tooltip when default |
| Styles | src/css/custom.css |
Styles for navbar widget, inline component, and link component |
| Pattern | Where to use | How it works |
|---------|--------------||--------------|
| CAPTAIN_DOMAIN | Inside code fences (```) | CodeBlock swizzle replaces it reactively |
| <CaptainDomain /> | Inline prose text (bare domain names, not clickable) | MDX component renders the current domain |
| <CaptainDomainLink to="https://sub.{domain}" /> | https:// URLs in prose that readers should visit | Clickable link when domain is customized, styled text with tooltip when default |
| <CaptainDomainPart segment="cluster\|tenant\|tld" /> | Inline prose — individual segment of the captain domain | MDX component splits the domain and renders the requested segment (cluster, tenant, or tld) |
| {{ .Values.captain_domain }} | Helm template YAML in code fences | Shown as-is (not replaced) — it's a real Helm expression |
Any doc file that uses the <CaptainDomain />, <CaptainDomainLink />, or <CaptainDomainPart /> JSX components must use the .mdx extension (not .md). Plain .md files cannot render JSX components. Standard Docusaurus components like <Tabs> and <TabItem> work in .md files — only custom JSX components like <CaptainDomain /> and <CaptainDomainLink /> require .mdx.
- Code fences: Write
CAPTAIN_DOMAINas a raw sentinel. The swizzled CodeBlock replaces it with the user's domain automatically. - Prose text (domain names): Use
<CaptainDomain />. Example:Your domain is <CaptainDomain />. - Prose text (clickable URLs): Use
<CaptainDomainLink to="https://sub.{domain}/path" />for anyhttps://URL the reader should visit. Optionalchildrenoverride the link text:<CaptainDomainLink to="https://argocd.{domain}">ArgoCD dashboard</CaptainDomainLink>. - Helm templates: Use
{{ .Values.captain_domain }}— this is a real Helm expression and must not be replaced. - Never hardcode a specific cluster domain (e.g.,
my-cluster.my-tenant.onglueops.com) in documentation prose or code fences. Use one of the patterns above instead.