O Manifesto No-Build: Publicando Sem um Bundler
O texto a seguir não é um argumento para que você abandone suas ferramentas de build. É uma medição do que acontece quando você o faz.
blakecrosley.com roda FastAPI + Jinja2 + HTMX + Alpine.js + CSS puro. Sem webpack. Sem Vite. Sem Rollup. Sem compilador TypeScript. Sem Babel. Sem PostCSS. Sem Tailwind. Sem package.json. Sem node_modules/. O site serve 33 posts de blog com 14 componentes JavaScript interativos, 20 guias, traduções em nove idiomas e pontua 100/100/100/100 no Lighthouse.
TL;DR
A comunidade HTMX tem bastante advocacy. O que falta é evidência. Os números aqui vêm de um site em produção com conteúdo substancial, recursos interativos e internacionalização — tudo sem uma única ferramenta de build. Os tradeoffs são honestos, e a conclusão é específica: para sites orientados a conteúdo com um desenvolvedor solo ou equipe pequena, ferramentas de build resolvem problemas que você não tem enquanto criam problemas que você tem. Para equipes grandes com bibliotecas de componentes compartilhadas e pacotes de design system, ferramentas de build justificam sua complexidade. A fronteira é mais clara do que o discurso sugere.
A Stack
Backend: FastAPI + Jinja2 (server-rendered HTML)
Frontend: HTMX + Alpine.js + Bootstrap 5 (CDN)
Styles: Plain CSS with custom properties
JavaScript: Vanilla JS, IIFE-scoped per component
Deployment: Railway (git push → live)
CDN: Cloudflare (caching, Workers, D1)
Sem transpilação. Sem tree shaking. Sem hot module replacement. Sem source maps. O JavaScript que você escreve é o JavaScript que vai para produção.
Os Números
Aqui estão as métricas reais — não estimativas:
| Métrica | blakecrosley.com | Projeto Next.js Típico (estimativa do autor)1 |
|---|---|---|
| Dependências | 18 pacotes Python | 300+ pacotes npm |
| Arquivos de configuração de build | 0 | 5-8 (next.config, tsconfig, postcss, tailwind, eslint, babel, etc.) |
Tamanho do node_modules/ |
Não existe | 150-400 MB |
| Tempo de instalação | pip install -r requirements.txt: 8 segundos |
npm install: 30-90 segundos |
| Etapa de build | Nenhuma | next build: 15-60 segundos |
| Pipeline de deploy | git push → no ar em ~40 segundos |
git push → install → build → deploy: 2-5 minutos |
| Arquivos CSS | 14 arquivos, 10.300 linhas (CSS puro) | Gerados a partir de Tailwind/Sass, saída varia |
| Arquivos JS | 33 arquivos, 10.061 linhas (legíveis por humanos) | Empacotados, minificados, divididos em chunks: ilegíveis em produção |
| Performance no Lighthouse | 100 | Varia (frequentemente 70-90 sem trabalho de otimização) |
Os 18 pacotes Python incluem FastAPI, Jinja2, Pydantic, SQLAlchemy e outros 14. Nenhum é uma ferramenta de build. Nenhum é um compilador. Nenhum é um bundler.2
O Que Você Perde
Honestidade exige listar os custos reais. E eles são reais.
Sem TypeScript. Cada arquivo .js neste projeto é JavaScript puro. Testes e a análise do Claude Code capturam erros de tipo, não um compilador. A abordagem funciona para um desenvolvedor solo. Não funcionaria para uma equipe de 10 pessoas compartilhando interfaces de componentes entre módulos.
Sem Hot Module Replacement. Quando altero um arquivo CSS, atualizo o navegador manualmente. O hx-boost do HTMX torna a navegação rápida o suficiente para que atualizações completas sejam toleráveis. Em um projeto onde estou iterando em detalhes visuais a cada 30 segundos, o HMR economizaria tempo significativo.
Sem Tree Shaking. Cada byte de JavaScript que escrevo vai para o navegador. Não consigo importar uma única função de uma biblioteca utilitária sem enviar o arquivo inteiro. A restrição impõe disciplina: arquivos pequenos e focados em vez de grandes módulos utilitários. Os 14 componentes interativos têm em média 300-700 linhas cada porque precisam ser autocontidos.3
Sem Biblioteca de Componentes do npm. Sem Radix, sem shadcn/ui, sem Headless UI. Cada elemento interativo (a simulação de boids, o visualizador de código de Hamming, o simulador de consenso) é construído manualmente. A abordagem só é viável porque os componentes interativos servem a propósitos pedagógicos específicos, não a padrões genéricos de UI.
Sem Design System Tokens do npm. Meu design system vive inteiramente em CSS custom properties. Não consigo importá-lo como um pacote em outro projeto. Para um sistema de site único, a restrição é aceitável. Para uma organização com múltiplos produtos, não é.
Os cinco tradeoffs são aceitáveis para um site orientado a conteúdo com um desenvolvedor. Seriam inaceitáveis para um produto SaaS com uma equipe de engenharia de 15 pessoas.
O Que Você Ganha
Zero falhas de build. O pipeline de deploy é git push. Nenhum npm install pode falhar por conflito de peer dependency. Nenhum next build pode falhar por erro de TypeScript em um arquivo que não toquei. Nenhum PR do Dependabot atualiza uma dependência transitiva e quebra o build.4
Debug com View Source. O JavaScript que roda no navegador é o JavaScript que escrevi. Sem necessidade de source maps. Sem mapeamento de saída compilada para código original. Quando um bug aparece em produção, leio o arquivo implantado diretamente.
Startup local instantâneo. uvicorn app.main:app --reload inicia em menos de 2 segundos. Sem npm run dev que instala, compila e empacota antes de mostrar uma página.
Zero ruído do Dependabot. Sem package-lock.json significa sem PRs semanais atualizando semver, ansi-regex ou glob-parent: pacotes que nunca importei diretamente, mas que vivem três camadas abaixo na minha árvore de dependências.
À prova de futuro. O site vai funcionar daqui a 10 anos. O HTML é HTML. O CSS é CSS. O JavaScript é JavaScript. Não existe migração de Webpack 4 → 5, nem depreciação do Create React App, nem migração para o App Router do Next.js. A plataforma é o padrão.5
HTMX Como Arquitetura
O discurso sobre HTMX foca na sintaxe: hx-get, hx-swap, hx-target. Esse é o enquadramento errado. O insight arquitetural é que HTML renderizado no servidor é a API.
Em uma SPA tradicional:
Browser → fetch('/api/users') → JSON → React renders HTML → DOM update
Com HTMX:
Browser → GET /users (hx-get) → Server renders HTML fragment → DOM swap
O servidor retorna a representação final. Sem gerenciamento de estado no cliente, sem serialização/desserialização, sem hidratação. O template Jinja2 é o componente. O endpoint FastAPI é a API. Uma camada, não três.6
O padrão se mapeia diretamente ao princípio de engenharia composta: cada peça de infraestrutura faz exatamente uma coisa, e as peças se compõem sem interferência. Um template renderiza HTML. Uma rota o retorna. O HTMX o insere no DOM. Nenhuma etapa de build coordena essas peças porque nenhuma coordenação é necessária.
CSS Puro Funciona
Meu design system usa 10 tokens de cor, 13 etapas de escala tipográfica e oito valores de espaçamento — todos CSS custom properties:
:root {
--color-bg-dark: #000000;
--color-text-primary: #ffffff;
--color-text-secondary: rgba(255,255,255,0.65);
--spacing-sm: 1rem;
--spacing-md: 1.5rem;
--font-size-lg: 1.25rem;
}
Sem etapa de compilação Sass. Sem configuração Tailwind gerando utilitários. Sem plugins PostCSS transformando sintaxe customizada. O navegador lê esses valores diretamente.7
A estética de beleza e brutalismo deste site (branco sobre preto absoluto com quatro camadas de opacidade) emerge da restrição. Quando você não pode recorrer a uma paleta de cores, a tipografia carrega a hierarquia. Quando você não pode recorrer a sombras de componentes, o espaço em branco cria estrutura. A restrição é o design.8
A Jornada do CLS
A jornada do Lighthouse expôs um custo genuíno do no-build: a extração de CSS crítico exigiu um script Python customizado. Em um projeto Next.js, o framework lida com isso automaticamente.
O bug específico: uma media query mobile sobrescrevia uma CSS custom property (--gutter: 48px → --gutter: 24px). O CSS crítico incluía o valor desktop, mas não a sobrescrita mobile. No mobile, o hero renderizava com 48px de padding, depois mudava para 24px quando a folha de estilo completa carregava, produzindo um CLS de 0,493.
A correção foram 12 linhas de Python. A investigação levou três horas. Uma ferramenta de build teria lidado com isso automaticamente.
A contabilidade honesta: ferramentas de build automatizam coisas que você pode fazer manualmente, mas a versão manual custa tempo de debugging quando quebra. A questão é se o custo da automação (complexidade, dependências, falhas de build, churn de migração) excede o custo manual (sessões ocasionais de debugging).
Para este site, o custo manual tem sido menor. Três anos, um bug de CLS, três horas de debugging. A alternativa (manter um pipeline de build) teria consumido mais tempo cumulativo em atualizações de dependências, breaking changes e manutenção de configuração.
Quando Não Usar Isso
A abordagem no-build é errada para:
Equipes grandes. O valor do TypeScript escala com o tamanho da equipe.9 Quando 10 desenvolvedores compartilham interfaces de componentes, a verificação de tipos em tempo de compilação previne bugs de integração que testes em runtime capturam tarde demais. Um desenvolvedor solo mantém todo o sistema na cabeça. Uma equipe não consegue.
Pacotes de design system. Se múltiplos produtos consomem seu design system, ele precisa ser um pacote npm com versionamento adequado, tree shaking e um pipeline de build. CSS custom properties em uma única folha de estilo não se compõem entre repositórios.
Estado complexo no cliente. Se sua aplicação tem estado rico no lado do cliente (interfaces de arrastar e soltar, colaboração em tempo real, dados offline-first), um framework como React ou Svelte justifica sua complexidade. O HTMX substitui estado do cliente por round-trips ao servidor, o que funciona até que a latência importe.
Bibliotecas do ecossistema npm. Se você precisa de primitivos Radix, Framer Motion ou TanStack Query, você precisa de um pipeline de build. Os três assumem um bundler. Usá-los sem um varia de doloroso a impossível.
A fronteira é mais simples do que o discurso sugere: se sua aplicação é primariamente conteúdo renderizado por um servidor, ferramentas de build são overhead. Se sua aplicação é primariamente estado gerenciado por um cliente, ferramentas de build são infraestrutura.
Principais Conclusões
Para desenvolvedores solo e equipes pequenas:
-
A prova é o site, não o argumento. blakecrosley.com serve 33 posts, 14 componentes interativos, 20 guias e nove idiomas com zero ferramentas de build e pontuações perfeitas no Lighthouse. Os números são verificáveis.
-
O custo honesto do no-build é debugging ocasional. O bug de CLS levou três horas para corrigir. Uma ferramenta de build teria lidado com ele automaticamente. Ao longo de três anos, o tempo cumulativo de debugging foi muito menor do que o tempo cumulativo de manutenção que um pipeline de build teria exigido.
-
Restrições produzem design. Sem cores forçou a tipografia a carregar a hierarquia. Sem ferramentas de build forçou JavaScript simples e autocontido. As melhores restrições são aquelas que você escolhe antes de precisar delas.
Para líderes técnicos avaliando escolhas de stack:
-
Ferramentas de build resolvem problemas de escala de equipe. TypeScript, tree shaking e bibliotecas de componentes justificam sua complexidade quando múltiplos desenvolvedores compartilham interfaces. Um desenvolvedor solo construindo sites orientados a conteúdo não tem esses problemas.
-
A contribuição real do HTMX é arquitetural. HTML renderizado no servidor como API elimina gerenciamento de estado no cliente, serialização e hidratação. A sintaxe é secundária em relação ao insight.
Este artigo conecta as seções de Design e Engenharia do blog. Decisões de design aparecem em Beleza e Brutalismo, Design Systems para Startups e Escalas Tipográficas. As medições de engenharia estão em Pontuação Perfeita no Lighthouse e Engenharia Composta. O post sobre vibe coding explora onde essa filosofia se aplica ao desenvolvimento assistido por IA.
-
A coluna “Projeto Next.js Típico” reflete a experiência do autor em mais de 5 projetos Next.js (2021-2024) e normas relatadas pela comunidade. Os números específicos (300+ pacotes, 150-400 MB de node_modules) são consistentes com números comumente reportados na comunidade Node.js. Projetos individuais variam significativamente. Os números são estimativas do autor, não benchmarks verificados independentemente. ↩
-
Lista completa de dependências em fevereiro de 2026: fastapi, uvicorn, starlette, pydantic, pydantic-settings, jinja2, markdown, pygments, beautifulsoup4, lxml, nh3, resend, python-dotenv, python-multipart, slowapi, httpx, sqlalchemy, analytics-941. Zero são ferramentas de build. Zero são compiladores. Zero são bundlers. ↩
-
O tamanho médio dos componentes (300-700 linhas) foi medido a partir dos 14 arquivos JS interativos em
/static/js/em fevereiro de 2026. Os tamanhos variam de 240 linhas (signal-calculator.js) a 690 linhas (boids-simulation.js). ↩ -
Baseado na experiência do autor mantendo projetos Next.js, o ecossistema JavaScript gera 15-25 PRs do Dependabot por mês para um projeto ativo, a maioria atualizando dependências transitivas que o desenvolvedor nunca importou diretamente. O número é uma estimativa de observação direta, não um benchmark verificado independentemente. ↩
-
A plataforma web (HTML, CSS, JavaScript) manteve compatibilidade retroativa por 30 anos. Uma página de 1996 ainda renderiza no Chrome 2026. Tim Berners-Lee articulou isso como um princípio de design: “um navegador deve ser retrocompatível, no sentido de que deve ser capaz de ler uma versão anterior da linguagem.” Veja w3.org/DesignIssues/Principles. ↩
-
Carson Gross, criador do HTMX, enquadra isso como “hipermídia como motor do estado da aplicação” (HATEOAS). Veja os ensaios do htmx.org e o livro Hypermedia Systems (2023) de Gross, Stepinski e Cotter: hypermedia.systems. ↩
-
CSS Custom Properties (Variáveis CSS) são suportadas em 97%+ dos navegadores globais. Fonte: caniuse.com/css-variables. Nenhuma etapa de compilação é necessária para usá-las. ↩
-
O princípio de “restrição como ferramenta de design” tem uma longa história. Charles Eames: “O design depende em grande parte das restrições.” O movimento Dogma 95 no cinema provou que remover ferramentas (sem iluminação artificial, sem pós-produção) produziu narrativas mais honestas, não menos. Veja en.wikipedia.org/wiki/Dogme_95. ↩
-
A Pesquisa de Desenvolvedores Stack Overflow 2024 constatou que TypeScript é a 4ª linguagem mais popular e o superset mais popular de JavaScript, com adoção escalando proporcionalmente ao tamanho da equipe. Veja survey.stackoverflow.co/2024/. ↩