Satteri 2026: Pipeline Markdown em Rust Vence unified/remark
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.
- 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.
- 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 pluginremark-mathexistente e alimentar a saida do Satteri em um passo separadorehype-katex. - 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.
- Semana 1: Baseline. Instrumente o passo
remark-parseexistente. Capture tempo de parse, tempo de walk da AST e uso de memoria para um conjunto de inputs representativo. Esse e seu numero "antes" para a comparacao eventual. - Semana 2: Adicione Satteri em paralelo. Instale Satteri, escreva o shim que converte a saida para a forma de AST existente e rode no mesmo conjunto de inputs em um ambiente nao-producao. Compare tempo de parse e forma de AST. O shim deve ser de 20 a 50 linhas.
- Semana 3: Feature flag. Adicione uma flag de runtime que roteia uma porcentagem do trafego de producao atraves do Satteri. Comece em 1%, observe diffs de saida, aumente para 100% se os diffs forem zero. A maioria dos projetos encontra que os diffs se limitam a tratamento de whitespace em casos de borda.
- Semana 4: Limpeza. Remova o import
remark-parse, descarte as dependencias nao usadas, atualize a documentacao. O resultado e um unico arquivo WASM de 480 KB substituindo uma arvore de pacotes npm com 300+ dependencias transitivas.
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
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.
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.
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.
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.
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".
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 FreeParsers 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.