Skip to main content

Advanced Documentation Topics

This guide covers advanced topics for Thunder documentation development, including custom React components, Docusaurus plugins, and deployment strategies.

Creating Custom Components​

To create new custom components for Thunder documentation:

  1. Create the component in docs/src/components/:
docs/src/components/MyComponent.tsx
import React from 'react';
import {Box, Typography} from '@wso2/oxygen-ui';

interface MyComponentProps {
title: string;
children: React.ReactNode;
}

export default function MyComponent({title, children}: MyComponentProps) {
return (
<Box sx={{ border: '1px solid', borderColor: 'divider', p: 2, borderRadius: 1 }}>
<Typography variant="h6" gutterBottom>
{title}
</Typography>
<Box>{children}</Box>
</Box>
);
}
  1. Register the component in docs/src/theme/MDXComponents.tsx:
docs/src/theme/MDXComponents.tsx
import MDXComponents from '@theme-original/MDXComponents';
import MyComponent from '@site/src/components/MyComponent';

export default {
...MDXComponents,
MyComponent,
};
  1. Use in MDX files without imports:
<MyComponent title="Example">
This is my custom component content.
</MyComponent>

Component Best Practices​

  • TypeScript: Always use TypeScript for type safety
  • Oxygen UI: Prefer Oxygen UI components for consistency
  • Accessibility: Follow WCAG guidelines
  • Responsive: Test on mobile and desktop
  • Documentation: Add JSDoc comments explaining usage
  • Props validation: Use TypeScript interfaces for props
  • Default values: Provide sensible defaults for optional props

Component Styling​

Use Oxygen UI's sx prop for styling components:

<Box 
sx={{
padding: 2,
backgroundColor: 'background.paper',
borderRadius: 1,
'&:hover': {
backgroundColor: 'action.hover',
},
}}
>
Content
</Box>

Common theme tokens:

  • primary.main, secondary.main - Brand colors
  • background.paper, background.default - Background colors
  • text.primary, text.secondary - Text colors
  • divider - Border colors
  • action.hover, action.selected - Interactive states

See Oxygen UI Theme Documentation for complete theme reference.

Custom Pages​

Create standalone pages outside the documentation structure.

Creating a Custom Page​

docs/src/pages/my-page.tsx
import React from 'react';
import Layout from '@theme/Layout';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';

export default function MyPage() {
const {siteConfig} = useDocusaurusContext();

return (
<Layout
title="My Custom Page"
description="Description for SEO">
<main>
<h1>Custom Page Content</h1>
<p>This is a standalone page.</p>
</main>
</Layout>
);
}

Access: http://localhost:3000/my-page

Landing Pages​

Create rich landing pages with custom layouts:

docs/src/pages/index.tsx
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import styles from './index.module.css';

function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/guides/introduction">
Get Started →
</Link>
</div>
</div>
</header>
);
}

export default function Home() {
return (
<Layout>
<HomepageHeader />
<main>{/* Your content sections */}</main>
</Layout>
);
}

Docusaurus Configuration​

Site Configuration​

Edit docs/docusaurus.config.ts for global settings:

import type {Config} from '@docusaurus/types';

const config: Config = {
title: 'Thunder Documentation',
tagline: 'Identity and Access Management',
favicon: 'img/favicon.ico',
url: 'https://your-domain.com',
baseUrl: '/',

// GitHub Pages deployment
organizationName: 'asgardeo',
projectName: 'thunder',

// Internationalization
i18n: {
defaultLocale: 'en',
locales: ['en'],
},

// Presets and plugins
presets: [
[
'classic',
{
docs: {
routeBasePath: '/',
sidebarPath: './sidebars.ts',
editUrl: 'https://github.com/asgardeo/thunder/tree/main/docs/',
},
theme: {
customCss: './src/css/custom.css',
},
},
],
],
};

export default config;

Theme Configuration​

themeConfig: {
// Navbar
navbar: {
title: 'Thunder',
logo: {
alt: 'Thunder Logo',
src: 'img/logo.svg',
},
items: [
{
type: 'docSidebar',
sidebarId: 'guideSidebar',
position: 'left',
label: 'Guides',
},
{
href: 'https://github.com/asgardeo/thunder',
label: 'GitHub',
position: 'right',
},
],
},

// Footer
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [
{label: 'Getting Started', to: '/guides/introduction'},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} WSO2 LLC.`,
},

// Code highlighting
prism: {
theme: require('prism-react-renderer').themes.github,
darkTheme: require('prism-react-renderer').themes.dracula,
additionalLanguages: ['bash', 'java', 'go'],
},

// Algolia Search (if configured)
algolia: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY',
indexName: 'thunder',
},
},

Docusaurus Plugins​

Official Plugins​

Install and configure official Docusaurus plugins:

pnpm add -D @docusaurus/plugin-content-blog
pnpm add -D @docusaurus/plugin-client-redirects
pnpm add -D @docusaurus/plugin-sitemap

Configure in docusaurus.config.ts:

plugins: [
// Blog plugin
[
'@docusaurus/plugin-content-blog',
{
id: 'blog',
routeBasePath: 'blog',
path: './blog',
},
],

// Redirects plugin
[
'@docusaurus/plugin-client-redirects',
{
redirects: [
{
from: '/old-path',
to: '/new-path',
},
],
},
],

// Sitemap plugin
[
'@docusaurus/plugin-sitemap',
{
changefreq: 'weekly',
priority: 0.5,
},
],
],

Custom Plugins​

Create custom plugins for specific needs:

docs/plugins/myPlugin.ts
import type {Plugin} from '@docusaurus/types';

export default function myPlugin(): Plugin {
return {
name: 'my-custom-plugin',

async loadContent() {
// Load custom data
return {data: 'custom data'};
},

async contentLoaded({content, actions}) {
const {addRoute} = actions;
// Add custom routes
},

configureWebpack(config, isServer, utils) {
// Modify webpack config
return {
mergeStrategy: {'module.rules': 'prepend'},
module: {
rules: [
// Custom webpack rules
],
},
};
},
};
}

Search Configuration​

For smaller sites, use local search:

pnpm add -D @easyops-cn/docusaurus-search-local

Configure:

themes: [
[
'@easyops-cn/docusaurus-search-local',
{
hashed: true,
language: ['en'],
highlightSearchTermsOnTargetPage: true,
explicitSearchResultPath: true,
},
],
],

For production sites, use Algolia DocSearch:

  1. Apply for DocSearch
  2. Configure in docusaurus.config.ts:
algolia: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY',
indexName: 'thunder',
contextualSearch: true,
searchParameters: {},
searchPagePath: 'search',
},

Versioning​

Enable Versioning​

Create documentation versions for different releases:

cd docs
pnpm docusaurus docs:version 1.0.0

This creates:

  • versioned_docs/version-1.0.0/: Versioned documentation
  • versioned_sidebars/version-1.0.0-sidebars.json: Versioned sidebars
  • Updates versions.json

Version Configuration​

docusaurus.config.ts
presets: [
[
'classic',
{
docs: {
lastVersion: 'current',
versions: {
current: {
label: '2.0.0 (Next)',
path: 'next',
},
'1.0.0': {
label: '1.0.0',
path: '1.0.0',
},
},
},
},
],
],

Internationalization (i18n)​

Setup i18n​

Configure supported locales:

docusaurus.config.ts
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'es'],
localeConfigs: {
en: {
label: 'English',
direction: 'ltr',
},
fr: {
label: 'Français',
direction: 'ltr',
},
},
},

Translating Content​

Extract translatable strings:

pnpm docusaurus write-translations --locale fr

Translate files in i18n/fr/:

i18n/
└── fr/
├── docusaurus-plugin-content-docs/
│ └── current/
│ └── guides/
│ └── introduction.md
└── docusaurus-theme-classic/
└── navbar.json

Build with Locales​

pnpm docusaurus build --locale fr

Deployment​

GitHub Pages​

Deploy to GitHub Pages using the GitHub Action:

.github/workflows/deploy-docs.yml
name: Deploy Docs

on:
push:
branches: [main]
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: pnpm/action-setup@v4

- name: Build Docs
run: make build_docs

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build

Vercel​

Deploy to Vercel:

  1. Connect your GitHub repository to Vercel
  2. Configure build settings:
    • Build Command: cd docs && pnpm build
    • Output Directory: docs/build
  3. Add environment variables if needed
  4. Deploy

Netlify​

Deploy to Netlify:

netlify.toml
[build]
command = "cd docs && pnpm build"
publish = "docs/build"

[[redirects]]
from = "/*"
to = "/index.html"
status = 200

Docker​

Create a Docker image:

Dockerfile.docs
FROM node:18-alpine AS builder

WORKDIR /app
COPY docs/package.json docs/pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile

COPY docs/ ./
RUN pnpm build

FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Build and run:

docker build -f Dockerfile.docs -t thunder-docs .
docker run -p 8080:80 thunder-docs

Performance Optimization​

Bundle Size​

Optimize bundle size:

docusaurus.config.ts
future: {
experimental_faster: {
swcJsLoader: true,
swcJsMinimizer: true,
swcHtmlMinimizer: true,
lightningCssMinimizer: true,
rspackBundler: true,
mdxCrossCompilerCache: true,
},
},

Image Optimization​

Use optimized images:

import ThemedImage from '@theme/ThemedImage';

<ThemedImage
alt="Diagram"
sources={{
light: require('./img/diagram-light.png').default,
dark: require('./img/diagram-dark.png').default,
}}
/>

Lazy Loading​

Lazy load heavy components:

import React, {lazy, Suspense} from 'react';

const HeavyComponent = lazy(() => import('./HeavyComponent'));

export default function Page() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}

Analytics​

Google Analytics​

docusaurus.config.ts
presets: [
[
'classic',
{
gtag: {
trackingID: 'G-XXXXXXXXXX',
anonymizeIP: true,
},
},
],
],

Custom Analytics​

docs/src/theme/Root.tsx
import React, {useEffect} from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';

export default function Root({children}) {
const {siteConfig} = useDocusaurusContext();

useEffect(() => {
// Custom analytics initialization
}, []);

return <>{children}</>;
}

Testing Documentation​

Check for broken links:

pnpm build
# Docusaurus will report broken links during build

Visual Regression​

Use tools like Percy or Chromatic for visual regression testing.

Accessibility Testing​

pnpm add -D @axe-core/cli

Test accessibility:

pnpm build
pnpm serve &
axe http://localhost:3000 --exit

Troubleshooting​

Build Issues​

Memory issues:

NODE_OPTIONS="--max-old-space-size=8192" pnpm build

Cache issues:

rm -rf .docusaurus node_modules pnpm-lock.yaml
pnpm install
pnpm clear

Plugin Conflicts​

Check plugin compatibility and load order. Use DEBUG=* pnpm build for detailed logs.

© 2026 Thunder. All rights reserved.
Terms & ConditionsPrivacy Policy