Vocs is a React-based static documentation generator, powered by Vite. Write your content in Markdown or MDX, and Vocs will generate a static site with a default theme.
Scaffold a new project with the command line:
npm init vocs- Install Vocs:
npm i vocs@next- Add scripts to
package.json:
{
"scripts": {
"docs:dev": "vocs dev",
"docs:build": "vocs build",
"docs:preview": "vocs preview"
}
}- Create your first page:
my-project/
├── docs/
│ ├── pages/
│ │ └── index.mdx
├── node_modules/
└── package.json
- Run the development server:
npm run docs:devVisit http://localhost:5173 to see your documentation site.
A typical Vocs project structure looks like this:
my-project/
├── docs/
│ ├── pages/
│ │ ├── index.mdx
│ │ └── about.mdx
│ ├── public/
│ │ └── favicon.ico
│ └── vocs.config.ts
├── node_modules/
└── package.json
The main directories and files are:
docs/: Root directory for documentationdocs/pages/: Contains your documentation pagesdocs/public/: Static assetsdocs/vocs.config.ts: Configuration file
Vocs supports standard Markdown syntax plus additional features. Here's a comprehensive guide:
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6- Italics:
*asterisks*or_underscores_ - Bold:
**asterisks**or__underscores__ - Combined:
**asterisks and _underscores_** - Strikethrough:
~~Scratch this~~
1. Ordered list item
2. Another item
- Unordered sub-list
- Nested sub-list
- Another sub-list item
3. Third ordered item[Link text](URL)
```javascript
console.log("hello world")
```- Titles: ```````bash [Terminal]````
- Line focus:
// [!code focus] - Line highlights:
// [!code hl] - Line numbers: Add
showLineNumbersmeta - Word focus:
// [!code word] - Diffs:
// [!code ++]and// [!code --]
:::code-group
```bash [npm]
npm i vocspnpm i vocs:::
#### Callouts
```markdown
:::note
Note content
:::
:::warning
Warning content
:::
:::danger
Danger content
:::
| Header 1 | Header 2 | Header 3 |
|----------|:--------:|---------:|
| Left | Center | Right |
| aligned | aligned | aligned |::::steps
### Step one
Content for step one
### Step two
Content for step two
::::- Import and use React components
- Use JSX in markdown
- Export metadata with frontmatter
Vocs provides several built-in components that you can use throughout your documentation:
Displays author or authors in a specific format.
Displays blog posts within the blogDir.
Display a Vocs-flavored button with three styles:
- Default Button
- Accent Button
- Link Button
Displays a callout with content.
Displays a "home page" section with customizable content including logos, descriptions, and call-to-action buttons.
Renders a list of sponsors defined in the Vocs config.
You can also create and use your own custom components by importing them in your MDX files.
Vocs comes with three built-in layouts: docs, landing, and minimal. Each layout has its own styling and components.
The default layout for documentation pages. Includes:
- Edit page link
- Outline
- Footer navigation
---
layout: docs
---
# A docs page
This is a docs page.Special layout for homepages without sidebar or documentation components.
---
layout: landing
---
This is a landing page.Use the built-in <HomePage> components for a templated home page:
---
layout: landing
---
import { HomePage } from 'vocs/components'
<HomePage.Root>
<HomePage.Logo />
<HomePage.Tagline>React Documentation Framework, powered by Vite</HomePage.Tagline>
<HomePage.InstallPackage name="vocs" type="init" />
<HomePage.Description>
Vocs is a minimal static documentation generator designed to supercharge your documentation workflow.
</HomePage.Description>
<HomePage.Buttons>
<HomePage.Button href="/docs" variant="accent">Get started</HomePage.Button>
<HomePage.Button href="https://github.com/wevm/vocs">GitHub</HomePage.Button>
</HomePage.Buttons>
</HomePage.Root>A barebones layout without documentation components:
---
layout: minimal
---
# A minimal page
This page uses a minimal layout.Control layout features through frontmatter:
---
showSidebar: false
showOutline: false
showLogo: false
------
layout: landing
content:
horizontalPadding: 0px
width: 100%
verticalPadding: 0px
---Vocs uses a configuration file (vocs.config.ts) to define global metadata for your documentation. This includes things like the site title, description, logo, sidebar, and more for your project.
The Vocs config should be defined in a vocs.config.ts file at the root of your project:
viem/
├── docs/
├── node_modules/
├── src/
├── package.json
└── vocs.config.ts
- title (string): Documentation title
- description (string): General description for the documentation
- basePath (string): Base path for deployment (e.g., '/docs')
- baseUrl (string): Base URL for documentation
- blogDir (string): Path to blog pages relative to project root
- font (object): Configure font settings including Google Fonts
- iconUrl (string): Favicon URL
- logoUrl (string): Logo URL for sidebar and mobile nav
- sidebar (object): Navigation displayed on the sidebar
- socials (array): Social media links in top navigation
- theme (object): Theme configuration
- search (object): Search configuration
- markdown (object): Markdown processing configuration
Example Configuration:
import { defineConfig } from 'vocs'
export default defineConfig({
title: 'My Docs',
description: 'Documentation for my awesome project',
basePath: '/docs',
baseUrl: 'https://example.com',
sidebar: [
{
text: 'Getting Started',
link: '/docs',
},
{
text: 'API',
collapsed: true,
items: [
{
text: 'Config',
link: '/docs/api/config',
},
],
}
],
socials: [
{
icon: 'github',
link: 'https://github.com/username/project',
},
],
theme: {
accentColor: '#ff0000',
}
})Theming in Vocs is highly configurable. You can customize your documentation through CSS variables in the configuration file or via CSS classes.
import { defineConfig } from 'vocs'
export default defineConfig({
theme: {
accentColor: '#ff0000', // Single color
// OR
accentColor: {
light: 'black',
dark: 'white',
},
// OR
accentColor: {
backgroundAccent: { light: 'white', dark: 'black' },
backgroundAccentHover: { light: 'whitesmoke', dark: 'gray' },
backgroundAccentText: { light: 'black', dark: 'white' },
textAccent: { light: 'black', dark: 'white' },
}
}
})You can force a specific color scheme:
export default defineConfig({
theme: {
colorScheme: 'dark' // or 'light'
}
})Customize any CSS variable used in Vocs:
export default defineConfig({
theme: {
variables: {
color: {
background: {
light: 'white',
dark: 'black'
}
},
content: {
horizontalPadding: '40px',
verticalPadding: '80px'
}
}
}
})Every element in Vocs can be customized via CSS classes using the .Vocs_{element} pattern. For example:
.Vocs_H1 {
color: red;
}Inspect your documentation's HTML to see available class names for customization.
You can set page-specific metadata in the frontmatter of Markdown pages using YAML format between --- separators at the top of the page.
---
title: Example
description: This is an example page.
---
# Hello world
This is me.- title (string): Page title for the
<title>tag - description (string): Page description for meta tags
- date (string): Publication date
- authors (string[]): Page authors
- layout ("docs" | "landing" | "minimal"): Page layout type
docs: Documentation page layout (default)landing: Landing page layoutminimal: Minimal layout without sidebar/header
- showSidebar (boolean): Toggle sidebar visibility
- showOutline (boolean | number): Toggle outline or specify depth
- showLogo (boolean): Toggle logo visibility in header
- showAiCta (boolean): Toggle AI call-to-action dropdown
---
content:
horizontalPadding: string
width: string
verticalPadding: string
---Example with multiple options:
---
title: My Page
description: A comprehensive guide
authors:
- [jxom](https://x.com/jxom)
- [awkweb](https://x.com/awkweb)
date: 2023-12-01
layout: docs
showOutline: 2
content:
horizontalPadding: 40px
width: 100%
verticalPadding: 80px
---Vocs supports dynamic open graph images that are displayed when sharing links on platforms like Twitter, Slack, or Telegram.
Use the built-in API by setting the ogImageUrl in your config:
import { defineConfig } from 'vocs'
export default defineConfig({
ogImageUrl: 'https://vocs.dev/api/og?logo=%logo&title=%title&description=%description',
title: 'My Docs'
})You can deploy your own OG Image API using Vercel Edge Functions:
- Clone and deploy the example repository
- Update your config with your deployed URL:
import { defineConfig } from 'vocs'
export default defineConfig({
ogImageUrl: 'https://<my-project>.vercel.app/api/og?logo=%logo&title=%title&description=%description',
title: 'My Docs'
})Available template variables:
%logo: Logo image URL%title: Page title%description: Page description
Configure different OG images for different paths:
import { defineConfig } from 'vocs'
export default defineConfig({
ogImageUrl: {
'/': 'https://vocs.dev/og-image.png',
'/docs': 'https://vocs.dev/api/og?logo=%logo&title=%title&description=%description',
},
title: 'My Docs'
})Vocs provides two main navigation components: sidebar and top navigation.
Configure the sidebar in vocs.config.ts:
import { defineConfig } from 'vocs'
export default defineConfig({
sidebar: [
{
text: 'Getting Started',
link: '/docs',
},
{
text: 'API',
collapsed: true,
items: [
{
text: 'Config',
link: '/docs/api/config',
},
],
}
]
})Create different sidebars for different sections:
export default defineConfig({
sidebar: {
'/docs/': [
{
text: 'Getting Started',
link: '/docs',
},
// ... more items
],
'/examples/': [
{ text: 'React', link: '/examples/react' },
{ text: 'Vue', link: '/examples/vue' }
]
}
})Configure the top navigation bar:
export default defineConfig({
topNav: [
{
text: 'Guide & API',
link: '/docs/getting-started',
match: '/docs'
},
{ text: 'Blog', link: '/blog' },
{
text: 'Version',
items: [
{
text: 'Changelog',
link: 'https://github.com/org/repo/changelog',
},
{
text: 'Contributing',
link: 'https://github.com/org/repo/contributing',
},
],
},
]
})Top navigation items support:
text: Display textlink: Navigation URLmatch: Path pattern for highlightingitems: Dropdown menu items
Add custom CSS by creating a styles.css file in the Vocs root directory:
my-project/
├── docs/
│ ├── pages/
│ │ ├── index.mdx
│ │ └── about.tsx
│ ├── public/
│ │ └── favicon.ico
│ └── styles.css
├── node_modules/
Example styles.css:
body {
background-color: #f3f3f3;
}
.Vocs_H1 {
color: red;
}// layout.tsx
import './global.css'
import './theme.css'
export default function Root({ children }) {
return children
}import './theme.css'
# Hello world
This is me.Vocs includes built-in Tailwind support. Enable it by importing in your styles.css:
@import "tailwindcss";TypeScript Twoslash is a markup language for JavaScript and TypeScript that enhances code samples with type information and compiler features.
Get type information about an identifier:
const example: string = "hello"
// ^?Show auto-complete information:
type Example = { apple: 'foo' | 'bar' | 'baz' }
const example: Example = { apple: '|' }
// ^|Highlight specific code ranges:
function add(foo: number, bar: number) {
// ^^^
return foo + bar
}Remove code above the marker from output:
// Setup code
import { something } from 'somewhere'
// ---cut---
console.log(something)Remove code after the marker:
console.log("This stays")
// ---cut-after---
console.log("This is removed")Create multiple files in a single code block:
// @filename: types.d.ts
export type User = {
id: number
name: string
}
// @filename: index.ts
import { User } from './types'
const user: User = {
id: 1,
name: 'John'
}Control TypeScript behavior with compiler flags:
// @strict: true
// @target: ES2020
// @lib: DOM,ES2020Common flags include:
@noImplicitAny@strictNullChecks@allowJs@checkJs@jsx@module
You can include other Markdown files in your documentation using MDX imports.
- Create a snippet file:
// snippet.mdx
### Hello world
This is my snippet.- Import and use the snippet:
// example.mdx
import Snippet from './snippet.mdx'
# Example
This is an example of including a snippet.
<Snippet />Since snippets are React components, you can pass props:
// example.mdx
import Snippet from './snippet.mdx'
<Snippet title="Hello world" content="This is my snippet." />Access props in the snippet using the props global variable:
// snippet.mdx
### {props.title}
{props.content}Code Snippets in Vocs come in two forms:
- Virtual file snippets in your Markdown code
- Physical file snippets in your file system
To create a virtual file snippet:
- Define the snippet with a filename meta tag:
import { http, createPublicClient } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
chain: mainnet,
transport: http(),
})- Import the snippet using the
// [!include ...]marker:
// [!include example.ts]
const blockNumber = await client.getBlockNumber()For physical file snippets:
- Create a file in your codebase (e.g.,
docs/snippets/example.ts):
import { http, createPublicClient } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
chain: mainnet,
transport: http(),
})- Import using the
// [!include ...]marker with the file path:
// [!include ~/snippets/example.ts]
const blockNumber = await client.getBlockNumber()You can include specific regions of code using // [!region] and // [!endregion] markers:
// [!region import]
import { http, createPublicClient } from 'viem'
import { mainnet } from 'viem/chains'
// [!endregion import]
// [!region setup]
const client = createPublicClient({
chain: mainnet,
transport: http(),
})
// [!endregion setup]Then import specific regions:
// [!include ~/snippets/example.ts:import]
// [!include ~/snippets/example.ts:setup]For duplicate variable declarations in different regions, use the _$ suffix:
const block_$1 = await client.getBlock()
const block_$2 = await client.getBlock({ blockNumber: 42069n })Use /(find)/(replace)/ syntax to modify imported snippets:
// [!include ~/snippets/example.ts /viem/@viem\/core/ /mainnet/sepolia/]- Code Block Markers: You can include markers like line highlights in snippets:
const blockNumber = await client.getBlockNumber() // [!code hl]- Twoslash Integration: Combine with Twoslash for type information:
const blockNumber = await client.getBlockNumber()
// ^?- Twoslash with Virtual Files: Use multiple virtual files in Twoslash code blocks:
import { client } from './client.js'
const blockNumber = await client.getBlockNumber()import { http, createPublicClient } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http(),
})