Markdown
Installation
You can use Markdown by adding one of the following Vite plugins.
Vue
Markdown plugins compatible with Vue:
Example:
React
Markdown plugins compatible with React:
Example:
Metadata
There are several techniques for defining metadata (e.g. the date and author of a page).
The preferred technique depends on whether you want to define global or local metadata.
Global metadata
What is global metadata? For example, you want to show a list of all your blog posts always on the left side of your website.
2024-01-01 New Year 2024 Resolution 2023-12-20 Wrapping up 2023 2023-06-15 My summer 2023
Because this list is shown on the left of every page, the publishing date and title of all blog posts is needed for rendering any page: the metadata needs to be accessible globally.
For global metadata, we recommend:
⚠️You may be tempted to use
import.meta.glob()
to retrieve metadata defined inside all+Page.md
files, but we discourage this approach: loading all+Page.md
files at once contradicts Vite's lazy-transpiling approach and it would significantly slow down development speed.
Local metadata
What is local metadata? For example, you want to show detailed information below a blog post, such as the author's name. This metadata is shown only for that page and, therefore, needs to be accessible only locally.
For local metadata, we recommend:
With a metadata.js
file
A simple way to define metadata is to define a metadata.js
file that contains global metadata.
// /pages/metadata.js
// This metadata is available to every page
export const metadata = [
{
url: '/blog/introducing-vike',
title: 'Introducing Vike',
date: new Date('2024-01-01')
},
{
url: '/blog/v1',
title: 'v1.0.0 release',
date: new Date('2025-07-01')
}
]
// /pages/metadata.ts
// This metadata is available to every page
export const metadata = [
{
url: '/blog/introducing-vike',
title: 'Introducing Vike',
date: new Date('2024-01-01')
},
{
url: '/blog/v1',
title: 'v1.0.0 release',
date: new Date('2025-07-01')
}
]
// /pages/+Layout.jsx
import React from 'react'
import { metadata } from './metadata'
export function Layout({ children }) {
// Current URL
const { urlPathname } = usePageContext()
// The page's metadata
const { title } = metadata.find(({ url }) => url === urlPathname)
return (
<>
{/* Show the list of blog posts */}
<LeftSidebar>
<p>Blog posts:</p>
<ul>
{metadata.map(({ title, url, date }) => (
<li>
<a href={url}>{data + title}</a>
</li>
))}
</ul>
</LeftSidebar>
{/* The page's content */}
<Content>
<h1>{title}</h1>
{/* children is pageContext.Page which is the component defined by +Page.md */}
{children}
</Content>
</>
)
}
// /pages/+Layout.tsx
import React from 'react'
import { metadata } from './metadata'
export function Layout({ children }: { children: React.ReactNode }) {
// Current URL
const { urlPathname } = usePageContext()
// The page's metadata
const { title } = metadata.find(({ url }) => url === urlPathname)
return (
<>
{/* Show the list of blog posts */}
<LeftSidebar>
<p>Blog posts:</p>
<ul>
{metadata.map(({ title, url, date }) => (
<li>
<a href={url}>{data + title}</a>
</li>
))}
</ul>
</LeftSidebar>
{/* The page's content */}
<Content>
<h1>{title}</h1>
{/* children is pageContext.Page which is the component defined by +Page.md */}
{children}
</Content>
</>
)
}
See also:
// /pages/blog/introducing-vike/+Page.md
We're thrilled to officially introduce Vike.
// /pages/blog/v1/+Page.md
The `v1.0.0` release signals that Vike is ready for prime time: it now includes
all essentials you'd expect from a frontend framework with a robust design.
With a custom setting (eager)
You can use meta
to create a custom setting for defining global metadata.
/pages/+config.js
/pages/+onCreateGlobalContext.server.js
/pages/+Layout.jsx
/pages/2024-new-year/+Page.md
/pages/2024-new-year/+metadata.js
/pages/+config.ts
/pages/+onCreateGlobalContext.server.ts
/pages/+Layout.tsx
/pages/2024-new-year/+Page.md
/pages/2024-new-year/+metadata.ts
// /pages/+config.js
export default {
meta: {
// Create +metadata setting
metadata: {
// Make +metadata available to all pages
eager: true,
env: {
server: true,
// Instead of `client: true`, we use onCreateGlobalContext() with passToClient to
// be able to determine exactly what metadata is sent to the client-side.
client: false
}
}
},
passToClient: [
// Make globalContext.posts available on the client-side
'posts'
]
}
// /pages/+config.ts
import type { Config } from 'vike/types'
export default {
meta: {
// Create +metadata setting
metadata: {
// Make +metadata available to all pages
eager: true,
env: {
server: true,
// Instead of `client: true`, we use onCreateGlobalContext() with passToClient to
// be able to determine exactly what metadata is sent to the client-side.
client: false
}
}
},
passToClient: [
// Make globalContext.posts available on the client-side
'posts'
]
} satisfies Config
When setting
eager: true
the setting is available globally to all pages.
// /pages/2024-new-year/+metadata.js
export const metadata = {
title: 'New Year 2024 Resolution'
}
// /pages/2024-new-year/+metadata.ts
export const metadata = {
title: 'New Year 2024 Resolution'
}
Unlike in the example below you cannot define
+metadata
inside+Page.md
, because+Page.md
is only loaded when rendering that page. Consequently, the content of+Page.md
isn't available when rendering another page.
// /pages/+onCreateGlobalContext.server.js
// Environment: server
export async function onCreateGlobalContext(globalContext) {
const pages = globalContext.pages
const posts = Object.values(pages).map((page) => {
const { metadata } = page.config
const post = {
url: page.route,
title: metadata.title
}
return post
})
globalContext.posts = posts
}
// /pages/+onCreateGlobalContext.server.ts
// Environment: server
import type { GlobalContextServer } from 'vike/types'
export async function onCreateGlobalContext(globalContext: GlobalContextServer) {
const pages = globalContext.pages
const posts = Object.values(pages).map((page) => {
const { metadata } = page.config
const post = {
url: page.route,
title: metadata.title
}
return post
})
globalContext.posts = posts
}
declare global {
namespace Vike {
interface GlobalContext {
posts: {
url: string,
title: string,
}[]
}
}
}
See also:
// pages/+config.js
export default {
passToClient: ['posts']
}
// pages/+config.ts
import type { Config } from 'vike/types'
export default {
passToClient: ['posts']
} satisfies Config
// /pages/+Layout.jsx
// Environment: server & client
import React from 'react'
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
export function Layout({ children }) {
const pageContext = usePageContext()
const { posts } = pageContext.globalContext
return (
<>
{/* Show the list of blog posts */}
<LeftSidebar>
<p>Blog posts:</p>
<ul>
{posts.map((post) => (
<li>
<a href={post.url}>{post.title}</a>
</li>
))}
</ul>
</LeftSidebar>
{/* The page's content */}
<Content>
<h1>{title}</h1>
{/* children is pageContext.Page which is the component defined by +Page.md */}
{children}
</Content>
</>
)
}
// /pages/+Layout.tsx
// Environment: server & client
import React from 'react'
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
export function Layout({ children }: { children: React.ReactNode }) {
const pageContext = usePageContext()
const { posts } = pageContext.globalContext
return (
<>
{/* Show the list of blog posts */}
<LeftSidebar>
<p>Blog posts:</p>
<ul>
{posts.map((post) => (
<li>
<a href={post.url}>{post.title}</a>
</li>
))}
</ul>
</LeftSidebar>
{/* The page's content */}
<Content>
<h1>{title}</h1>
{/* children is pageContext.Page which is the component defined by +Page.md */}
{children}
</Content>
</>
)
}
See also:
With a custom setting
You can use meta
to create a custom setting for defining local metadata.
// /pages/2024-new-year/+Page.mdx
export const metadata = {
author: {
firstName: 'John',
lastName: 'Smith',
country: 'England'
}
}
## Some Markdown
This page uses [markdown](https://en.wikipedia.org/wiki/Markdown).
MDX allows you to export JavaScript values in
.mdx
files.
Usually, Vike forbids
+Page.js
files to have "side exports": the+Page.js
should only export the value of thePage
setting. But, for improved DX, Vike allows markdown files (such as+Page.mdx
) to export the value of other settings.
// /pages/+config.js
// Create +metadata setting
export default {
meta: {
metadata: {
env: { server: true, client: true }
}
}
}
// /pages/+config.ts
import type { Config } from 'vike/types'
// Create +metadata setting
export default {
meta: {
metadata: {
env: { server: true, client: true }
}
}
} satisfies Config
With frontmatter
Some markdown processors have support for a so-called frontmatter:
---
title: A Markdown Page
author: John Smith
---
## Some Markdown
This page uses [markdown](https://en.wikipedia.org/wiki/Markdown).
You can use such frontmatter to define local metadata.
⚠️We discourage using frontmatter for defining global metadata, because loading all
+Page.md
files at once contradicts Vite's lazy-transpiling approach and it would significantly slow down development speed.
The markdown processor exposes the data defined by the frontmatter as an export, for example export { frontmatter }
. You can access it by using meta
to define a +frontmatter
setting (or whatever the name of the export is).
// pages/+config.js
export default {
meta: {
// Create new setting +frontmatter
frontmatter: {
env: { server: true, client: true }
}
}
}
// pages/+config.ts
export default {
meta: {
// Create new setting +frontmatter
frontmatter: {
env: { server: true, client: true }
}
}
} satisfies Config
You can then use pageContext.config
to access it:
// /pages/+Layout.jsx
import React from 'react'
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
export function Layout({ children }) {
const pageContext = usePageContext()
const { frontmatter } = pageContext.config
return (
<>
<h1>{frontmatter.title}</h1>
{children}
<footer>
<p>Written by {frontmatter.author}.</p>
</footer>
</>
)
}
// /pages/+Layout.tsx
import React from 'react'
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
export function Layout({ children }: { children: React.ReactNode }) {
const pageContext = usePageContext()
const { frontmatter } = pageContext.config
return (
<>
<h1>{frontmatter.title}</h1>
{children}
<footer>
<p>Written by {frontmatter.author}.</p>
</footer>
</>
)
}
See also: