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:5180/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:5180 --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.

Thunder LogoThunder Logo

Work together seamlessly with secure your applications with ease.

Terms & Policy

Pages

HomeDocsAPIsSDKs
© WSO2 LLC. All rights reserved.