CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vitepress

Vite & Vue powered static site generator with Vue-based theming and markdown processing

Pending
Overview
Eval results
Files

theming.mddocs/

Theme System API

VitePress theming system provides a Vue-based theme architecture with a comprehensive default theme, composables for state management, and extensive customization options. Themes can be extended, replaced, or enhanced with custom functionality.

Capabilities

Theme Structure

Core theme interfaces and structure for creating custom themes.

Theme Interface

Main theme object structure that defines how themes are implemented.

/**
 * Theme object structure for VitePress themes
 */
interface Theme {
  /**
   * Main layout component (required for custom themes)
   */
  Layout?: Component;
  
  /**
   * App enhancement function for registering components, plugins, etc.
   */
  enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>;
  
  /**
   * Parent theme to extend from
   */
  extends?: Theme;
  
  /**
   * @deprecated Use Layout component and check useData().page.value.isNotFound
   * Custom 404 Not Found component
   */
  NotFound?: Component;
  
  /**
   * @deprecated Wrap your Layout component instead
   * Setup function called during app initialization
   */
  setup?: () => void;
}

interface EnhanceAppContext {
  /**
   * Vue app instance
   */
  app: App;
  
  /**
   * VitePress router instance
   */
  router: Router;
  
  /**
   * Reactive site data
   */
  siteData: Ref<SiteData>;
}

Usage Examples:

// Custom theme example
import DefaultTheme from "vitepress/theme";
import CustomLayout from "./CustomLayout.vue";
import CustomComponent from "./components/CustomComponent.vue";

const customTheme: Theme = {
  extends: DefaultTheme,
  Layout: CustomLayout,
  enhanceApp(ctx) {
    // Register custom components globally
    ctx.app.component("CustomComponent", CustomComponent);
    
    // Add custom plugins
    ctx.app.use(CustomPlugin);
    
    // Add global properties
    ctx.app.config.globalProperties.$customUtility = customUtility;
    
    // Router hooks
    ctx.router.onBeforeRouteChange = (to) => {
      console.log("Navigating to:", to);
    };
  }
};

export default customTheme;

Default Theme

VitePress default theme with comprehensive component library and configuration options.

Default Theme Export

The main default theme object with Layout and app enhancement.

/**
 * VitePress default theme
 */
declare const DefaultTheme: Theme & {
  /**
   * Main layout component
   */
  Layout: Component;
  
  /**
   * App enhancement function
   */
  enhanceApp: (ctx: EnhanceAppContext) => void;
};

Usage Examples:

// Use default theme as-is
import DefaultTheme from "vitepress/theme";
export default DefaultTheme;

// Extend default theme
import DefaultTheme from "vitepress/theme";
import "./custom-styles.css";

export default {
  extends: DefaultTheme,
  enhanceApp(ctx) {
    // Call parent enhanceApp
    DefaultTheme.enhanceApp?.(ctx);
    
    // Add custom enhancements
    ctx.app.component("MyCustomComponent", MyCustomComponent);
  }
};

// Replace default theme layout
import DefaultTheme from "vitepress/theme";
import CustomLayout from "./CustomLayout.vue";

export default {
  ...DefaultTheme,
  Layout: CustomLayout
};

Default Theme Configuration

Comprehensive configuration interface for the default theme.

DefaultTheme.Config

Configuration interface for customizing the default theme appearance and behavior.

/**
 * Configuration interface for VitePress default theme
 */
interface DefaultTheme.Config {
  /**
   * Site logo configuration
   */
  logo?: ThemeableImage;
  
  /**
   * Custom logo link override
   */
  logoLink?: string | { 
    link?: string; 
    rel?: string; 
    target?: string; 
  };
  
  /**
   * Custom site title in navbar (overrides config.title)
   */
  siteTitle?: string | false;
  
  /**
   * Navigation items in header
   */
  nav?: NavItem[];
  
  /**
   * Sidebar configuration
   */
  sidebar?: Sidebar;
  
  /**
   * Aside/outline configuration
   */
  aside?: boolean | "left";
  outline?: Outline | Outline["level"] | false;
  
  /**
   * Edit link configuration
   */
  editLink?: EditLink;
  
  /**
   * Last updated configuration
   */
  lastUpdated?: LastUpdatedOptions;
  
  /**
   * Document footer (prev/next) configuration
   */
  docFooter?: DocFooter;
  
  /**
   * Social links in navigation
   */
  socialLinks?: SocialLink[];
  
  /**
   * Footer configuration
   */
  footer?: Footer;
  
  /**
   * Search configuration (local or Algolia)
   */
  search?: 
    | { provider: "local"; options?: LocalSearchOptions }
    | { provider: "algolia"; options: AlgoliaSearchOptions };
  
  /**
   * Carbon ads configuration
   */
  carbonAds?: CarbonAdsOptions;
  
  /**
   * Internationalization routing
   */
  i18nRouting?: boolean;
  
  /**
   * External link icon display
   */
  externalLinkIcon?: boolean;
  
  /**
   * 404 page customization
   */
  notFound?: NotFoundOptions;
  
  /**
   * UI text labels (for internationalization)
   */
  darkModeSwitchLabel?: string;
  lightModeSwitchTitle?: string;
  darkModeSwitchTitle?: string;
  sidebarMenuLabel?: string;
  returnToTopLabel?: string;
  langMenuLabel?: string;
  skipToContentLabel?: string;
}

type ThemeableImage =
  | string
  | { src: string; alt?: string; [prop: string]: any }
  | { light: string; dark: string; alt?: string; [prop: string]: any };

Usage Examples:

// Complete default theme configuration
import { defineConfig } from "vitepress";

export default defineConfig({
  title: "My Documentation",
  themeConfig: {
    logo: "/logo.svg",
    siteTitle: "My Docs",
    
    nav: [
      { text: "Guide", link: "/guide/" },
      { text: "API", link: "/api/" },
      {
        text: "Resources",
        items: [
          { text: "Examples", link: "/examples/" },
          { text: "FAQ", link: "/faq/" }
        ]
      }
    ],
    
    sidebar: {
      "/guide/": [
        {
          text: "Getting Started",
          collapsed: false,
          items: [
            { text: "Introduction", link: "/guide/" },
            { text: "Installation", link: "/guide/installation" }
          ]
        }
      ]
    },
    
    editLink: {
      pattern: "https://github.com/user/repo/edit/main/docs/:path",
      text: "Edit this page"
    },
    
    socialLinks: [
      { icon: "github", link: "https://github.com/user/repo" },
      { icon: "twitter", link: "https://twitter.com/user" }
    ],
    
    search: {
      provider: "local",
      options: {
        translations: {
          button: { buttonText: "Search" },
          modal: { noResultsText: "No results found" }
        }
      }
    }
  }
});

Theme Composables

Vue composables for accessing and managing theme state within components.

useSidebar

Composable for managing sidebar state and behavior.

/**
 * Access sidebar state and controls
 * @returns DocSidebar object with sidebar state and methods
 */
function useSidebar(): DefaultTheme.DocSidebar;

interface DefaultTheme.DocSidebar {
  /**
   * Whether sidebar is open (mobile)
   */
  isOpen: Ref<boolean>;
  
  /**
   * Computed sidebar items for current route
   */
  sidebar: ComputedRef<SidebarItem[]>;
  
  /**
   * Sidebar groups (same as sidebar but different name for compatibility)
   */
  sidebarGroups: ComputedRef<SidebarItem[]>;
  
  /**
   * Whether current page has sidebar
   */
  hasSidebar: ComputedRef<boolean>;
  
  /**
   * Whether current page has aside/outline
   */
  hasAside: ComputedRef<boolean>;
  
  /**
   * Whether aside is positioned on the left
   */
  leftAside: ComputedRef<boolean>;
  
  /**
   * Whether sidebar is enabled for current route
   */
  isSidebarEnabled: ComputedRef<boolean>;
  
  /**
   * Open sidebar (mobile)
   */
  open(): void;
  
  /**
   * Close sidebar (mobile)
   */
  close(): void;
  
  /**
   * Toggle sidebar (mobile)
   */
  toggle(): void;
}

Usage Examples:

<script setup>
import { useSidebar } from "vitepress/theme";

const { 
  isOpen, 
  sidebar, 
  hasSidebar, 
  hasAside, 
  open, 
  close, 
  toggle 
} = useSidebar();

// Custom sidebar component
const handleItemClick = () => {
  // Close mobile sidebar after navigation
  if (window.innerWidth < 768) {
    close();
  }
};
</script>

<template>
  <aside v-if="hasSidebar" class="custom-sidebar" :class="{ open: isOpen }">
    <button @click="toggle" class="sidebar-toggle">
      {{ isOpen ? 'Close' : 'Open' }} Menu
    </button>
    
    <nav class="sidebar-nav">
      <div v-for="item in sidebar" :key="item.text" class="sidebar-group">
        <h3 v-if="item.text">{{ item.text }}</h3>
        <ul v-if="item.items">
          <li v-for="child in item.items" :key="child.link">
            <a :href="child.link" @click="handleItemClick">
              {{ child.text }}
            </a>
          </li>
        </ul>
      </div>
    </nav>
  </aside>
</template>

useLocalNav

Composable for managing local navigation (table of contents) state.

/**
 * Access local navigation (outline) state
 * @returns DocLocalNav object with headers and visibility state
 */
function useLocalNav(): DefaultTheme.DocLocalNav;

interface DefaultTheme.DocLocalNav {
  /**
   * Page outline headers
   */
  headers: ShallowRef<Header[]>;
  
  /**
   * Whether local nav should be shown
   */
  hasLocalNav: ComputedRef<boolean>;
}

Usage Examples:

<script setup>
import { useLocalNav, useData } from "vitepress/theme";

const { headers, hasLocalNav } = useLocalNav();
const { page } = useData();

// Custom table of contents component
const activeHeader = ref("");

// Track active header on scroll
onMounted(() => {
  const observer = new IntersectionObserver((entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) {
        activeHeader.value = entry.target.id;
      }
    }
  });

  // Observe all headers
  headers.value.forEach(header => {
    const element = document.getElementById(header.slug);
    if (element) observer.observe(element);
  });
});
</script>

<template>
  <nav v-if="hasLocalNav" class="local-nav">
    <h4>On This Page</h4>
    <ul>
      <li 
        v-for="header in headers" 
        :key="header.slug"
        :class="{ 
          active: activeHeader === header.slug,
          [`level-${header.level}`]: true 
        }"
      >
        <a :href="`#${header.slug}`">{{ header.title }}</a>
        
        <!-- Nested headers -->
        <ul v-if="header.children?.length">
          <li 
            v-for="child in header.children" 
            :key="child.slug"
            :class="{ active: activeHeader === child.slug }"
          >
            <a :href="`#${child.slug}`">{{ child.title }}</a>
          </li>
        </ul>
      </li>
    </ul>
  </nav>
</template>

Default Theme Components

Comprehensive set of Vue components provided by the default theme.

Layout Components

Main layout and page structure components.

/**
 * Home page content area component
 */
declare const VPHomeContent: Component;

/**
 * Home page features section component
 */
declare const VPHomeFeatures: Component<{
  features: Feature[];
}>;

/**
 * Home page hero section component
 */
declare const VPHomeHero: Component<{
  name?: string;
  text?: string;
  tagline?: string;
  image?: ThemeableImage;
  actions?: HeroAction[];
}>;

/**
 * Home page sponsors section component
 */
declare const VPHomeSponsors: Component<{
  message?: string;
  sponsors: Sponsor[];
}>;

/**
 * Team page wrapper component
 */
declare const VPTeamPage: Component;

/**
 * Team page section component
 */
declare const VPTeamPageSection: Component<{
  title?: string;
  lead?: string;
  members: TeamMember[];
}>;

/**
 * Team page title component
 */
declare const VPTeamPageTitle: Component<{
  title: string;
  lead?: string;
}>;

/**
 * Team members grid component
 */
declare const VPTeamMembers: Component<{
  size?: "small" | "medium";
  members: TeamMember[];
}>;

UI Components

Reusable UI components for custom layouts and content.

/**
 * Badge/tag component for highlighting information
 */
declare const VPBadge: Component<{
  type?: "info" | "tip" | "warning" | "danger";
  text: string;
}>;

/**
 * Button component with theme styling
 */
declare const VPButton: Component<{
  tag?: string | Component;
  size?: "medium" | "big";
  theme?: "brand" | "alt" | "sponsor";
  text: string;
  href?: string;
}>;

/**
 * Features showcase component
 */
declare const VPFeatures: Component<{
  features: Feature[];
}>;

/**
 * Responsive image component with theme support
 */
declare const VPImage: Component<{
  image: ThemeableImage;
  alt?: string;
}>;

/**
 * Enhanced link component with external link detection
 */
declare const VPLink: Component<{
  tag?: string | Component;
  href?: string;
  noIcon?: boolean;
  target?: string;
  rel?: string;
}>;

/**
 * Sponsors display component
 */
declare const VPSponsors: Component<{
  mode: "normal" | "aside";
  tier: string;
  size?: "big" | "medium" | "small" | "xmini";
  data: Sponsor[];
}>;

Navigation Components

Components for navigation menus and search functionality.

/**
 * Navigation bar search component
 */
declare const VPNavBarSearch: Component;

/**
 * Social media link component
 */
declare const VPSocialLink: Component<{
  icon: SocialLinkIcon;
  link: string;
  ariaLabel?: string;
}>;

/**
 * Social media links group component
 */
declare const VPSocialLinks: Component<{
  links: SocialLink[];
}>;

Documentation Components

Components specific to documentation layouts.

/**
 * Aside sponsors section component
 */
declare const VPDocAsideSponsors: Component<{
  tier: string;
  size?: "big" | "medium" | "small";
  data: Sponsor[];
}>;

Usage Examples:

<script setup>
import {
  VPHomeHero,
  VPHomeFeatures,
  VPTeamMembers,
  VPButton,
  VPBadge
} from "vitepress/theme";

// Hero configuration
const heroConfig = {
  name: "My Project",
  text: "Next Generation Tool",
  tagline: "Fast, reliable, and easy to use",
  image: {
    src: "/hero-logo.svg",
    alt: "My Project Logo"
  },
  actions: [
    {
      theme: "brand",
      text: "Get Started",
      link: "/guide/getting-started"
    },
    {
      theme: "alt", 
      text: "View on GitHub",
      link: "https://github.com/user/project"
    }
  ]
};

// Features configuration
const features = [
  {
    icon: "⚡",
    title: "Fast Performance",
    details: "Optimized for speed and efficiency"
  },
  {
    icon: "🔧",
    title: "Easy Configuration", 
    details: "Simple setup with sensible defaults"
  }
];

// Team members
const teamMembers = [
  {
    avatar: "/avatars/john.jpg",
    name: "John Doe",
    title: "Lead Developer",
    links: [
      { icon: "github", link: "https://github.com/johndoe" }
    ]
  }
];
</script>

<template>
  <div class="custom-layout">
    <!-- Hero section -->
    <VPHomeHero v-bind="heroConfig" />
    
    <!-- Features section -->
    <VPHomeFeatures :features="features" />
    
    <!-- Team section -->
    <section class="team-section">
      <h2>Meet the Team</h2>
      <VPTeamMembers size="medium" :members="teamMembers" />
    </section>
    
    <!-- Custom content with theme components -->
    <section class="custom-content">
      <h2>
        Latest Release 
        <VPBadge type="tip" text="v2.0" />
      </h2>
      
      <p>Check out our latest features and improvements.</p>
      
      <VPButton 
        theme="brand"
        text="Download Now"
        href="/download"
      />
    </section>
  </div>
</template>

Theme Types

Supporting type definitions for theme configuration and components.

Navigation Types

type NavItem = NavItemComponent | NavItemWithLink | NavItemWithChildren;

interface NavItemComponent {
  component: string;
  props?: Record<string, any>;
}

interface NavItemWithLink {
  text: string;
  link: string;
  activeMatch?: string;
  rel?: string;
  target?: string;
  noIcon?: boolean;
}

interface NavItemWithChildren {
  text?: string;
  items: (NavItemComponent | NavItemChildren | NavItemWithLink)[];
  activeMatch?: string;
}

interface NavItemChildren {
  text?: string;
  items: NavItemWithLink[];
}

Sidebar Types

type Sidebar = SidebarItem[] | SidebarMulti;

interface SidebarMulti {
  [path: string]: SidebarItem[] | { items: SidebarItem[]; base: string };
}

interface SidebarItem {
  text?: string;
  link?: string;
  items?: SidebarItem[];
  collapsed?: boolean;
  base?: string;
  docFooterText?: string;
  rel?: string;
  target?: string;
}

Feature and Team Types

interface Feature {
  icon?: FeatureIcon;
  title: string;
  details: string;
  link?: string;
  linkText?: string;
  rel?: string;
  target?: string;
}

type FeatureIcon = 
  | string
  | { src: string; alt?: string; width?: string; height?: string; wrap?: boolean }
  | { light: string; dark: string; alt?: string; width?: string; height?: string; wrap?: boolean };

interface TeamMember {
  avatar: string;
  name: string;
  title?: string;
  org?: string;
  orgLink?: string;
  desc?: string;
  links?: SocialLink[];
  sponsor?: string;
  actionText?: string;
}

interface SocialLink {
  icon: SocialLinkIcon;
  link: string;
  ariaLabel?: string;
}

type SocialLinkIcon = string | { svg: string };

Install with Tessl CLI

npx tessl i tessl/npm-vitepress

docs

build-dev.md

cli.md

client-api.md

configuration.md

index.md

markdown.md

theming.md

tile.json