Este post é para desenvolvedores. Vamos abrir o capô do sistema de blog que você está lendo agora e explicar cada decisão de arquitetura — desde como os arquivos .mdx viram páginas até como um componente interativo é injetado no meio do texto sem comprometer a performance do servidor.
A Stack
O blog roda sobre o Next.js App Router (v16) e usa duas dependências centrais:
next-mdx-remote— compila MDX em React Server Components, sem necessidade de configurar loaders no bundler.gray-matter— extrai o frontmatter YAML do topo de cada arquivo.mdx.
Não usamos @next/mdx (que transforma .mdx diretamente em páginas dentro de app/) porque precisávamos de controle programático para listar, ordenar e filtrar posts — algo que exige ler os arquivos como dados, não como rotas.
Estrutura de Arquivos
src/
├── content/
│ └── blog/
│ ├── hello-world.mdx ← este arquivo
│ └── outro-post.mdx
├── lib/
│ └── blog.ts ← lê e parseia os .mdx
├── components/
│ ├── MDXComponents.tsx ← mapeamento de componentes
│ ├── AmortizationDemo.tsx ← componente interativo ('use client')
│ ├── BlogHeader.tsx
│ └── BlogFooter.tsx
└── app/
└── blog/
├── page.tsx ← listagem (/blog)
└── [slug]/
└── page.tsx ← post individual (/blog/[slug])
Os posts ficam em src/content/blog/, completamente separados do código da aplicação. O nome do arquivo é o slug da URL: hello-world.mdx vira /blog/hello-world.
Como o Conteúdo é Carregado
O módulo blog.ts expõe duas funções:
getBlogPosts()— lê todos os.mdxdo diretório, extrai o frontmatter comgray-mattere retorna uma lista de metadados ordenada por data (mais recente primeiro).getPostBySlug(slug)— lê um arquivo específico e retorna o conteúdo bruto + metadados.
Ambas rodam no servidor (Node.js fs), nunca no browser. O Next.js chama essas funções em build time (para generateStaticParams) e em request time (para renderização).
Compilação do MDX
No componente da página [slug]/page.tsx, o conteúdo bruto do .mdx é passado para o MDXRemote do next-mdx-remote/rsc:
import { MDXRemote } from 'next-mdx-remote/rsc';
<MDXRemote
source={post.content}
components={mdxComponents}
/>
O MDXRemote compila o markdown em JSX no servidor, gerando HTML estático. Isso significa que o corpo do artigo não precisa de JavaScript no client — a menos que um componente específico exija interatividade.
Componentes Customizados
O arquivo MDXComponents.tsx mapeia cada elemento HTML nativo para um componente React estilizado:
export const mdxComponents = {
h2: (props) => <h2 className="font-serif font-semibold text-foreground ..." {...props} />,
p: (props) => <p className="text-muted-foreground leading-[1.8] ..." {...props} />,
blockquote: (props) => <blockquote className="border-l-2 border-primary/40 ..." {...props} />,
// ...
AmortizationDemo, // componente interativo
};
Todas as classes usam CSS variables do design system (text-foreground, bg-card, border-primary), não cores hard-coded. Isso garante que se o tema mudar, o blog muda junto.
Componentes Interativos
Componentes como o AmortizationDemo abaixo são marcados com 'use client' e carregam JavaScript apenas quando necessários. No MDX, basta usá-los como uma tag:
<AmortizationDemo />
E o resultado é um componente React completo, renderizado inline no artigo:
Simulação Rápida (PRICE)
A hidratação acontece apenas para esse componente. O restante do artigo continua sendo HTML estático.
Como Criar um Novo Post
Crie um arquivo .mdx em src/content/blog/ com o frontmatter obrigatório:
---
title: "Título do Post"
date: "2026-07-20"
description: "Resumo que aparece na listagem."
tags: ["tag1", "tag2"]
---
Escreva o conteúdo em Markdown normal. Para usar um componente interativo, registre-o no objeto mdxComponents em MDXComponents.tsx e chame-o pelo nome no corpo do texto.
Não é necessário reiniciar o servidor de desenvolvimento — o hot reload detecta novos arquivos automaticamente.
Como Adicionar um Novo Componente Interativo
O fluxo completo:
- Crie o componente em
src/components/com a diretiva'use client'no topo. - Importe-o em
MDXComponents.tsxe adicione-o ao objetomdxComponents. - Use
<NomeDoComponente />no corpo do seu.mdx.
O MDXRemote resolve a referência automaticamente na hora da compilação. Não é necessário importar nada dentro do arquivo .mdx — o mapeamento em mdxComponents é o catálogo de tudo que está disponível.
O que acha de testar essa solução no seu próprio projeto? Navegue pelos posts do Visconde, aprenda sobre finanças, e veja como criamos um sistema de baixo custo para ter nosso próprio blog.


