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