Skip to main content

Global Plugin

The global plugin provides core functionality for registering global UI components, styles, and runtime configuration. It makes shared components and configuration available throughout your documentation site.

Features

  • Global Components - Register React components available in all markdown files
  • Global Styles - Add site-wide SCSS/CSS stylesheets
  • Global UI Components - Add persistent UI elements (header, footer, etc.)
  • Runtime Configuration - Expose configuration to client-side code
  • Version Management - Handle versioned documentation
  • Multi-Site Support - Configure multiple documentation sites
  • Login Page - Automatically add authentication pages

Configuration

Configure the global plugin in your doom.config.ts:
import { defineConfig } from '@alauda/doom'
import { globalPlugin } from '@alauda/doom/plugins'

export default defineConfig({
  plugins: [
    globalPlugin({
      version: '2.0.0',  // Site version
      download: true     // Enable download functionality
    })
  ]
})

Plugin Options

version
string
Version string for the documentation site. Exposed to runtime code.
download
boolean
default:"false"
Enable download functionality for documentation.

Global Components

The plugin automatically registers components from the runtime components directory, making them available in all markdown files without imports.

Auto-Registration

Components are automatically discovered and registered:
packages/doom/src/plugins/global/index.ts:42-52
markdown: {
  globalComponents: fs
    .readdirSync(componentsDir)
    .filter((file) => {
      const basename = path.basename(file, path.extname(file))
      return (
        !basename.startsWith('_') &&
        !basename.endsWith('.d') &&
        basename !== 'index'
      )
    })
    .map((file) => path.resolve(componentsDir, file)),
}

Component Rules

Components are registered if they:
  • ✅ Exist in the runtime/components directory
  • ✅ Have a valid file extension (.tsx, .jsx, .ts, .js)
  • ✅ Don’t start with underscore (_private.tsx)
  • ✅ Aren’t type definition files (.d.ts)
  • ✅ Aren’t named index

Usage in Markdown

Once registered, use components directly:
# My Documentation

<Alert type="info">
  This component is globally available!
</Alert>

<CodeBlock language="typescript">
  const example = "No import needed"
</CodeBlock>

Global Styles

The plugin loads site-wide styles:
packages/doom/src/plugins/global/index.ts:37
globalStyles: pkgResolve('styles/global.scss'),

Adding Custom Styles

Create a styles/global.scss file:
// Custom theme colors
:root {
  --primary-color: #3b82f6;
  --secondary-color: #8b5cf6;
}

// Global utilities
.highlight {
  background-color: var(--primary-color);
  padding: 0.25rem 0.5rem;
  border-radius: 0.25rem;
}

// Component overrides
.rspress-nav {
  backdrop-filter: blur(10px);
}

Global UI Components

Register persistent UI elements that appear on every page:
packages/doom/src/plugins/global/index.ts:38-40
globalUIComponents: fs
  .readdirSync(globalComponentsDir, 'utf8')
  .map((component) => path.resolve(globalComponentsDir, component)),

Use Cases

  • Custom Header - Add branding, navigation, search
  • Footer - Links, copyright, social icons
  • Sidebar - Custom navigation, ads, widgets
  • Overlays - Announcement banners, cookie notices
  • Analytics - Tracking scripts, monitoring

Example UI Component

global/CustomBanner.tsx
import React from 'react'

export default function CustomBanner() {
  return (
    <div className="custom-banner">
      <p>📢 New version available! <a href="/changelog">See what's new</a></p>
    </div>
  )
}

Runtime Configuration

The plugin exposes configuration through a virtual module:
packages/doom/src/plugins/global/index.ts:54-74
addRuntimeModules(config, isProd) {
  return {
    'doom-@global-virtual': `export default ${JSON.stringify(
      {
        userBase: config.userBase,
        prefix: config.prefix,
        version,
        download,
        sites: config.sites?.map((site) => ({
          ...site,
          base: addTrailingSlash(
            site.base || (site.name === 'acp' ? ACP_BASE : ''),
          ),
          version: site.version,
        })),
        export: config.export,
      },
      null,
      isProd ? 0 : 2,
    )}`
  }
}

Accessing Configuration

Import the virtual module in your components:
import globalConfig from 'doom-@global-virtual'

export default function VersionBadge() {
  return (
    <span className="version">
      v{globalConfig.version}
    </span>
  )
}

Available Fields

interface GlobalVirtual {
  userBase: string      // Base URL for user content
  prefix?: string       // URL prefix
  version?: string      // Site version
  download?: boolean    // Download enabled
  sites?: DoomSite[]    // Multi-site configuration
  export?: ExportItem[] // Export configuration
}

Multi-Site Configuration

The plugin supports multiple documentation sites:
export default defineConfig({
  sites: [
    {
      name: 'main',
      base: '/',
      version: '2.0'
    },
    {
      name: 'api',
      base: '/api',
      version: '2.0'
    },
    {
      name: 'acp',
      base: '/acp',  // Special handling for ACP
      version: '1.5'
    }
  ],
  plugins: [
    globalPlugin({ version: '2.0.0' })
  ]
})
Create a site switcher using the configuration:
import globalConfig from 'doom-@global-virtual'

export function SiteSwitcher() {
  return (
    <select>
      {globalConfig.sites?.map(site => (
        <option key={site.name} value={site.base}>
          {site.name} (v{site.version})
        </option>
      ))}
    </select>
  )
}

Login Page

The plugin automatically adds login pages:
packages/doom/src/plugins/global/index.ts:76-97
addPages(config) {
  let loginPath: string
  for (const ext of ['.js', '.tsx']) {
    loginPath = baseResolve(`login/index${ext}`)
    if (fs.existsSync(loginPath)) {
      break
    }
  }
  if ((config.themeConfig?.locales?.length ?? 0) < 1) {
    return [
      {
        routePath: '/login',
        filepath: loginPath!,
      },
    ]
  }
  const lang = config.lang
  return config.themeConfig!.locales!.map((l) => ({
    routePath: l.lang && l.lang !== lang ? `/${l.lang}/login` : '/login',
    filepath: loginPath,
  }))
}

Localized Login

Login pages are automatically generated for each locale:
  • English site: /login
  • Chinese site: /zh/login
  • French site: /fr/login

Custom Login Page

Create a custom login component:
login/index.tsx
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'

export default function LoginPage() {
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const navigate = useNavigate()

  const handleLogin = async () => {
    // Authentication logic
    await authenticate(username, password)
    navigate('/')
  }

  return (
    <div className="login-page">
      <h1>Login</h1>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="Username"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
      />
      <button onClick={handleLogin}>Sign In</button>
    </div>
  )
}

Version Management

Display version information throughout your site:
import globalConfig from 'doom-@global-virtual'

export function Header() {
  return (
    <header>
      <h1>My Docs</h1>
      {globalConfig.version && (
        <span className="version-badge">
          Version {globalConfig.version}
        </span>
      )}
    </header>
  )
}

Version-Based Features

Conditionally show features based on version:
import globalConfig from 'doom-@global-virtual'

export function DownloadButton() {
  if (!globalConfig.download) {
    return null
  }

  return (
    <button onClick={handleDownload}>
      Download v{globalConfig.version}
    </button>
  )
}

Best Practices

  1. Component Naming - Use PascalCase for global components
  2. Style Scoping - Use CSS modules or scoped selectors to avoid conflicts
  3. Performance - Keep global UI components lightweight
  4. TypeScript - Add type definitions for virtual modules
  5. Testing - Test components in isolation before making them global

Component Organization

packages/doom/
├── src/
│   ├── runtime/
│   │   └── components/       # Global markdown components
│   │       ├── Alert.tsx
│   │       ├── CodeBlock.tsx
│   │       └── _internal/    # Not registered (starts with _)
│   ├── global/               # Global UI components
│   │   ├── Header.tsx
│   │   ├── Footer.tsx
│   │   └── Banner.tsx
│   ├── styles/
│   │   └── global.scss       # Global styles
│   └── login/
│       └── index.tsx          # Login page

Component Categories

Runtime Components (in markdown):
  • Alerts, warnings, notes
  • Code blocks with special features
  • Tabs, accordions
  • Custom formatting
Global UI Components (persistent):
  • Header, footer
  • Navigation, breadcrumbs
  • Announcement banners
  • Search overlays

TypeScript Support

Add type definitions for the virtual module:
types/doom-global.d.ts
declare module 'doom-@global-virtual' {
  export interface DoomSite {
    name: string
    base: string
    version?: string
  }

  export interface ExportItem {
    // Your export types
  }

  export interface GlobalVirtual {
    userBase: string
    prefix?: string
    version?: string
    download?: boolean
    sites?: DoomSite[]
    export?: ExportItem[]
  }

  const globalConfig: GlobalVirtual
  export default globalConfig
}

Advanced Usage

Dynamic Component Loading

import { lazy, Suspense } from 'react'

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

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

Context Providers

import { createContext, useContext } from 'react'
import globalConfig from 'doom-@global-virtual'

const ConfigContext = createContext(globalConfig)

export function useGlobalConfig() {
  return useContext(ConfigContext)
}

export default function ConfigProvider({ children }) {
  return (
    <ConfigContext.Provider value={globalConfig}>
      {children}
    </ConfigContext.Provider>
  )
}

Troubleshooting

Components Not Available

If global components aren’t working:
  1. Verify file is in runtime/components directory
  2. Check filename doesn’t start with _
  3. Ensure valid file extension (.tsx, .jsx)
  4. Restart dev server after adding new components

Styles Not Applied

If global styles aren’t loading:
  1. Check styles/global.scss exists
  2. Verify SCSS syntax is valid
  3. Look for conflicting styles
  4. Check browser console for errors

Virtual Module Errors

If doom-@global-virtual import fails:
  1. Add TypeScript declaration file
  2. Restart TypeScript server
  3. Check plugin is registered
  4. Verify build is up to date

Build docs developers (and LLMs) love