1Requisição chegamiddleware.ts lê o path, detecta o locale (cookie "locale" ou Accept-Language via detectLocaleFromAcceptLanguage) e reescreve /pt/sobre -> /sobre com o header x-locale; /admin e /api passam direto (isPassthrough).
2Tema/animação já vêm certosapp/layout.tsx lê os cookies "theme" e "reduce-motion" antes de renderizar -- sem cookie, o padrão é escuro e animado. Não depende de JS no cliente, então não tem flash de tema errado.
3Server Component rodaA página (ex: app/(site)/sobre/page.tsx) é async e busca dados direto no servidor, sem JS extra pro cliente.
4Conteúdo vem cacheadogetSiteContent()/queries-cached.ts usa unstable_cache do Next -- não bate no Supabase em toda requisição.
5Texto bilíngue é resolvidoresolveText(pt, en, locale) escolhe a versão certa do texto conforme o locale detectado, usando o dicionário de lib/i18n/dictionaries.ts.
6HTML pronto é enviadoA página já renderizada chega no navegador; hidratação do React só liga as partes interativas (animações, forms).
1Pessoa digitaSearchPanel espera 300ms sem digitação (debounce) antes de disparar a busca, pra não bater na API em toda letra.
2POST /api/searchapp/api/search/route.ts recebe { query } e primeiro checa o rate limit (countRecentSearchesFromIp, padrão 20/min).
3Duas buscas em paralelosearchFullText (Postgres, tsvector) e searchSemantic (embeddings) rodam ao mesmo tempo; a semântica tem timeout de 4s pra não travar a resposta.
4Reciprocal Rank FusionreciprocalRankFusion (lib/search/rank.ts) combina as duas listas de resultado num ranking só, sem um método dominar o outro.
5Log e respostalogSearchRequest grava a busca (pra métricas de /status) e o resultado combinado volta pro SearchPanel.
1Toda tabela novaMigração cria a tabela + política de RLS + grant explícito -- RLS sozinha não libera o client JS do Supabase, precisa do grant também. Tabelas principais: projects, articles, languages, authors, companies, messages, resume, resume_links, contact_links, site_content, search_index, search_requests, mcp_connections (+ project_authors/project_languages como tabelas de junção).
2Leitura públicalib/supabase/queries.ts usa a anon key, só leitura, filtrando pelas policies de RLS (ex: só conteúdo visível).
3Mutação autenticadalib/supabase/admin-queries.ts usa o client autenticado da sessão do admin -- policies de RLS exigem auth.uid() válido.
4Acesso via MCPlib/supabase/service.ts monta um client próprio por conexão MCP, respeitando as permissões daquele token específico.
1Tenta acessar /adminmiddleware.ts intercepta e checa a sessão do Supabase Auth via cookie.
2Sem sessão -> /admin/loginshouldRedirectToLogin decide o redirect; com sessão válida, a requisição segue normal.
3Login por e-mail/senhaapp/admin/login/actions.ts chama supabase.auth.signInWithPassword({ email, password }); a sessão vira cookie via @supabase/ssr, sem token separado pra gerenciar no cliente.
4Edita numa abaCada aba (Projetos, Artigos, Tecnologias, Autores, Empresas, Mensagens, Contato, Personalização, Currículo, Imagens, MCP, Preview) chama uma função de admin-queries.ts, ex: upsertProjeto.
5Grava no PostgresA mutação passa pelas policies de RLS que exigem usuário autenticado.
6Reindexa pra buscareindexProject/reindexArticle (lib/supabase/search-index.ts) geram um embedding novo do texto e gravam na tabela search_index -- é o que a busca semântica lê depois.
7Cache do site precisa atualizarComo o público lê via cache (unstable_cache), a mutação revalida a tag certa pra a mudança aparecer no site.
1Pasta configurada no admindrive_folder_url no conteúdo do site guarda qual pasta do Drive é a fonte das imagens.
2Markdown referencia por nomeUm texto escreve ; remark-drive-images resolve isso pra uma URL real.
3Busca na API do Drivelib/drive.ts procura o arquivo por nome dentro da pasta configurada -- token do Drive nunca sai do servidor.
4Proxy pro navegador/api/drive-image/[fileId] e /api/drive-video/[fileId] servem o arquivo como proxy, sem expor a API do Drive direto pro cliente.
1Conexão criada no adminA aba MCP gera um token novo e define quais permissões aquela conexão específica tem.
2Cliente de IA chama a APIPOST /api/mcp com o token (header Authorization ou X-Auth-Token, pra clientes que não deixam setar Authorization).
3Token é validadolib/mcp/auth.ts confere o token e carrega as permissões daquela conexão específica.
4Servidor MCP é montadolib/mcp/server.ts + registerMcpTools só registram as tools/resources que aquela conexão tem permissão de usar.
5Tool roda no SupabaseCada tool lê ou escreve via lib/supabase/service.ts, dentro do que foi permitido pra aquele token. Cobre CRUD completo por permissão: projetos, artigos, tecnologias, autores, empresas (upsert/delete/list de cada); mensagens (list/marcar lida/delete); links de contato e de currículo; currículo (read/update); e o conteúdo do site (read/set/delete de cada chave).
1Formulário client-sidecontact-form.tsx valida nome/e-mail/mensagem antes de enviar.
2Grava no SupabaseA mensagem é salva numa tabela própria, sem precisar de autenticação (RLS permite só o insert).
3Aparece no adminA aba Mensagens lista as mensagens recebidas, com opção de marcar como lida.
4Também acessível via MCPUma conexão MCP com a permissão certa pode ler as mensagens de contato como recurso.
1Flag geral no admineaster_eggs_ativo liga/desliga todos de uma vez, sem precisar deploy novo.
2Cada um é independenteSudoEasterEgg, SpinEasterEgg e Mascote são componentes client separados, cada um escutando seu próprio gatilho.
3Exemplo: o mascoteMascote conta cliques numa janela de tempo curta; ao bater o número certo, abre o vídeo via /api/drive-video/[fileId].
1Página busca ao vivoA cada acesso a /status, o servidor mede as métricas na hora -- nada fica pré-calculado. Mostra também o deploy atual e a branch em uso, lidos de verdade, não hardcoded.
2Latência do bancoUma query simples é cronometrada contra o Supabase pra mostrar o tempo real de resposta.
3Última republicação/reindexTimestamps guardados no próprio conteúdo do site, atualizados quando o conteúdo muda ou a busca é reindexada.