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:
- Create the component in
docs/src/components/:
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>
);
}
- Register the component in
docs/src/theme/MDXComponents.tsx:
import MDXComponents from '@theme-original/MDXComponents';
import MyComponent from '@site/src/components/MyComponent';
export default {
...MDXComponents,
MyComponent,
};
- 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 colorsbackground.paper,background.default- Background colorstext.primary,text.secondary- Text colorsdivider- Border colorsaction.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
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:
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:
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
Local Search
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,
},
],
],
Algolia Search
For production sites, use Algolia DocSearch:
- Apply for DocSearch
- 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 documentationversioned_sidebars/version-1.0.0-sidebars.json: Versioned sidebars- Updates
versions.json
Version Configuration
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:
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:
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:
- Connect your GitHub repository to Vercel
- Configure build settings:
- Build Command:
cd docs && pnpm build - Output Directory:
docs/build
- Build Command:
- Add environment variables if needed
- Deploy
Netlify
Deploy to Netlify:
[build]
command = "cd docs && pnpm build"
publish = "docs/build"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Docker
Create a Docker image:
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:
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
presets: [
[
'classic',
{
gtag: {
trackingID: 'G-XXXXXXXXXX',
anonymizeIP: true,
},
},
],
],
Custom Analytics
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
Link Validation
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.