Retour au blog
3 min de lecture

Construire un blog MDX dans Remix

Retour d'expérience sur l'intégration de MDX, Shiki et @tailwindcss/typography dans une app Remix v2 + Vite.

Construire un blog dans une app existante, c'est rarement la priorité — jusqu'au jour où on en a besoin. Voici comment j'ai branché MDX, Shiki et un système de typographie soigné dans Remix v2 sans renverser l'architecture.

Le pipeline en trois plugins#

Tout part de Vite (vite.config.ts). L'ordre des plugins compte : MDX avant Remix, sinon Remix ne voit pas les .mdx comme des routes potentielles.

import mdx from "@mdx-js/rollup"
import remarkFrontmatter from "remark-frontmatter"
import remarkMdxFrontmatter from "remark-mdx-frontmatter"
import rehypePrettyCode from "rehype-pretty-code"
 
export default defineConfig({
  plugins: [
    mdx({
      remarkPlugins: [
        remarkFrontmatter,
        [remarkMdxFrontmatter, { name: "frontmatter" }],
      ],
      rehypePlugins: [
        [rehypePrettyCode, {
          theme: { light: "github-light", dark: "github-dark" },
          keepBackground: false,
        }],
      ],
    }),
    remix({ /* ... */ }),
    tsconfigPaths(),
  ],
})

Lister les articles sans loader serveur#

Avec Vite, import.meta.glob permet de charger tous les .mdx d'un coup :

const modules = import.meta.glob<MdxModule>(
  "../content/blog/*.mdx",
  { eager: true }
)

Chaque module expose default (le composant React) et frontmatter (l'objet parsé). Pour la liste, on extrait juste le frontmatter. Pour la page article, on rend le composant.

Le piège du dual theme Shiki#

rehype-pretty-code peut générer un thème clair et sombre dans le même HTML, en utilisant des CSS variables. Chaque token reçoit --shiki-light et --shiki-dark. À nous de les piloter en CSS :

.prose code span {
  color: var(--shiki-light);
}
html.dark .prose code span {
  color: var(--shiki-dark);
}

Et la typographie ?#

@tailwindcss/typography fait le gros du travail avec sa classe prose. Pour override les couleurs sans toucher au plugin, on définit une variante custom dans tailwind.config.ts (typography.blog) avec les bonnes CSS variables (--tw-prose-body, --tw-prose-links, etc).

Résultat : un article qui ressemble à un article, pas à un dashboard.

Franck Vienot

Publié le 28 mars 2026