youhide@homelab: ~/blog

$cat rebuilding-this-site.md

Deleting the build step

Apagando o build

This site had two pages of content. Serving them took a static site generator, a theme vendored as a git submodule pinned to a commit from 2019, an SCSS build cache checked into the repository, and a deploy that pushed the result over FTP using a third-party action pinned to a mutable @master ref.

Este site tinha duas páginas de conteúdo. Para servir isso eram necessários um gerador de site estático, um tema vendorizado como submódulo git travado num commit de 2019, um cache de build SCSS commitado no repositório e um deploy que empurrava o resultado por FTP usando uma action de terceiro travada numa ref mutável @master.

None of that was a problem, exactly. It worked. It had worked for years. But I kept opening the repo, remembering how it was wired, and closing it again — which is a slow way of saying I had stopped writing anything.

Nada disso era exatamente um problema. Funcionava. Funcionou por anos. Mas eu abria o repositório, lembrava como aquilo era ligado, e fechava de novo — que é um jeito lento de dizer que eu tinha parado de escrever.

What the overhead actually was

Qual era o overhead de verdade

Three things, and only one of them is about convenience:

Três coisas, e só uma delas é sobre conveniência:

  • A supply chain I did not control. A deploy action on @master holds my FTP credentials and can change under me between one push and the next.
  • A theme frozen in 2019. Every visual change meant reading somebody else's SCSS to find the variable that would let me override it.
  • A build step between me and the output. To answer "why is this margin here" I had to run the generator, not read a file.
  • Uma cadeia de suprimentos que eu não controlava. Uma action de deploy em @master segura minhas credenciais de FTP e pode mudar sozinha entre um push e o seguinte.
  • Um tema congelado em 2019. Qualquer mudança visual significava ler o SCSS dos outros pra achar a variável que me deixaria sobrescrever aquilo.
  • Um build entre mim e o resultado. Pra responder "por que essa margem está aqui" eu tinha que rodar o gerador, não ler um arquivo.

What replaced it

O que entrou no lugar

Four HTML files, one stylesheet, one script, and a GitHub Pages artifact deploy that publishes the site/ subdirectory so repository sources never reach the published tree:

Quatro arquivos HTML, uma folha de estilo, um script e um deploy de artefato do GitHub Pages que publica o subdiretório site/, de forma que os fontes do repositório nunca chegam à árvore publicada:

site/          everything that gets published
  index.html
  about/
  projects/
  blog/
  404.html
  css/style.css
  js/main.js   language toggle and tag filter
assets/        source files, NOT published

Preview is python3 -m http.server 8000 --directory site. The URL structure is identical to production because there is no transformation between them — what is in the folder is what is on the domain.

O preview é python3 -m http.server 8000 --directory site. A estrutura de URL é idêntica à de produção porque não existe transformação entre as duas — o que está na pasta é o que está no domínio.

Bilingual without a pipeline

Bilíngue sem pipeline

Both languages ship in the same markup. Every translatable string exists twice, tagged with lang, and CSS hides the inactive one:

Os dois idiomas vão no mesmo markup. Cada string traduzível existe duas vezes, marcada com lang, e o CSS esconde a inativa:

html[data-lang="en"]    [lang="pt-BR"],
html[data-lang="pt-BR"] [lang="en"] { display: none !important; }

A short script flips data-lang on <html> and stores the choice. It is loaded synchronously in <head>, so the right language is set before the body paints — no flash of the wrong one. With JavaScript disabled the page keeps the language hardcoded in the file and still renders correctly. The cost is real: every paragraph is written twice, and this post is no exception.

Um script curto troca o data-lang no <html> e guarda a escolha. Ele é carregado de forma síncrona no <head>, então o idioma certo é definido antes do body pintar — sem flash do idioma errado. Com JavaScript desligado a página mantém o idioma fixo no arquivo e renderiza normalmente. O custo é real: cada parágrafo é escrito duas vezes, e este post não é exceção.

Zero external requests

Zero requisições externas

System monospace stack, inline SVG icons, no CDN, no analytics, no font service. The page loads from one origin and asks nobody else for permission to finish rendering. This is the part I would keep even if I went back to a generator.

Stack de monoespaçada do sistema, ícones SVG inline, sem CDN, sem analytics, sem serviço de fontes. A página carrega de uma origem só e não pede permissão pra mais ninguém pra terminar de renderizar. Essa é a parte que eu manteria mesmo se voltasse pra um gerador.

What I gave up

O que eu abri mão

Honestly: this does not scale, and I know exactly where the wall is. Every new post is a new folder with a full HTML document in it, and the index, the sitemap and the RSS feed are updated by hand. At twenty or thirty posts that becomes the kind of repetitive work I write tools to avoid — and when it does, I will write the tool, and it will be mine.

Sinceramente: isso não escala, e eu sei exatamente onde está a parede. Cada post novo é uma pasta nova com um documento HTML inteiro dentro, e o índice, o sitemap e o feed RSS são atualizados na mão. Em vinte ou trinta posts isso vira o tipo de trabalho repetitivo que eu escrevo ferramentas pra evitar — e quando virar, eu escrevo a ferramenta, e ela vai ser minha.

Until then, the whole site is something I can read top to bottom in one sitting. For a personal site that is worth more than any feature I removed.

Até lá, o site inteiro é uma coisa que eu consigo ler de ponta a ponta de uma sentada. Para um site pessoal isso vale mais do que qualquer feature que eu tirei.