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

client-api.mddocs/

Client-Side API

VitePress client-side API provides composables and utilities for accessing runtime data, navigation, and page information. Essential for building custom themes and Vue components in markdown files.

Capabilities

Core Composables

Vue composables for accessing VitePress runtime state and functionality.

useData

Access VitePress runtime data including site configuration, page data, and theme configuration.

/**
 * Access VitePress runtime data
 * @returns VitePressData object containing reactive site and page data
 */
function useData<T = any>(): VitePressData<T>;

interface VitePressData<T> {
  /**
   * Reactive site-level data and configuration
   */
  site: Ref<SiteData<T>>;
  
  /**
   * Reactive theme configuration
   */
  theme: Ref<T>;
  
  /**
   * Reactive current page data
   */
  page: Ref<PageData>;
  
  /**
   * Reactive frontmatter of current page
   */
  frontmatter: Ref<Record<string, any>>;
  
  /**
   * Reactive route parameters for dynamic routes
   */
  params: Ref<Record<string, string>>;
  
  /**
   * Computed page title (from frontmatter or page data)
   */
  title: Ref<string>;
  
  /**
   * Computed page description (from frontmatter or page data)
   */
  description: Ref<string>;
  
  /**
   * Current language code
   */
  lang: Ref<string>;
  
  /**
   * Text direction (ltr/rtl)
   */
  dir: Ref<string>;
  
  /**
   * Current locale index for multi-language sites
   */
  localeIndex: Ref<string>;
  
  /**
   * Dark mode state (reactive)
   */
  isDark: Ref<boolean>;
}

Usage Examples:

<script setup>
import { useData } from "vitepress";

const { site, page, theme, frontmatter, isDark } = useData();

// Access site information
console.log("Site title:", site.value.title);
console.log("Base URL:", site.value.base);

// Access page information
console.log("Page title:", page.value.title);
console.log("Page path:", page.value.relativePath);

// Access theme configuration
console.log("Nav items:", theme.value.nav);

// Access frontmatter
console.log("Page tags:", frontmatter.value.tags);

// React to dark mode changes
watch(isDark, (dark) => {
  console.log("Dark mode:", dark ? "enabled" : "disabled");
});
</script>

<template>
  <div :class="{ dark: isDark }">
    <h1>{{ page.title }}</h1>
    <p>{{ page.description }}</p>
    <div v-if="frontmatter.tags">
      <span v-for="tag in frontmatter.tags" :key="tag" class="tag">
        {{ tag }}
      </span>
    </div>
  </div>
</template>

useRouter

Access VitePress router for programmatic navigation and route handling.

/**
 * Access VitePress router instance
 * @returns Router object with navigation methods and hooks
 */
function useRouter(): Router;

interface Router {
  /**
   * Current route information
   */
  route: Route;
  
  /**
   * Navigate to a new URL
   * @param to - Target URL or path
   * @returns Promise that resolves after navigation
   */
  go(to?: string): Promise<void>;
  
  /**
   * Hook called before route changes
   */
  onBeforeRouteChange?: (to: string) => Awaitable<void | boolean>;
  
  /**
   * Hook called before page loads
   */
  onBeforePageLoad?: (to: string) => Awaitable<void | boolean>;
  
  /**
   * Hook called after page loads
   */
  onAfterPageLoad?: (to: string) => Awaitable<void>;
  
  /**
   * Hook called after route changes
   */
  onAfterRouteChange?: (to: string) => Awaitable<void>;
}

Usage Examples:

<script setup>
import { useRouter, onMounted } from "vitepress";

const router = useRouter();

// Navigate programmatically
const goToPage = (path) => {
  router.go(path);
};

// Set up navigation hooks
onMounted(() => {
  router.onBeforeRouteChange = async (to) => {
    console.log("Navigating to:", to);
    // Return false to cancel navigation
    if (to.includes("restricted")) {
      return false;
    }
  };
  
  router.onAfterPageLoad = async (to) => {
    console.log("Page loaded:", to);
    // Update analytics, scroll position, etc.
    trackPageView(to);
  };
});

const trackPageView = (path) => {
  // Analytics tracking logic
};
</script>

<template>
  <nav>
    <button @click="goToPage('/guide/')">Guide</button>
    <button @click="goToPage('/api/')">API</button>
    <button @click="goToPage('/examples/')">Examples</button>
  </nav>
</template>

useRoute

Access current route information and reactive route state.

/**
 * Access current route information
 * @returns Current Route object with path, data, and component
 */
function useRoute(): Route;

interface Route {
  /**
   * Current path
   */
  path: string;
  
  /**
   * Current page data
   */
  data: PageData;
  
  /**
   * Current page component
   */
  component: Component | null;
}

Usage Examples:

<script setup>
import { useRoute, computed } from "vitepress";

const route = useRoute();

// Reactive computed properties based on route
const isHomePage = computed(() => route.path === "/");
const isApiPage = computed(() => route.path.startsWith("/api/"));
const currentSection = computed(() => {
  const segments = route.path.split("/").filter(Boolean);
  return segments[0] || "home";
});

// Access route data
console.log("Current path:", route.path);
console.log("Page headers:", route.data.headers);
</script>

<template>
  <div>
    <div v-if="isHomePage" class="home-banner">
      Welcome to the homepage!
    </div>
    
    <nav class="breadcrumb">
      <span class="section" :class="{ active: currentSection === 'home' }">
        Home
      </span>
      <span v-if="!isHomePage" class="section active">
        {{ currentSection }}
      </span>
    </nav>
    
    <div v-if="isApiPage" class="api-notice">
      You're viewing API documentation
    </div>
  </div>
</template>

Client Utilities

Utility functions for common client-side operations and URL handling.

withBase

Prepend configured base URL to internal links and paths.

/**
 * Prepend configured base to internal URLs
 * @param path - URL path string
 * @returns URL with base prepended
 */
function withBase(path: string): string;

Usage Examples:

<script setup>
import { withBase, useData } from "vitepress";

const { site } = useData();

// Ensure links work with custom base URLs
const logoUrl = withBase("/logo.svg");
const apiUrl = withBase("/api/reference");

// Dynamic asset paths
const getAssetUrl = (filename) => withBase(`/assets/${filename}`);
</script>

<template>
  <header>
    <img :src="logoUrl" :alt="site.title" />
    <nav>
      <a :href="withBase('/guide/')">Guide</a>
      <a :href="apiUrl">API Reference</a>
    </nav>
  </header>
  
  <main>
    <img :src="getAssetUrl('hero-image.jpg')" alt="Hero" />
  </main>
</template>

onContentUpdated

Register callbacks for content updates and page changes.

/**
 * Register callback for content updates
 * @param fn - Callback function to execute on content updates
 * @returns void (auto-unregisters on component unmount)
 */
function onContentUpdated(fn: () => any): void;

Usage Examples:

<script setup>
import { onContentUpdated, nextTick } from "vitepress";

// Update third-party widgets when content changes
onContentUpdated(() => {
  // Reinitialize syntax highlighters
  if (window.Prism) {
    window.Prism.highlightAll();
  }
  
  // Update table of contents
  updateTableOfContents();
  
  // Scroll to hash if present
  nextTick(() => {
    const hash = window.location.hash;
    if (hash) {
      const element = document.querySelector(hash);
      element?.scrollIntoView();
    }
  });
});

const updateTableOfContents = () => {
  // Custom TOC update logic
  const headers = document.querySelectorAll("h1, h2, h3, h4, h5, h6");
  console.log("Found headers:", headers.length);
};
</script>

defineClientComponent

Define async components for client-side rendering with SSR compatibility.

/**
 * Define async component for client-side rendering
 * @param loader - AsyncComponentLoader function
 * @param args - Component arguments
 * @param cb - Completion callback
 * @returns Component definition object with SSR support
 */
function defineClientComponent(
  loader: AsyncComponentLoader,
  args?: any,
  cb?: () => void
): Component;

type AsyncComponentLoader = () => Promise<Component>;

Usage Examples:

<script setup>
import { defineClientComponent } from "vitepress";

// Define client-only component (e.g., interactive widgets)
const InteractiveChart = defineClientComponent(
  () => import("./components/InteractiveChart.vue"),
  {
    // Component props
    data: chartData,
    options: chartOptions
  },
  () => {
    console.log("Chart component loaded");
  }
);

// Define component with loading state
const HeavyWidget = defineClientComponent(
  () => import("./components/HeavyWidget.vue"),
  {},
  () => {
    // Initialize widget after loading
    initializeWidget();
  }
);
</script>

<template>
  <div>
    <h2>Data Visualization</h2>
    <InteractiveChart v-if="chartData" />
    <div v-else>Loading chart...</div>
    
    <h2>Advanced Features</h2>
    <HeavyWidget />
  </div>
</template>

getScrollOffset

Calculate scroll offset based on site configuration for proper anchor positioning.

/**
 * Calculate scroll offset based on site configuration
 * @returns Scroll offset in pixels
 */
function getScrollOffset(): number;

Usage Examples:

<script setup>
import { getScrollOffset } from "vitepress";

// Custom scroll behavior
const scrollToElement = (elementId) => {
  const element = document.getElementById(elementId);
  if (element) {
    const offset = getScrollOffset();
    const top = element.offsetTop - offset;
    
    window.scrollTo({
      top,
      behavior: "smooth"
    });
  }
};

// Handle anchor clicks with proper offset
const handleAnchorClick = (event, hash) => {
  event.preventDefault();
  scrollToElement(hash.slice(1));
  
  // Update URL without jumping
  history.pushState(null, null, hash);
};
</script>

<template>
  <nav class="table-of-contents">
    <ul>
      <li v-for="header in headers" :key="header.slug">
        <a 
          :href="`#${header.slug}`" 
          @click="handleAnchorClick($event, `#${header.slug}`)"
        >
          {{ header.title }}
        </a>
      </li>
    </ul>
  </nav>
</template>

Environment Detection

Constants and utilities for detecting the runtime environment.

inBrowser

Boolean constant indicating whether code is running in browser environment.

/**
 * Whether code is running in browser environment
 */
const inBrowser: boolean;

Usage Examples:

<script setup>
import { inBrowser } from "vitepress";

// Conditionally run browser-only code
if (inBrowser) {
  // Safe to access window, document, localStorage, etc.
  console.log("Running in browser");
  console.log("User agent:", navigator.userAgent);
  
  // Initialize browser-only features
  initializeAnalytics();
  setupKeyboardShortcuts();
} else {
  console.log("Running on server (SSR)");
}

const initializeAnalytics = () => {
  // Browser-only analytics code
  if (typeof window !== "undefined" && window.gtag) {
    window.gtag("config", "GA_MEASUREMENT_ID");
  }
};

const setupKeyboardShortcuts = () => {
  if (inBrowser) {
    document.addEventListener("keydown", (event) => {
      if (event.ctrlKey && event.key === "k") {
        // Open search
        openSearch();
      }
    });
  }
};
</script>

Content Component

Vue component for rendering markdown content within Vue templates.

Content

Component for rendering processed markdown content with Vue component support.

/**
 * Component for rendering markdown content
 */
const Content: Component;

Usage Examples:

<script setup>
import { Content, useData } from "vitepress";

const { page, frontmatter } = useData();

// Custom content wrapper with additional features
const showTableOfContents = computed(() => 
  frontmatter.value.toc !== false && page.value.headers.length > 1
);
</script>

<template>
  <div class="content-wrapper">
    <header v-if="frontmatter.showHeader !== false">
      <h1>{{ page.title }}</h1>
      <p class="description">{{ page.description }}</p>
      
      <div v-if="frontmatter.tags" class="tags">
        <span v-for="tag in frontmatter.tags" :key="tag" class="tag">
          {{ tag }}
        </span>
      </div>
    </header>
    
    <aside v-if="showTableOfContents" class="table-of-contents">
      <h2>On This Page</h2>
      <nav>
        <ul>
          <li v-for="header in page.headers" :key="header.slug">
            <a :href="`#${header.slug}`">{{ header.title }}</a>
          </li>
        </ul>
      </nav>
    </aside>
    
    <main class="content">
      <!-- Render the actual markdown content -->
      <Content />
    </main>
    
    <footer v-if="frontmatter.showFooter !== false">
      <p v-if="page.lastUpdated">
        Last updated: {{ new Date(page.lastUpdated).toLocaleDateString() }}
      </p>
    </footer>
  </div>
</template>

<style scoped>
.content-wrapper {
  display: grid;
  grid-template-columns: 1fr 200px;
  gap: 2rem;
}

.table-of-contents {
  position: sticky;
  top: 2rem;
  height: fit-content;
}
</style>

Advanced Client Utilities

Additional utilities for advanced client-side functionality.

Custom Data Loading

/**
 * Load custom data in client components
 */
interface DataLoader<T> {
  /**
   * Load data for current page
   */
  load(): Promise<T>;
  
  /**
   * Cache loaded data
   */
  cache?: boolean;
  
  /**
   * Invalidate cache conditions
   */
  invalidate?: (route: Route) => boolean;
}

/**
 * Create data loader for client components
 */
function createDataLoader<T>(loader: DataLoader<T>): () => Promise<T>;

Client-Side Search

/**
 * Client-side search functionality
 */
interface SearchProvider {
  /**
   * Search query
   */
  search(query: string): Promise<SearchResult[]>;
  
  /**
   * Initialize search index
   */
  initialize(): Promise<void>;
  
  /**
   * Update search index
   */
  update(pages: PageData[]): Promise<void>;
}

interface SearchResult {
  /**
   * Page title
   */
  title: string;
  
  /**
   * Page URL
   */
  url: string;
  
  /**
   * Search excerpt
   */
  excerpt: string;
  
  /**
   * Search relevance score
   */
  score: number;
}

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