Rendering Markdown files using solid-start and MDX
Sometimes, it's easier to write down content in markdown. However, solid-start doesn't render these by default.
Thankfully, using vite and the mdx project, it's pretty easy to get everything set up.
Dependencies
In an existing solid start project (if you don't have one created already, refer to the getting started docs), install @vinxi/plugin-mdx
pnpm i @vinxi/plugin-mdx
vite.config.js
Add the plugin to your vite.config.js
file
import { defineConfig } from "@solidjs/start/config";import pkg from "@vinxi/plugin-mdx";
const { default: mdx } = pkg;
export default defineConfig({ start: { // Register the extensions with solid-start extensions: ["mdx", "md"], }, plugins: [ // Add and configure the `@vinxi/plugin-mdx` plugin in order to properly handle markdown files mdx.withImports({})({ jsx: true, jsxImportSource: "solid-js", providerImportSource: "solid-mdx", }), ],});
Usage
Simple markdown component
From a jsx or tsx file, the markdown file can then be imported and used directly as a component
# This is a markdown file...
"use server";import Test from "./test.md";
export default function () { return <Test />;}
MDX
Render JSX inside the component
A .md
will be limited to expressing plain markdown. It might instead be useful to render more complex pages by importing and rendering components from within the markdown file.
.mdx
files allow you to render jsx from within a markdown file. For example, if an mdx
file contains the following:
import Counter from "~/components/Counter";
# This is a counter:<Counter />
It will render the Counter
component from the ./components/Counter
inline in the markdown file. Like so:
Frontmatter
From a .mdx
file, you can expose properties that can then be read where the file is embedded.
export const title = "Test Page";...
import * as MarkdownFile from "./test.mdx";
export default function() { return <h1>{MarkdownFile.title}</h1>;}
For instance, the root notes page of this site uses a title
, url
, and date
property on each markdown file in order to render the note index.
Page
The markdown file can also be treated as a page. To do this, use the (.mdx)[https://mdxjs.com/] file extension.
# This is a markdown file...
Navigating to /test
will render the markdown file as a page. (this is how this page is rendered)
Code Syntax Highlighting
Using remark-expressive-code
, code blocks can be highlighted.
Install the needed packages:
pnpm i remark-expressive-code rehype-raw @mdx-js/mdx
Feel free to read up on these packages to understand what they offer. But for this use case, the following configuration will show highlighted code.
Add these imports in vite.config.js
import rehypeRaw from "rehype-raw";import { nodeTypes } from "@mdx-js/mdx";
import remarkExpressiveCode from "remark-expressive-code";
And then configure the remark and rehype plugins:
plugins: [ vinxiMdx.withImports({})({ //... rehypePlugins: [[rehypeRaw, { passThrough: nodeTypes }]], remarkPlugins: [ [ remarkExpressiveCode, { themes: ["min-light", "material-theme-ocean"] }, ], ], }),],});