MDX
An alternative way to author content is using .mdx
files (Markdown JSX). These files are authored as Markdown, but they are compiled down to Qwik components. In addition to Markdown syntax, .mdx
files can also refer to other components.
Let's assume you have your routes set up like this:
src/
└── routes/
└── some/
└── path/
└── index.mdx # https://example.com/some/path
---
title: Hello World Title
---
This is a simple hello world component.
The above component will be rendered at https://example.com/some/path
.
Importing other components.
MDX is a creative opportunity for you to come up with new content quickly ("Qwikly" 🙂) and if you need more interaction on your page you can seamlessly integrate your Qwik components like so:
src/
├── components/
| └── counter
│ └── counter.tsx
└── routes/
└── some/
└── path/
└── index.mdx # https://example.com/some/path
---
title: Hello World Title
---
import { Counter } from "../../../components/counter/counter";
This is a simple hello world component.
<Counter />
import { component$, useSignal } from '@qwik.dev/core';
export const Counter = component$(() => {
const count = useSignal(0);
return (
<button class="counter" type="button" onClick$={() => count.value++}>
Increment {count.value}
</button>
);
});
Note: A key difference between Qwik Router and some other meta-frameworks' routers is directory-based routing. Every route needs to be defined as a-directory/index.(tsx,ts,js,jsx,md,mdx)
.
In other meta-frameworks' routers about.mdx
might render the route http://example.com/about
. However, this will not work in the Qwik Router. You must rename the file to about/index.mdx
for Qwik Router to know to render it.
Disabling default MDX plugins included.
Qwik Router includes 3 plugins by default.
- remarkGfm: GFM support (autolink literals, footnotes, strikethrough, tables, tasklists).
- rehypeSyntaxHighlight: Lightweight, robust, elegant virtual syntax highlighting using Prism.
- rehypeAutolinkHeadings: Plugin to add links to headings in HTML.
These plugins can be disabled independently in the following way:
import { defineConfig } from 'vite';
import { qwikRouter } from '@qwik.dev/router/vite';
// See below
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
export default defineConfig(() => {
return {
plugins: [
qwikRouter({
mdxPlugins: {
remarkGfm: false,
rehypeSyntaxHighlight: false,
rehypeAutolinkHeadings: false,
},
mdx: {
rehypePlugins: [
// Plugins can now be added manually to use a different configuration
[rehypeAutolinkHeadings, { behavior: 'wrap' }],
],
},
}),
/* the rest of the configuration */
],
};
});
Open Graph Properties
You can use og
or opengraph
property to define Open Graph protocol metadata.
title: My Title
description: My Description
og:
- title: My Custom Title
description: true
- image: https://example.com/rock.jpg
image:alt: A shiny red apple with a bite taken out
- image: https://example.com/rock2.jpg
Setting og:title
or og:description
to true
will check and use outside title
and description
property instead. Thus, you can avoid writing a same title and description twice.
The above example will generate the following HTML code.
<title>My Title</title>
<meta name="description" content="My Description" />
<meta property="og:title" content="My Custom Title" />
<meta property="og:description" content="My Description" />
<meta property="og:image" content="https://example.com/rock.jpg" />
<meta property="og:image:alt" content="A shiny red apple with a bite taken out" />
<meta property="og:image" content="https://example.com/rock2.jpg" />
Reading frontmatter data
Frontmatter keys are accessible by leveraging the useDocumentHead()
hook.
---
title: Hello World Title
tags:
- super
- exiting
- docs
---
import { Tags } from "../../../components/tags/tags";
This is a simple hello world component.
<Tags />
import { component$ } from '@qwik.dev/core';
import { useDocumentHead } from '@qwik.dev/router';
export const Tags = component$(() => {
const { frontmatter } = useDocumentHead();
if (frontmatter.tags.length === 0) {
return null;
}
return (
<ul>
{frontmatter.tags.map((tag: string) => (
<li key={`tag-${tag}`}>{tag}</li>
))}
</ul>
);
});