© 2026 Erivelton. Todos os direitos reservados.

Feito com Next.js, Vercel e muito café ☕

Voltar ao blog
metamdx

Referência de Componentes MDX

Manual completo de todos os componentes e recursos disponíveis para escrever posts neste blog.

Publicado em 3 de abril de 2026 por Erivelton Silva12 min de leitura
Cover: Referência de Componentes MDX

Este post é um manual de referência rápida. Aqui estão todos os componentes e recursos disponíveis ao escrever um novo post. Mantenha-o aberto como guia enquanto escreve.


#Markdown nativo

O Markdown padrão funciona normalmente. Todos os elementos abaixo não precisam de componentes extras.

#Tipografia

Negrito, itálico, tachado e código inline funcionam nativamente.

Blockquote para destacar citações ou trechos importantes de outras fontes.

#Âncoras em headings

Todos os headings (##, ###, etc.) recebem automaticamente um id gerado a partir do texto (via rehype-slug) e um link âncora # clicável ao passar o mouse (via rehype-autolink-headings).

O id é gerado em kebab-case. Use para linkar diretamente para uma seção:

[Ir para seção "# Âncoras em headings"](#âncoras-em-headings)

Ir para seção "# Âncoras em headings"

#Links

Links internos e externos são tratados automaticamente pelo componente Link da pasta components/mdx/link.tsx:

  • [texto](/rota) → link interno com Next.js, sem reload de página usando Link do Next.js
  • [texto](https://...) ou [texto](http://...) → abre em nova aba com ícone de link externo e usa 'a' com target="_blank" e rel="noopener noreferrer"
  • www.exemplo.com → detectado como externo e prefixado com https://
  • contato@exemplo.com → vira link de e-mail

Exemplos:

  • Link interno
  • Link externo
  • https://google.com
  • www.google.com
  • contato@exemplo.com

#Listas

Lista não ordenada:

  • Item simples
  • Item com código inline
  • Item com negrito ou itálico

Lista ordenada:

  1. Primeiro passo
  2. Segundo passo
  3. Terceiro passo

Lista de tarefas (via remark-gfm):

  • Tarefa concluída
  • Tarefa pendente

#Tabelas

Suporte nativo via remark-gfm:

PropTipoPadrãoDescrição
variantstring'info'Estilo visual do componente
titlestring—Título opcional
classNamestring—Classes CSS adicionais
childrenReactNode—Conteúdo interno

#Código

O rehype-pretty-code processa os blocos de código com syntax highlight automático. O componente CodeBlock adiciona o botão de copiar.

Bloco simples:

function greet(name: string): string {
  return `Hello, ${name}!`
}

Com title e caption:

utils/greet.ts
function greet(name: string): string {
  return `Hello, ${name}!`
}
Função utilitária de saudação.

Com showLineNumbers:

components/button.tsx
interface ButtonProps extends React.ComponentProps<'button'> {
  variant?: 'default' | 'outline' | 'ghost'
}
 
export function Button({ variant = 'default', className, ...props }: ButtonProps) {
  return (
    <button className={cn(buttonVariants({ variant }), className)} {...props} />
  )
}

Linguagens suportadas: ts, tsx, js, jsx, bash, css, json, html, md, mdx, sql, yaml e muitas outras.


#Callout

Caixas de destaque para informações importantes. Variantes: info (padrão), tip, warning, danger.

Mensagem informativa simples, sem título.

Informação

Use para contexto adicional que complementa o conteúdo principal mas não é crítico para o entendimento.

Dica

Use para boas práticas, atalhos ou formas mais eficientes de fazer algo.

Atenção

Use para alertar sobre comportamentos inesperados, deprecações ou armadilhas comuns.

Cuidado

Use para avisos críticos — dados que podem ser perdidos, falhas de segurança ou erros irreversíveis.

Sintaxe:

<Callout variant='tip' title='Título opcional'>
  Conteúdo do callout. Suporta `código inline` e **negrito**.
</Callout>
PropValoresPadrão
variantinfo tip warning dangerinfo
titlestring—

#Badge

Etiquetas inline para categorizar ou destacar termos.

Variantes:

default primary success warning danger info

Tamanhos:

sm md lg

Modificadores:

dashed primary dashed borderless success borderless

Sintaxe:

<Badge variant='primary' size='md' dashed>texto</Badge>
PropValoresPadrão
variantdefault primary success warning danger infodefault
sizesm md lgmd
dashedbooleanfalse
borderlessbooleanfalse

#Kbd

Representa teclas e atalhos de teclado inline no texto.

Salve com ⌘ + S no macOS ou Ctrl + S no Windows. Abra o terminal com ⌘ + J no VS Code.

Sintaxe:

<Kbd>⌘</Kbd> + <Kbd>K</Kbd>

#Tabs

Conteúdo alternado em abas. Ideal para mostrar o mesmo conteúdo em múltiplas variações — gerenciadores de pacotes, linguagens, frameworks.

A prop tabs define os nomes das abas. Cada Tab recebe um value que deve corresponder a um item do array tabs.

npm install react react-dom

Use defaultValue para definir qual aba abre por padrão (padrão: primeira aba):

<Tabs tabs={['TypeScript', 'JavaScript']} defaultValue='JavaScript'>
  <Tab value='TypeScript'>...</Tab>
  <Tab value='JavaScript'>...</Tab>
</Tabs>

Sintaxe completa:

<Tabs tabs={['Aba 1', 'Aba 2']}>
  <Tab value='Aba 1'>Conteúdo da aba 1</Tab>
  <Tab value='Aba 2'>Conteúdo da aba 2</Tab>
</Tabs>

#Steps

Passo a passo numerado automaticamente. Ideal para tutoriais e guias de instalação.

Instale as dependências

Execute o comando no terminal na raiz do projeto:

bun add react react-dom

Configure o arquivo principal

Crie o arquivo de configuração com o conteúdo abaixo:

// app.config.ts
export default {
  port: 3_000,
  host: 'localhost',
}

Inicie o servidor

Com tudo configurado, suba o servidor de desenvolvimento:

bun dev

Sintaxe:

<Steps>
  <Step title='Título do passo'>
    Descrição e conteúdo do passo. Suporta markdown e blocos de código.
  </Step>
</Steps>

#Accordion

Conteúdo expansível em seções. Útil para FAQs, glossários e informações complementares.

Por padrão (type='single'), apenas um item fica aberto por vez. Com type='multiple', vários itens podem ficar abertos simultaneamente.

Sintaxe:

<Accordion type='single'>
  <AccordionItem title='Pergunta ou título'>
    Resposta ou conteúdo expandido.
  </AccordionItem>
</Accordion>
PropValoresPadrão
typesingle multiplesingle

A prop value do AccordionItem é opcional — por padrão usa o próprio title como identificador.


#FileTree

Visualização de estrutura de arquivos e pastas. Pastas são clicáveis e expansíveis interativamente.

      • layout.tsx
      • page.tsx
  • next.config.ts
  • tailwind.config.ts
  • package.json

Sintaxe:

<FileTree>
  <FileTreeFolder name='src' defaultOpen>
    <FileTreeFolder name='components'>
      <FileTreeFile name='button.tsx' />
    </FileTreeFolder>
    <FileTreeFile name='app.tsx' highlight />
  </FileTreeFolder>
  <FileTreeFile name='package.json' />
</FileTree>
PropComponenteDescrição
nameFolder e FileNome exibido
defaultOpenFileTreeFolderPasta aberta por padrão
highlightFileTreeFileDestaca o arquivo — útil para "edite este arquivo"

#Imagens

#Imagem de capa

Cada post pode ter uma imagem de capa. Basta nomear o arquivo cover e colocá-lo na mesma pasta do index.mdx — nenhuma configuração adicional é necessária.

content/posts/2026-01-15-meu-post/
├── index.mdx
└── cover.jpg   ← detectado automaticamente

A capa aparece no topo do post, logo abaixo do título, e também é usada na OG image gerada para redes sociais. Extensões suportadas: .jpg, .jpeg, .png, .webp, .avif.

#Imagem inline (Markdown)

Imagens inseridas diretamente no Markdown. O caminho é relativo ao index.mdx.

Sintaxe:

![Descrição da imagem](./nome-do-arquivo.jpg 'Título tooltip')

Exemplo:

Imagem de exemplo

#Componente Image

Para imagens com legenda ou controle fino de propriedades, use o componente Image.

Sintaxe:

import MinhaImagem from './cover.jpg'
 
<Image
  src={MinhaImagem}
  alt='Descrição acessível obrigatória'
  title='Título da imagem. Opcional.'
  caption='Legenda exibida abaixo da imagem. Opcional.'
/>

Exemplo:

Exemplo de imagem com legenda usando o componente Image.
Figura 1. Imagem de exemplo com legenda.

#RatioImage

Imagem com proporção fixa usando object-cover. Evita layout shift com imagens de tamanhos variados.

Sintaxe:

<RatioImage
  src={MinhaImagem}
  alt='Descrição acessível'
  ratio={16 / 9}
  title='Título da imagem. Opcional.'
  caption='Legenda opcional.'
/>

Exemplo:

Exemplo de imagem com proporção fixa usando RatioImage.
Figura 2. Imagem com proporção fixa (16:9).

Proporções comuns: 16 / 9, 4 / 3, 1 (quadrado), 21 / 9 (ultrawide).

#ImageGrid

Grade de imagens com número de colunas configurável. O columns definido no ImageGrid é propagado automaticamente via context para todos os GridImage filhos — não é necessário repetir a prop em cada um.

Sintaxe:

<ImageGrid columns={3}>
  <GridImage src={Imagem1} alt='...' caption='Legenda 1' />
  <GridImage src={Imagem2} alt='...' caption='Legenda 2' />
  <GridImage src={Imagem3} alt='...' caption='Legenda 3' />
</ImageGrid>

Para sobrescrever o número de colunas em um item específico, passe columns diretamente no GridImage:

<ImageGrid columns={3}>
  <GridImage src={Imagem1} alt='...' />
  <GridImage src={Imagem2} alt='...' columns={2} />  {/* sobrescreve o contexto */}
</ImageGrid>

Exemplo:

Imagem 1
Legenda 1
Imagem 2
Legenda 2
Imagem 3
Legenda 3
PropComponenteValoresPadrão
columnsImageGrid2 3 4 5 63
columnsGridImage2 3 4 5 6contexto

#YouTube

O id é o código na URL do YouTube — em youtube.com/watch?v=dQw4w9WgXcQ o id é dQw4w9WgXcQ.

Sintaxe:

<Youtube id='m3DJmtLdqhU' />

Exemplo:


#Tweet

Embed de um tweet pelo id. O id está na URL: x.com/user/status/123456789 → id é 123456789.

Sintaxe:

<Tweet id='2026946487599697948' />

Exemplo:


#Emojis

O remark-gemoji converte shortcodes no emoji correspondente.

Sintaxe:

:rocket: → 🚀 | :tada: → 🎉 | :warning: → ⚠️ | :bulb: → 💡 | :white_check_mark: → ✅

Exemplo:

🚀 🎉 ⚠️ 💡 ✅

Referência completa: github.com/ikatyang/emoji-cheat-sheet


#Importando assets locais

Imagens e outros arquivos da mesma pasta podem ser importados diretamente no MDX:

import Cover from './cover.jpg'
import Diagrama from './diagrama.png'
 
<Image src={Cover} alt='Capa do post' />
<Image src={Diagrama} alt='Diagrama de arquitetura' caption='Figura 1.' />

O rehype-mdx-import-media permite referenciar imagens diretamente no Markdown sem import explícito — o plugin resolve o caminho automaticamente.


#Frontmatter

Todo post precisa de um frontmatter válido no topo do arquivo .mdx:

---
slug: 'meu-post'
title: 'Título do Post'
description: 'Descrição curta exibida no card e no SEO.'
publishedAt: '2026-01-15'
tags: ['tag1', 'tag2']
status: 'published'
authors:
  - erivelton
---

#Campo status

ValorComportamento
draftNunca foi publicado — não aparece na listagem e não tem rota gerada
publishedVisível publicamente
archivedRemovido da listagem, mas a URL continua acessível com um banner de aviso

#Campo updatedAt

Quando informado, substitui o publishedAt em todas as exibições de data e troca o ícone de calendário pelo ícone de "atualizado" nos cards e no cabeçalho do post:

---
publishedAt: '2026-01-15'
updatedAt: '2026-04-03'   # opcional — use ao fazer atualizações significativas
---

#Campos para posts de série

Quando o post faz parte de uma série, informe o slug da série e a posição. Ambos os campos são obrigatórios em conjunto:

---
series: 'slug-da-serie'
order: 1
---

O banner da série é exibido automaticamente no rodapé do post com a lista de todos os posts da série e a posição atual destacada.


#Séries

Séries são definidas no arquivo content/series/index.json:

[
  {
    "slug": "minha-serie",
    "title": "Minha Série",
    "description": "Descrição curta da série.",
    "publishedAt": "2026-01-15",
    "status": "in-progress"
  }
]
CampoTipoValoresObrigatório
slugstringkebab-case✅
titlestring—✅
descriptionstringmáx. 300 caracteres✅
publishedAtstringISO date (YYYY-MM-DD)✅
statusstringplanned in-progress complete✅

Após editar o arquivo, regenere o índice:

bun run build:blog

Séries com status in-progress aparecem automaticamente na seção Séries em andamento da home.


#Projetos

Projetos são gerados automaticamente a partir dos repositórios públicos do GitHub via API (@octokit/rest). O controle de quais repositórios aparecem é feito pelos topics de cada repositório na interface do GitHub.

TopicEfeito
portfolioInclui o repositório na listagem de projetos
featuredMarca como destaque — aparece na seção "Em destaque"
wipDefine o status como Em progresso

Repositórios arquivados no GitHub recebem automaticamente o status Arquivado. Os demais aparecem como Ativo.

As tags exibidas no card são os topics do repositório, excluindo os três de controle acima.

Para regenerar a listagem após alterar os topics no GitHub:

bun run build:projects

Variáveis de ambiente

O script de geração de projetos requer um token do GitHub configurado. Certifique-se de que GITHUB_TOKEN está definido no .env.local antes de rodar o comando.

Sugerir alterações
Bun
Bun
@bunjavascript
·Follow

Bun v1.3.10 - Fixes 155 issues (addressing 642 👍) - `bun repl` - native JS/TS repl - Windows ARM64 - ECMAScript decorators - Faster event loop - Barrel file import optimization - Faster structuredClone, Buffer.slice, path.parse Thanks 11 contributors! bun.com/blog/bun-v1.3.…

9:04 AM · Feb 26, 2026
861
Reply
Read 29 replies