← voltar à cena

Mindscape

Portfólio imersivo onde o mapa do site é um cérebro 3D gerado por código: nenhum arquivo de modelo, nenhuma textura, e orçamento de peso que falha o build.

Estudo técnico · não publicado — conteúdo de exemplo · agosto de 2026

O problema

Sites imersivos costumam cobrar um pedágio. Você espera cinco segundos numa tela preta, baixa oito megabytes de modelo e textura, o notebook liga a ventoinha, e no celular ou trava ou cai num “versão simplificada” que ninguém projetou de verdade. O efeito impressiona uma vez e atrapalha todas as outras.

Este projeto começou de uma pergunta específica: dá para fazer um portfólio genuinamente tridimensional que pese menos que uma foto? Não “3D leve para os padrões de 3D” — leve de verdade, com o número escrito num orçamento que reprova o build quando estoura.

A ideia: a arquitetura de informação é anatomia

O que segura a peça de pé não é a técnica, é a metáfora. O mapa do site é um cérebro, e cada região anatômica é uma seção — escolhida pela função real daquela região, não pelo desenho:

  • Lobo frontal → Projetos (planejamento e execução)
  • Cerebelo → Habilidades (a parte motora, o que se faz sem pensar)
  • Hipocampo → Carreira (memória)
  • Sistema límbico → Sobre mim (afeto)
  • Córtex sensorial → Formação (o que entrou pelos sentidos)
  • Sinapse → Contato (a conexão)
  • Corpo caloso → Trabalhe comigo (a ponte entre dois hemisférios)

São cinco regiões de conteúdo mais duas de ação — e a piada só funciona porque cada nome é funcionalmente honesto. Um menu que diz “Sobre / Projetos / Contato” desaparece da memória; um que diz “Hipocampo” faz a pessoa parar meio segundo.

Home do Mindscape sobre fundo preto: menu superior com Projetos, Habilidades, Carreira, Sobre mim, Formação, Contato, Trabalhe comigo e Blog; à esquerda o título Um mapa do que eu construo, com a instrução Arraste para explorar cinco regiões; à direita um cérebro tridimensional em wireframe azul e violeta, com pontos alaranjados brilhando na superfície e um campo de estrelas ao fundo.
A abertura. O menu carrega os dois nomes — o anatômico e o funcional — e o cérebro fica à direita, girável com o dedo ou o mouse desde o primeiro segundo.

Como isso se sente

Print não vende cena 3D. O que segue é a captura do canvas real, rodando: o arrasto girando o cérebro, o mergulho da câmera para dentro de uma região quando você escolhe uma no menu, e a volta à superfície com Esc.

Quadro parado da cena: o cérebro tridimensional visto de perto, quase preenchendo o quadro, com a casca em azul translúcido, filamentos internos e dezenas de pontos de luz alaranjados.
Sete segundos e meio do canvas, sem interface por cima. Quem pede menos movimento no sistema não recebe o vídeo: o quadro parado entra no lugar, e o arquivo nem chega a ser baixado.

O mergulho é uma curva Bézier de 1,7 s na ida e 1,5 s na volta, e ele muda a URL: cada região tem rota própria — /regiao/frontal-lobe, /regiao/hippocampus e assim por diante. Isso importa mais do que parece, porque significa que a experiência é linkável, indexável e compartilhável, em vez de um estado interno que só existe depois de alguém clicar na ordem certa.

Uma região aberta: a câmera está dentro do cérebro, que ocupa a direita da tela em azul profundo com pontos de luz; à esquerda o título Lobo Frontal, planejamento e execução de projetos, seguido de uma entrada de projeto de exemplo.
Região aberta: a câmera está dentro do modelo e o item do menu virou o nome da região. O texto do projeto é de exemplo — o conteúdo real é a última pendência da peça, e a seção final deste caso é explícita sobre isso.

Um cérebro sem nenhum arquivo

Aqui está o truque que define o projeto: não existe modelo, não existe textura, não existe .glb. O cérebro é calculado no navegador a partir de uma esfera.

Como a geometria do cérebro é gerada A cena parte de uma esfera comum da three.js. Cada vértice dessa esfera é deslocado por um ruído fractal de quatro oitavas, cujos números pseudoaleatórios vêm de um gerador semeado com a semente zero — o que torna o resultado idêntico em toda execução. As normais são recalculadas depois do deslocamento, e não antes, para que a iluminação corresponda à superfície nova. O resultado é um buffer de posições, e é justamente esse buffer que o CI resume em SHA-256: dois builds limpos precisam produzir o mesmo hash, senão o gate reprova. Nenhum byte de modelo ou textura é baixado em nenhuma etapa. um cérebro sem nenhum arquivo esfera base SphereGeometry da three deslocamento FBM 4 oitavas mulberry32 SEED = 0 normais recalculadas depois do deslocamento buffer de posições a geometria pronta SHA-256 no CI dois builds, um hash 0 byte baixado A semente é o que separa "procedural" de "aleatório": sem ela o cérebro mudaria de forma a cada visita, e não haveria hash a comparar. Trocar uma constante de ruído muda o hash e o CI acusa — a forma do cérebro é versionada como se fosse código.
A parte que costuma surpreender é o gate de hash. Como a geometria é função pura de uma semente fixa, o CI consegue resumir o buffer de posições em SHA-256 e exigir que dois builds limpos produzam exatamente o mesmo valor. Uma otimização que mudasse a forma sem querer não passa despercebida.

Duas consequências práticas caem de graça. A primeira é que não há o que otimizar em pipeline de asset: não existe compressão de textura, LOD de malha nem CDN de modelo, porque não existe arquivo. A segunda é que a forma vira parâmetro — mudar a rugosidade do córtex é editar uma constante, não reabrir um software de modelagem e reexportar.

Orçamento de peso que reprova o build

A disciplina que segura tudo isso é chata e é o ponto: os orçamentos são gate de build, não observação em pull request.

O caminho crítico e onde a cena entra O que bloqueia a primeira pintura da página é apenas o HTML, o CSS e um script de casca, medidos em 3,79 quilobytes comprimidos com brotli contra um teto de 60. A primeira pintura acontece antes de qualquer coisa de três dimensões existir. Só depois um import dinâmico busca o pacote da cena, com a biblioteca de 3D, a de animação e o código da cena, medido em 134,76 quilobytes brotli contra um teto de 200. O verificador não soma arquivos às cegas: ele varre o diretório de build servido, segue as dependências a partir do HTML e separa o import dinâmico como grafo próprio; se não encontrar nenhum script bloqueante ou nenhum import dinâmico, ele falha em vez de reportar zero. o caminho crítico HTML + CSS + casca 3,79 KB brotli · teto 60 primeira pintura ainda sem nada em 3D import() dinâmico pacote da cena 134,76 KB brotli · teto 200 cérebro na tela só depois do paint Grafo vazio é falha, nunca "0 KB, tudo certo": o gate desconfia de si mesmo.
O medidor não soma a pasta de build: ele varre o HTML servido, segue as dependências estáticas e isola o import() da cena como um grafo separado, comprimindo cada arquivo em brotli. E se o parser não achar script bloqueante nem import dinâmico, ele falha — porque um "0 KB" silencioso seria um bug se passando por aprovação.

Os tetos são explícitos no código, não em documentação solta: 60 KB de caminho crítico, 200 KB para o pacote da cena, 8 KB de CSS, 12 draw calls, 220 mil triângulos, 2000 segmentos de linha, 900 pontos. E há um teto que vale por todos: zero assets binários na cena. Um .png que aparecesse por descuido reprovaria o build.

O blog leva a mesma regra ao extremo: os artigos são páginas estáticas com 0 KB de JavaScript. A peça inteira não tem uma única ilha hidratada — nenhuma diretiva client:* no projeto. É essa ausência que permite uma política de segurança com script-src 'self' sem unsafe-inline e sem nonce, porque simplesmente não existe script inline para liberar.

O que acontece quando ninguém está olhando

Medi isto no navegador, com a aba em primeiro plano: com a página parada e o canal de vida desligado por flag, a cena desenha zero quadros em cinco segundos. Ela não roda um laço de animação eterno; ela redesenha quando a câmera muda, e mais nada.

O que se vê na home parada — os pulsos de luz correndo pelos filamentos — é um canal separado e deliberado, adicionado depois por emenda ao próprio design. Ele desliga sozinho em cinco situações: sob prefers-reduced-motion, no perfil de máquina fraca, com a aba em segundo plano, com uma região aberta, e sob a flag que o CI usa para poder comparar pixels.

No mesmo lugar, a cena da home custa 6 draw calls e 51.692 triângulos — contra tetos de 12 e 220 mil. A folga serve para subir o número de segmentos da esfera nas máquinas que aguentam, sem reescrever nada.

Funciona sem JavaScript, sem WebGL e sem movimento

Um site imersivo que só funciona no caminho feliz para de ser produto e vira demonstração. Os três degraus abaixo estão implementados — dá para conferir cada um.

Sem JavaScript: o conteúdo das sete regiões é renderizado no build e vive em HTML real. O menu é feito de links <a href> verdadeiros para rotas estáticas — clicar funciona, o buscador indexa, e o mergulho de câmera é o aprimoramento que entra por cima quando há JS.

Sem WebGL: se o contexto não existe, um fallback pinta um gradiente radial estático com as cores da marca num canvas 2D. Não é uma tela de erro; é a mesma composição, parada.

Sem movimento: sob prefers-reduced-motion, o mergulho não vira uma animação rápida — ele deixa de ser animação. O código pula o tween inteiro e reposiciona a câmera direto, e existe um teste que falha se qualquer chamada de animação escapar. Nesta própria página, a mesma regra vale para o vídeo acima.

As decisões e o que cada uma custou

Astro com zero ilhas, em vez de um framework de componentes. Compra 0 KB de runtime e a política de segurança rígida. O preço é que qualquer interatividade precisa ser escrita à mão em TypeScript puro — não há estado reativo de graça.

CSS nativo com variáveis OKLCH, em vez de Tailwind. Um teto de 8 KB de CSS não sobrevive a um framework utilitário, e a alternativa de componentes prontos exigia React, que não existe aqui. O preço é escrever o sistema de tokens à mão.

A cena é função pura do progresso. Nada de acumular estado entre quadros — sem relógio interno, sem +=. Isso foi o que tornou possível o teste que compara pixels: ir e voltar precisa produzir a mesma imagem, pixel a pixel. O preço apareceu quando os pulsos de sinapse foram pedidos: em vez de quebrar a regra, abriu-se um segundo eixo de tempo isolado, com as cinco condições de desligamento descritas acima.

Medir o three antes de projetar em cima dele. A primeira tarefa do projeto foi um teste de peso da biblioteca, com poder de veto. Ele reprovou a premissa original na primeira medição, e a decisão subiu para o humano — que preferiu emendar o orçamento a trocar a stack. O preço foi um dia de trabalho antes da primeira linha de cena; o retorno foi não descobrir isso na véspera da entrega.

Contato por mailto:, sem formulário. Qualquer formulário exigiria abrir a política de rede ou subir um serviço, e o custo-alvo da peça era zero. O preço é a conversão menor de quem não tem cliente de e-mail configurado.

Estado

A peça foi construída em uma semana — 112 commits entre 4 e 10 de agosto de 2026. A suíte tem 500 testes de unidade verdes em 68 arquivos e 114 testes de ponta a ponta em 18 arquivos, e os orçamentos passam com folga confortável na medição de hoje.

Duas ressalvas, ditas na cara: o conteúdo ainda é de exemplo — nomes, textos e links de projeto são placeholders, e preencher isso com material real é a última pendência antes de publicar. E a peça nunca foi ao ar: a esteira de publicação existe e está fechada por gate justamente por causa do conteúdo, que é o comportamento desejado — o pipeline se recusa a publicar um site com texto de exemplo.

Vale registrar uma reviravolta de arquitetura, porque ela é a parte mais honesta da história. O projeto nasceu com a cena acoplada ao scroll, numa narrativa de quatro atos. Em uso, isso se revelou pior do que a ideia no papel: ler a página e conduzir a câmera brigavam pelo mesmo gesto. A narrativa por scroll foi removida e o arrasto assumiu — a cena virou um palco estável que a pessoa explora, em vez de um filme que ela avança sem querer. Trocar a tese central de um projeto no meio custa caro; manter uma tese que não funciona custa mais.

Quer conversar sobre este projeto — ou sobre construir algo assim? Fale comigoou escreva para contato@daniel-dac.com.

Ver os outros projetos