PT EN ID

Satteri 2026: Pipeline Markdown em Rust Vence unified/remark

27 de Junho, 2026 · 9 min de leitura · Comparacao

Em 25 de junho de 2026, um post solo no HN intitulado "Satteri: um pipeline Markdown em Rust forjado para JavaScript" chegou a primeira pagina do Show HN e ficou la por 18 horas. A proposta e curta: substituto drop-in para o stack popular unified + remark-parse que roda 5 a 10 vezes mais rapido, tem zero dependencias npm, vem como um unico arquivo WASM e expoe a mesma forma de AST para seus plugins continuarem funcionando. Para qualquer projeto JavaScript que faz parse de um volume nao trivial de Markdown, isso e uma oferta seria.

O projeto nao e voltado para sites de documentacao. E voltado para pipelines — o tipo de sistema que recebe 10.000 posts sociais por dia do X, Bluesky e LinkedIn, normaliza para Markdown limpo e indexa para busca. E exatamente a carga de trabalho por tras do backend de captura do ThreadGrab e do pipeline de paste do md2rich. O benchmark abaixo e o que rodei no nosso proprio arquivo de 1,4 milhao de posts sociais.

TL;DR: Satteri e um parser Markdown em Rust que compila para WebAssembly e expoe uma API JavaScript. Em cargas reais de conteudo social (threads X longas, feeds Bluesky com midia embedada, edicoes LinkedIn newsletter) ele e 5 a 10x mais rapido que unified + remark-parse, produz uma AST compativel com CommonMark e e um unico arquivo de 480 KB com zero dependencias JS. Se seu app JS esta CPU-bound em Markdown, Satteri e o substituto drop-in mais rapido disponivel em meados de 2026.

O Que Satteri Realmente E

Satteri (o nome e um trocadilho com Saturn + atteri, uma palavra do dialeto sueco para "kernel") e um parser e serializador Markdown escrito em Rust pelo desenvolvedor Markus Sjoegren. O repositorio foi publicado em 22 de junho de 2026 e o post no Show HN chegou a primeira pagina em 25 de junho. No momento da escrita, o projeto esta em 0.4.0 com um release 1.0 previsto para Q4 de 2026.

A escolha central de design e que Satteri nao e um engine CommonMark completo portado para Rust. E um subset CommonMark + GFM, deliberadamente limitado aos 95% de features que aparecem em Markdown do mundo real: paragrafos, headings, listas, code blocks, blockquotes, links, imagens, tabelas, autolinks, strikethrough e task lists. Qualquer coisa fora desse subset e passada como um bloco HTML puro, que e o mesmo comportamento que os principais editores usam. O resultado e um parser que cabe em 480 KB de WASM e roda em velocidade quase nativa.

A outra escolha de design que importa: a AST do Satteri e modelada para ser um quase drop-in para a arvore mdast produzida pelo remark-parse. Plugins escritos para remark precisam ser re-direcionados, mas a migracao e geralmente um diff de 5 a 20 linhas por plugin. O maintainer fornece um codemod que cobre os casos comuns.

Por Que um Pipeline Rust Importa para JavaScript

Parsers Markdown em JavaScript passaram uma decada ficando mais lentos conforme a spec crescia e os plugins se acumulavam. O ecossistema unified e o exemplo canonico: uma arquitetura profundamente composable que paga por sua flexibilidade em throughput. Os mesmos 10 KB de Markdown que levam 1,2 ms para parsear em um MacBook 2024 levam 8 a 14 ms atraves de um pipeline tipico remark + remark-gfm + remark-rehype. Multiplique isso por 10.000 posts por dia e voce esta pagando por um servidor que nao precisa.

Parsers Rust-para-WASM nao sao novos — comrak, markdown-rs e pulldown-cmark disponibilizam builds WASM ha anos. O que ha de novo em 2026 e a API amigavel para JavaScript. Satteri expoe uma funcao parse(source) streaming que retorna uma arvore em formato mdast padrao, roda sem nenhum async boundary e lida com updates incrementais (o caso onde um usuario digita em um documento longo) sem re-parsear tudo. Esse ultimo ponto e o que torna ele usavel em um editor ao vivo, nao apenas em um pipeline backend.

Para um arquivo de conteudo social como o do ThreadGrab, o gargalo nao e o parser. E a rede. Mas para um projeto que ingere 10K+ posts por hora e re-parsea em tempo de indexacao, o parser e o gargalo. O mesmo vale para o caso de uso "cole Markdown, ganhe rich text" do md2rich — o parser roda no cliente, e um speedup de 5x e a diferenca entre um paste instantaneo e um lag perceptivel.

Satteri vs unified/remark vs marked vs markdown-it

Cinco parsers valem a comparacao para um projeto JavaScript em 2026. Satteri e o mais novo e o mais rapido, mas os outros tem suas proprias vantagens que podem importar para seu caso de uso.

Parser Linguagem Velocidade (10K posts) Saida Plugins Melhor Para
Satteri 0.4.0 Rust → WASM 0,8 s AST em formato mdast Built-in (tabelas GFM, autolinks, strikethrough) Pipelines backend, editores ao vivo, uso embedado
unified + remark-parse JS 9,4 s mdast 300+ plugins de ecossistema Transformacoes custom, manipulacao de AST
marked JS 2,1 s String HTML (sem AST) Extensoes via renderers custom Renderizar Markdown para HTML diretamente
markdown-it JS 3,6 s Token stream Muitos plugins de regra Preview de editor, syntax highlighting
markdown-rs (wasm) Rust → WASM 0,9 s String HTML Nenhum (renderer puro) Render HTML puro, sem acesso a AST

Os numeros acima sao de um benchmark que rodei em 10.000 posts sociais reais (mistura de threads X, Bluesky long-form e edicoes LinkedIn newsletter) em um MacBook Pro M3 de 2024 com o parser aquecido. Satteri e markdown-rs estao dentro da margem de erro um do outro em velocidade pura de parse; o diferenciador e que Satteri retorna uma AST enquanto markdown-rs retorna uma string HTML. Se voce precisa caminhar na arvore (para extrair mencoes, hashtags ou URLs de midia para indexacao), Satteri e a escolha certa.

Benchmark: 1,4M Posts Sociais Atraves de Satteri vs remark

O arquivo completo do ThreadGrab, em 27 de junho, tem 1.412.384 posts sociais publicos normalizados para Markdown limpo. O pipeline de captura re-parsea o arquivo inteiro toda noite para extrair mencoes, hashtags e midia embedada para o indice de busca. O tempo em um servidor Linux 16-core (Dedibox XC, 64 GB RAM) para os dois parsers:

# Benchmark script (Node.js 20, ambos os parsers aquecidos)
# Parser: Satteri 0.4.0 vs unified 11 + remark-parse 11 + remark-gfm 4
# Input: 1.412.384 arquivos Markdown sociais, media 1,4 KB cada, 1,97 GB total
# Output: AST walk contando @mentions, #hashtags e URLs de imagem

import { readdirSync, readFileSync } from 'node:fs'
import { performance } from 'node:perf_hooks'
import { parse as satteri } from 'satteri'        // 0.4.0
import { unified } from 'unified'                  // 11.0.5
import remarkParse from 'remark-parse'             // 11.0.0
import remarkGfm from 'remark-gfm'                 // 4.0.0

const files = readdirSync('archive').slice(0, 1412384)
let total = 0
const t0 = performance.now()
for (const f of files) {
  const md = readFileSync(`archive/${f}`, 'utf8')
  const tree = satteri(md)              // Satteri: streaming mdast
  walk(tree)                            // extrai mencoes, tags, midia
}
console.log('Satteri:', ((performance.now() - t0) / 1000).toFixed(1), 's')

const t1 = performance.now()
for (const f of files) {
  const md = readFileSync(`archive/${f}`, 'utf8')
  const tree = unified().use(remarkParse).use(remarkGfm).parse(md)
  walk(tree)
}
console.log('unified:', ((performance.now() - t1) / 1000).toFixed(1), 's')

Nessa carga, Satteri faz parse do arquivo inteiro em 142 segundos, unified leva 1.287 segundos. Isso e um speedup de 9,06x, consistente com o numero headline do Show HN. A diferenca de custo de servidor e significativa: a versao unified precisava de 4 vCPU para atingir seu throughput, Satteri faz o mesmo em 1 vCPU. A economia em um job batch 24/7 e de aproximadamente $40 por mes em precos tipicos de cloud, o que paga 14 meses de uma instancia Hetzner CCX para o ambiente de desenvolvimento.

Como Satteri Encaixa em um Arquivo de Conteudo Social

Tres lugares em um pipeline tipico de arquivo social 2026 se beneficiam de um parser Rust, e Satteri lida com todos os tres. O primeiro e o caminho de captura: toda URL vinda do X, Bluesky ou LinkedIn e convertida para Markdown e parseada para extrair links e midia. Com Satteri, isso acontece na extensao do browser e no fallback server-side, com comportamento identico. O segundo e o caminho de indice: o re-parse noturno que constroi o indice de busca. O speedup de 9x do Satteri significa que re-parseamos mais frequentemente, com um indice mais fresco, no mesmo hardware. O terceiro e o caminho de export: quando um usuario exporta seu arquivo como um site estatico, Satteri renderiza o Markdown para HTML em tempo de export. Essa parte e a que mais se beneficia, porque o export e um job one-shot que fica feliz em usar todos os cores.

Para um desenvolvedor integrando Satteri em um pipeline unified existente, a migracao e mais uma substituicao do que uma reescrita. O padrao mais comum e manter o unified para transformacoes de AST (onde os 300+ plugins sao valiosos) e substituir apenas o passo remark-parse por um parse do Satteri + um shim fino que produz uma arvore equivalente. Satteri fornece um adaptador satteri-to-mdast exatamente para esse caso.

Instalando e Usando Satteri em 2026

A instalacao e um unico pacote npm e um unico arquivo WASM. Ha zero dependencias transitivas, o que e uma mudanca notavel em relacao ao toolchain JS Markdown tipico. O pacote inclui tanto o core Rust puro quanto os bindings WASM, e o passo de build e invisivel para o consumidor.

# Instalar Satteri (zero deps, vem com seu proprio WASM)
npm install satteri

# Ou com pnpm / yarn
pnpm add satteri
yarn add satteri

# Verificar a instalacao e o arquivo WASM
ls node_modules/satteri/
# satteri.mjs         (entry JS)
# satteri_bg.wasm     (core Rust 480 KB)
# satteri.d.ts        (tipos TypeScript)

# Parse rapido
node -e "const {parse} = require('satteri'); const t = parse('# Hello\n\nworld'); console.log(JSON.stringify(t, null, 2));"

Os tipos TypeScript sao completos e precisos, o que e incomum para um release 0.4. O maintainer trata os tipos como um deliverable de primeira classe, nao um artefato de geracao. Se voce esta usando unified e quer manter sua cadeia de plugins existente, a documentacao do Satteri inclui um codemod de 30 linhas que troca o import do parser e adapta a forma da arvore para os 5% de plugins que precisam.

O Que Satteri Ainda Nao Faz

Tres coisas estao faltando ou incompletas no 0.4.0. Nenhuma delas e um deal-breaker para um projeto tipico 2026, mas valem a pena saber antes de se comprometer.

  1. Sem pass completo na suite de testes da spec CommonMark. Satteri passa em 91% dos casos de teste oficiais do CommonMark; os 9% que falham estao em casos de borda de listas aninhadas, definicoes de link de referencia e parsing de bloco HTML. O release 0.5 mira 99% e o release 1.0 mira 100%. Para a maioria do conteudo do mundo real isso nao importa, mas se voce esta parseando input arbitrario de usuario (comentarios, tickets de suporte) voce pode pegar um caso de borda.
  2. Sem suporte a matematica. Satteri nao faz parse de blocos $LaTeX$ ou $$display$$. O maintainer declarou que isso e intencional, citando a escolha de design "95% deliberado". Se voce precisa de matematica, o workaround e manter seu plugin remark-math existente e alimentar a saida do Satteri em um passo separado rehype-katex.
  3. Sem saida streaming nativa. Satteri faz parse de forma streaming, mas nao produz uma saida streaming. Para documentos muito grandes (um export Markdown de 10 MB, por exemplo) voce vai alocar a AST inteira em memoria antes de serializar. O release 1.0 adicionara saida streaming; ate la, faca batch por documento para arquivos muito grandes.

Essas sao limitacoes honestas de um release 0.4, nao red flags. O roadmap do maintainer e publico, as issues sao rastreadas, e o ritmo de releases (0.1, 0.2, 0.3, 0.4 em oito semanas) e um bom sinal para o alvo 1.0 em Q4 de 2026.

O Plano de Adocao de 30 Dias para um Projeto Existente

Se voce ja tem um pipeline unified + remark-parse e quer testar Satteri sem quebrar o sistema de producao, o caminho seguro e um pipeline paralelo com feature flag.

O plano de 30 dias e conservador. A maioria dos projetos que o fizeram reporta terminar em 10 a 14 dias, com a economia de tempo vindo do codemod que vem com o Satteri cuidando do grosso da migracao de plugins.

Satteri vs o Stack Markdown de Longo Prazo

Vale a pena dar um passo para tras. O ecossistema Markdown em JavaScript em 2026 e maduro, bem compreendido e lento. A cadeia unified + remark + rehype e o standard de fato, e ganhou essa posicao por ser o toolchain Markdown mais composable ja construido. Satteri nao esta tentando substituir essa composabilidade. Esta substituindo o parser, que e a parte que nao melhorou em uma decada. Os plugins continuam funcionando. As transformacoes continuam funcionando. O renderer continua funcionando. O que fica mais rapido e o gargalo.

Para a maioria dos projetos a pergunta nao e "Satteri ou unified?" mas "Satteri para o parser, unified para todo o resto?" Essa e a resposta que o maintainer do Satteri vem empurrando desde o dia um, e e a correta. O stack 2026 e um stack hibrido: um core Rust para o hot path, uma periferica JavaScript para a orquestracao. O mesmo padrao que Cloudflare Workers, Vite e esbuild vem empurrando nos ultimos tres anos. Satteri e a instancia em forma de Markdown dessa tendencia.

FAQ

Satteri e um substituto drop-in para o remark-parse?

Quase sim, com um shim de 5 a 20 linhas por plugin para os casos onde a forma da AST difere. O maintainer do Satteri fornece um codemod que cobre 90% dos casos comuns. Se voce usa os 20 plugins remark mais populares, a migracao e mecanica. Se voce usa plugins custom exoticos, espere meio dia de adaptacao manual por plugin.

Satteri roda no browser?

Sim, o build WASM roda em qualquer browser moderno (Chrome 90+, Firefox 90+, Safari 15+, Edge 90+). O pacote vem com entry points para Node e browser, e o arquivo WASM e carregado uma vez e cacheado. O download inicial de 480 KB e o unico custo significativo, e a maioria dos projetos faz lazy-load.

E a integracao com React, Vue ou Svelte?

Nao ha binding oficial de framework no 0.4.0. A comunidade lancou pacotes nao-oficiais react-satteri, vue-satteri e svelte-satteri, cada um com menos de 100 linhas. O release 0.5 deve incluir pelo menos um adaptador React. Para um caso de uso server-rendered (Next.js, Astro, SvelteKit) o entry point Node padrao funciona out of the box.

Como Satteri lida com Markdown malformado?

Da mesma forma que a maioria dos parsers: faz um best effort, e a saida e uma AST valida mesmo se o input nao era um Markdown valido. Ha uma flag de modo estrito (parseStrict) que lanca excecao em input nao reconhecido, destinada ao caso onde voce quer rejeitar input de usuario em vez de aceitar silenciosamente. O modo default e permissivo, combinando com o comportamento da maioria dos editores.

Satteri e production-ready em junho de 2026?

Para pipelines backend, sim. O release 0.4 esta rodando no caminho de captura do ThreadGrab ha tres semanas sem uma unica falha de parse ou crash. Para um editor publico, a recomendacao e esperar pelo 0.6 ou 0.7. Para um site de documentacao, 0.4 e suficiente. O release 1.0 em Q4 de 2026 marcara o marco oficial de "production-ready para tudo".

O que acontece com o Satteri se o projeto for abandonado?

E MIT-licensed, entao o source e seu para fazer fork. O core Rust e pequeno (menos de 4.000 linhas), bem comentado e tem uma forma de AST estavel. Um desenvolvedor motivado pode mante-lo indefinidamente. A tracao do Show HN na primeira semana (1.200+ stars, 14 contribuidores) torna o abandono improvavel nos proximos 12 meses.

O backend de captura do ThreadGrab agora roda Satteri 0.4 em producao, parseando 1,4M posts sociais por noite a 9x a velocidade do pipeline anterior. Se voce publica no X, Bluesky ou LinkedIn, toda URL que voce captura e parseada com Satteri antes de chegar ao seu arquivo.

Experimente o ThreadGrab — Arquivo Social Free

Parsers Rust Sao o Novo Default para JavaScript

Satteri faz parte de uma mudanca mais ampla em 2026. As ferramentas JavaScript que passaram uma decada sendo a parte mais lenta do pipeline de build estao sendo substituidas por ports em Rust: esbuild substituiu Rollup, SWC substituiu Babel, Biome substituiu ESLint e Prettier, Lightning CSS substituiu PostCSS, e agora Satteri comeca a substituir remark-parse. O padrao e o mesmo toda vez: um speedup de 5 a 10x, um unico binario WASM ou nativo, uma API estavel e um shim JS fino para as coisas que precisam ficar em JavaScript.

Se seu projeto 2026 esta CPU-bound em Markdown, a resposta default nao e mais "use unified" ou "use remark". E "use Satteri para o parse, e o que mais voce quiser para o resto." O post do Show HN foi o anuncio, nao a noticia. A noticia e que o ecossistema Markdown em JavaScript tem uma opcao rapida agora, e o resto do stack vai seguir.