Devlog · Fase 0 · 2/7
A stack de aubia.dev: Octane, FrankenPHP e Inertia SSR
Uma latência dividida por cinco a dez graças a Octane e FrankenPHP, um SSR Inertia que serve o HTML completo já no primeiro byte: a stack de aubia.dev, bloco por bloco.
- laravel
- octane
- frankenphp
- inertia
- vite

aubia.dev serve seu HTML completo já no primeiro byte e responde com uma latência dividida por cinco a dez em relação a um PHP-FPM clássico. Para uma landing, isso não é luxo: uma vitrine tem um único trabalho não negociável, ser vista. Pelos visitantes, mas antes pelos motores de busca e pelos motores de resposta de IA. Abro para você a stack, com o raciocínio por trás de cada bloco.
O rendering do lado do servidor como invariante de SEO
Uma aplicação React clássica retorna uma casca HTML vazia e depois popula a página em JavaScript. Um navegador se acomoda a isso. Um crawler ou um motor de resposta, por sua vez, precisa encontrar o conteúdo diretamente no HTML da primeira resposta.
É por essa razão que me proibi o rendering apenas do lado do cliente nesta vitrine. O SSR comanda ali todo o resto. O Inertia v3 renderiza as páginas React do lado do servidor, e o HTML completo sai já no primeiro byte: título, subtítulo, seções, metadados de SEO, tudo está presente antes que uma única linha de JavaScript seja executada do lado do cliente. A hidratação assume em seguida o comando pela interatividade. Essa regra, o conteúdo precisa existir no HTML inicial, dita todo o resto do código frontend, até a proibição de exibir conteúdo por meio de um useEffect.
Octane e FrankenPHP: o servidor que não reinicia
Instalei o Octane logo no primeiro dia do repo, no fim de abril de 2026, antes mesmo de escrever a menor linha de conteúdo. É uma escolha de base, não uma otimização acrescentada depois. Em PHP tradicional, cada requisição reinicia a aplicação: carregamento do framework, resolução do container, depois resposta. O Laravel Octane muda esse modelo. A aplicação sobe uma vez, e depois workers persistentes servem milhares de requisições dentro do mesmo processo.
Faltava escolher o driver. Olhei o RoadRunner e o Swoole, as duas outras opções do Octane, antes de decidir pelo FrankenPHP: ele embarca o servidor Caddy nativamente, com HTTP/3, certificados automáticos e streaming sem camada adicional a operar, e seu roadmap é ativo no ecossistema Laravel.
// config/octane.php
'server' => env('OCTANE_SERVER', 'roadrunner'),
# .env : le driver actif sur aubia.dev
OCTANE_SERVER=frankenphp
Sobre essa base, o bootstrap do Laravel permanece em memória e a latência por requisição cai por um fator de cinco a dez em relação ao cold start do PHP-FPM. Um tempo de resposta do servidor baixo e estável conta para o score de performance e, portanto, para o ranqueamento. Mas esse modelo impõe uma disciplina que abordo mais abaixo.
Inertia v3: React sem uma API separada
O ponto que torna essa stack agradável é o Inertia. Ele faz a ponte entre Laravel e React sem que eu precise construir e versionar uma API REST separada. Os controllers retornam páginas React com suas props, do mesmo modo que retornariam views Blade. O SSR se ativa na configuração, sem servidor Node distinto a manter em desenvolvimento.
// config/inertia.php
'ssr' => [
'enabled' => true,
'url' => 'http://127.0.0.1:13714',
],
Concretamente, Inertia::render() substitui as views, as rotas permanecem definidas do lado do Laravel, e o React só se preocupa com o rendering. Uma única fonte de verdade para o roteamento, sem lógica duplicada entre um backend e um frontend que se ignoram.
Vite 8, Rolldown e React 19
Do lado do build, aubia.dev usa o Vite 8 com Rolldown, o bundler escrito em Rust integrado nativamente. O React 19 é compilado com o React Compiler, que memoiza automaticamente os componentes sem anotações manuais. O particionamento do bundle é conduzido explicitamente para isolar as grandes dependências em seus próprios chunks:
// vite.config.ts
codeSplitting: {
minSize: 20_000,
groups: [
{ name: 'react', test: /node_modules\/(react|react-dom|scheduler)\//, priority: 50 },
{ name: 'motion', test: /node_modules\/(motion|motion-dom)\//, priority: 40 },
{ name: 'fontawesome', test: /node_modules\/@fortawesome\//, priority: 30 },
],
},
Separar o React, as animações e os ícones permite ao navegador colocar em cache o que muda pouco e recarregar apenas o que muda. O build de produção gera, além disso, um bundle SSR dedicado via vite build --ssr.
A restrição stateless
Um servidor que nunca reinicia mantém tudo em memória entre as requisições. É justamente isso que o torna rápido, e é também sua armadilha. Sob o Octane, armazenar um estado próprio de uma requisição em um singleton ou em uma propriedade estática o faria vazar para a requisição seguinte, servida pelo mesmo worker. Todo o código da vitrine respeita, portanto, esta regra: nenhum estado de requisição é retido para além do seu escopo.
A contagem da lista de espera, por exemplo, é carregada de forma diferida para não bloquear o rendering do servidor em uma chamada de rede, e seu resultado chega em uma segunda requisição do lado do cliente:
'waitlist' => [
'count' => Inertia::defer(fn(): ?int => app(FetchWaitlistCountQuery::class)->run()),
],
O SSR permanece assim instantâneo, e o dado não determinístico nunca entra no primeiro render. Esse rigor stateless irriga cada módulo do repo.
O que a velocidade ainda não diz
Octane, FrankenPHP e Inertia dão uma vitrine rápida e indexável. Essa sobriedade vai ainda mais longe: a próxima etapa retira o próprio banco de dados, e com ele todo armazenamento local de dados pessoais.
Para ser avisado quando a beta 0.1 abrir, entre na lista de espera.
Esta construção é contada aqui, artigo após artigo. Embarque: o seu feedback desenhará o que vem a seguir.
Entrar na lista de espera