Skip to Content
Style Guide

Style Guide

A reference of every markdown element and Nextra component available in this template. Use it as a cheat sheet when authoring pages.

Typography

Headings

# Heading 1 ## Heading 2 ### Heading 3 #### Heading 4 ##### Heading 5 ###### Heading 6

Headings 2–4 are automatically picked up by the table of contents on the right.

Paragraphs and inline formatting

A regular paragraph supports bold text, italic text, bold italic, strikethrough, inline code, and links to other pages or external URLs .

You can combine them: a bold link  or italic code.

Blockquotes

Documentation is a love letter that you write to your future self.

— Damian Conway

Nested blockquotes:

Outer quote.

Inner quote.

Horizontal rule


Lists

Unordered

  • First item
  • Second item
  • Third item
    • Nested item
    • Another nested item
      • Deeply nested

Ordered

  1. First step
  2. Second step
  3. Third step
    1. Sub-step
    2. Sub-step

Task list

  • Completed task
  • Another completed task
  • Pending task
  • Future task

Tables

ComponentImport fromPurpose
Calloutnextra/componentsHighlight a block of information
Stepsnextra/componentsNumber sequential instructions
Tabsnextra/componentsGroup alternative content
Cardsnextra/componentsLinkable card grid
FileTreenextra/componentsRender a folder structure
Bleednextra/componentsExtend content past the gutter

Column alignment:

Left alignedCenteredRight aligned
npm1.x✔️
pnpm9.x✔️
yarn4.x✔️

Images

Place images in /public and reference them with a root-relative path. Nextra optimizes them automatically:

Diagram placeholder showing optimized image rendering

For finer control, use the Next.js <Image> component (see CLAUDE.md for details).

Code

Inline code

Use backticks for inline code references like npm install, file names like next.config.mjs, or short snippets.

Fenced code block

const greet = (name) => `Hello, ${name}!` console.log(greet('world'))

With filename

src/lib/greet.ts
export const greet = (name: string) => `Hello, ${name}!`

Line highlighting

const a = 1 const b = 2 // highlighted const c = 3 const d = 4 // highlighted const e = 5 // highlighted const f = 6 // highlighted

Line numbers

function add(a: number, b: number) { return a + b } add(2, 3)

Word highlighting

import { useState } from 'react' function Counter() { const [count, setCount] = useState(0) return <button onClick={() => setCount(count + 1)}>{count}</button> }

Diff-style

- const old = 'value' + const next = 'value'

Shell

npm install nextra nextra-theme-docs

Math (LaTeX)

Inline math: E=mc2E = mc^2 and i=1ni=n(n+1)2\sum_{i=1}^{n} i = \frac{n(n+1)}{2}.

Block math:

ex2dx=π\int_{-\infty}^{\infty} e^{-x^2} \, dx = \sqrt{\pi}

Nextra components

Callout (custom)

The template ships a custom <Callout> component registered globally — no import needed.

This is the default callout. Use it for general notes.

Info callout — helpful supplementary information.

Tip callout — a pro tip or “did you know” aside.

Success callout — confirm something is working.

Warning callout — caution the reader.

Error callout — flag a critical problem.

Important callout — highlight non-skippable details (distinct purple styling).

<Callout type="warning">Caution the reader.</Callout>

Callout (Nextra built-in)

Nextra’s own callout is available as NextraCallout in this page (imported and aliased to avoid colliding with the custom one above).

Default Nextra callout.
Info variant.
Warning variant.
Error variant.
import { Callout } from 'nextra/components' <Callout type="info">Your content here.</Callout>

Steps

Install dependencies

Run npm install to fetch the template’s dependencies.

Configure your content

Edit src/content/_meta.js to control the sidebar order.

Run the dev server

npm run dev

Build and deploy

npm run build

Tabs

npm install nextra nextra-theme-docs

Cards

Cards are navigation tiles — title + optional icon + optional arrow. Always use the self-closing form. Children render as an unpadded banner above the title bar (intended for full-bleed images, not description text), so don’t put paragraph content inside a card.

<Cards> <Cards.Card title="Overview" href="/" arrow /> <Cards.Card title="Nextra docs" href="https://nextra.site" arrow /> </Cards>

FileTree

      • layout.tsx
      • _meta.js
      • index.mdx
      • styleguide.mdx
    • mdx-components.tsx
  • next.config.mjs
  • package.json

Bleed

<Bleed> extends content past the page gutter — useful for wide diagrams, screenshots, or embedded media.

Wide image extended past the content gutter

Use <Bleed full> to extend all the way to the viewport edges.

Mermaid diagrams

Fenced code blocks tagged mermaid are rendered as live diagrams.

```mermaid graph LR A[MDX source] --> B[remark-mermaid] B --> C[Mermaid component] C --> D[Rendered diagram] ```

A sequence diagram:

Images & ImageZoom

All plain markdown images are now click-to-zoom by default — ![]() is wired through <ImageZoom> in src/mdx-components.tsx.

Click anywhere on this image to enlarge

You can also use the component explicitly if you need to pass next/image-specific props:

Toolbar screenshot
import { ImageZoom } from 'nextra/components' <ImageZoom src="/toolbar.png" alt="…" width={1200} height={300} />

YouTube

<YouTube> embeds a privacy-enhanced (youtube-nocookie.com) player at a 16:9 aspect ratio.

<YouTube id="dQw4w9WgXcQ" title="Optional title" /> <YouTube id="..." start={120} /> <YouTube id="..." aspectRatio={[4, 3]} />

Video

<Video> wraps the native HTML5 <video> element with sensible defaults (controls, preload="metadata", playsInline).

<Video src="/clips/intro.mp4" poster="/clips/intro-poster.jpg" /> {/* Multi-format fallback */} <Video src={[ { src: '/clips/intro.webm', type: 'video/webm' }, { src: '/clips/intro.mp4', type: 'video/mp4' } ]} />

Drop video files under /public and reference them with root-relative paths, same as images.

Embed

<Embed url="..."> is a one-stop wrapper for arbitrary URLs. Known providers render as a rich iframe; unknown URLs fall back to a simple link card.

Currently routed providers: YouTube, Vimeo, Loom, CodePen, Figma.

Unknown URL → link card fallback:

nextra.site
Nextra documentation
<Embed url="https://www.youtube.com/watch?v=..." /> <Embed url="https://vimeo.com/123456789" /> <Embed url="https://www.loom.com/share/abc..." /> <Embed url="https://codepen.io/user/pen/xyz..." /> <Embed url="https://www.figma.com/file/abc.../Title" />

Prefer the dedicated <YouTube> / <Video> components when you know the source — they’re slightly more configurable. Use <Embed> when the source could vary or when you want consistent “any-URL-works” behavior in authored content.

Button

<Button> is a styled action button with default and outline variants. It’s a thin wrapper around Headless UI’s button.

src/components/styleguide-demos.tsx
'use client' import { Button } from 'nextra/components' export function ButtonDemo() { return ( <> <Button onClick={() => alert('clicked')}>Default button</Button> <Button variant="outline" onClick={() => alert('clicked')}> Outline button </Button> </> ) }

Note: event handlers like onClick are functions and can’t be passed from a server-rendered MDX file directly to a client component. Wrap interactive buttons in a 'use client' component (as above) and import that into MDX.

Collapse

<Collapse> is a controlled show/hide region with height + opacity animation. You drive isOpen from your own state.

This content is revealed when the trigger is clicked. The Collapse component animates height and opacity.

  • Use it for optional / supplementary detail.
  • Use <details> for SEO-indexable accordions.
src/components/styleguide-demos.tsx
'use client' import { useState } from 'react' import { Collapse, Button } from 'nextra/components' export function CollapseDemo() { const [isOpen, setIsOpen] = useState(false) return ( <> <Button variant="outline" onClick={() => setIsOpen(o => !o)}> {isOpen ? 'Hide' : 'Show'} </Button> <Collapse isOpen={isOpen}>{/* … */}</Collapse> </> ) }

For collapsible content that should be visible to search engines, prefer the native <details> / <summary> HTML elements.

<Popup> is a hover-triggered popover. Useful for inline definitions and footnote-style asides.

Hover the underlined term for a definition:

import { Popup } from 'nextra/components' <Popup> <Popup.Button as="span">trigger text</Popup.Button> <Popup.Panel>panel content</Popup.Panel> </Popup>

Select

<Select> is a styled controlled <select>-like dropdown. Most often used for compact in-page filters or option pickers (theme, version, language).

'use client' import { useState } from 'react' import { Select } from 'nextra/components' const options = [ { id: 'system', name: 'System' }, { id: 'light', name: 'Light' }, { id: 'dark', name: 'Dark' } ] const [value, setValue] = useState('system') <Select value={value} onChange={setValue} options={options} selectedOption={<span>Theme: {value}</span>} />

Playground

<Playground> compiles a string of MDX in the browser and renders it inline. Useful for live API demos or component examples where you want readers to see source + output side by side without a separate sandbox.

import { Playground } from 'nextra/components' import { useMDXComponents } from '../mdx-components' <Playground source={` ## Hello from Playground This MDX is compiled at runtime. `} components={useMDXComponents()} fallback={<p>Loading…</p>} />

Note: Playground pulls the MDX compiler into the client bundle on first render, so use sparingly — not on every page.

<Banner> is a site-wide announcement strip rendered above the navbar. It’s wired in src/app/layout.tsx, not used inline in MDX.

src/app/layout.tsx
import { Banner, Layout, Navbar, Footer } from 'nextra-theme-docs' const banner = ( <Banner storageKey="release-1.0"> 🎉 v1.0 is out — <a href="/release-notes">read the notes</a> </Banner> ) <Layout banner={banner} navbar={<Navbar />} footer={<Footer …/>} …> {children} </Layout>

storageKey lets the banner remember it’s been dismissed per visitor.

Rich tables (DataTable)

GFM |-syntax tables can hold one line of plain text per cell. When you need multi-paragraph cells, lists, callouts, or other components inside cells, use <DataTable> instead.

ComponentWhen to useNotes
GFM table

Simple comparison rows with one line of plain text per cell.

Pipe-and-dash syntax (| col | col |). Authored inline in MDX. Fastest to write.

<DataTable>

Cells need multiple paragraphs, lists, or embedded components.

Examples of things you can put in a cell:

  • Bulleted lists
  • Yes, even other Callouts.
  • <code> and bold and links
HTML <table>Only when you need full control of attributes.Allowed in MDX, but bypasses the house style.

Column alignment:

LeftCenteredRight
npm1.x✔︎
pnpm9.x✔︎
<DataTable headers={['Column A', 'Column B']} widths={['30%', '70%']} align={['left', 'right']} caption="Optional caption rendered above the table." > <DataTable.Row> <DataTable.Cell>Cell content</DataTable.Cell> <DataTable.Cell> Can contain **markdown**, components, lists — anything MDX allows. </DataTable.Cell> </DataTable.Row> </DataTable>

API:

  • headers={[...]} — optional column headers (omit for headerless tables)
  • align={['left' | 'center' | 'right', ...]} — per-column alignment, applied to both header and body cells
  • widths={['20%', '160px', 'auto', ...]} — per-column width
  • caption={...} — optional caption above the table
  • <DataTable.Row> — wraps a row
  • <DataTable.Cell> — a body cell; supports colSpan, rowSpan, per-cell align override
  • <DataTable.HeaderCell> — for inline header cells if you don’t use the headers prop

DataTable is registered globally in src/mdx-components.tsx — no import needed in MDX.

Long sidebars get unwieldy without section headers. Add a separator with a title between groups:

src/content/_meta.js
export default { index: { title: 'Overview', theme: { breadcrumb: false } }, 'core': { type: 'separator', title: 'Core' }, concepts: 'Concepts', architecture: 'Architecture', 'reference': { type: 'separator', title: 'Reference' }, styleguide: 'Style Guide' }

The key ('core', 'reference') is arbitrary — only type and title matter. With title: bold, slightly elevated header text. Without title: a plain <hr>. Group headers can appear at any depth (top-level _meta.js or any nested section’s _meta.js).

The custom PageBreadcrumb (in src/components/PageBreadcrumb.tsx) reads the same _meta.js and prepends the active group as the leading crumb when present.

Frontmatter

Each page may declare a title and description in YAML frontmatter. These feed the <title> tag and meta description.

--- title: My Page description: One-sentence summary used for SEO and previews. --- # My Page Content here…

Control sidebar order, titles, and per-page theme options:

src/content/_meta.js
export default { index: { title: 'Overview', theme: { breadcrumb: false } }, styleguide: 'Style Guide' }
Last updated on