Sequência da Fase 0 do Nexus. 10 episódios cobrindo o ambiente fim-a-fim — do setup local até a integração entre frontend SvelteKit e backend Spring Boot. Cada accordion tem o áudio + resumo + material completo do episódio. Pode ouvir individualmente ou em sequência.
Contexto do projeto Nexus — propósitos, stack, decisões de fundo
Nexus é projeto pessoal do Flávio com dois propósitos casados: veículo de aprendizado (stack moderna pra praticar o que projeto real exige) e consolidação de informação hoje espalhada em Notion, Todoist, Obsidian, notas, Keep, emails e XTtreinamento.
Stack: Java 25 + Spring Boot 3.5 + JPA/Hibernate + Flyway + Spring Security + virtual threads no backend; SvelteKit + Svelte 5 + TypeScript + Vite no frontend; PostgreSQL 16; deploy planejado em Railway (backend) + Vercel (frontend).
Decisão consciente contra a moda: NÃO usar WebFlux (curva brutal, JPA não funciona, Nexus é single-user). Virtual threads do Java 25 cobrem concorrência sem trocar paradigma. Spring sobre Jasap pra alinhar com mercado (~95% das vagas Java).
O que tem que estar instalado na máquina antes de qualquer linha de código rodar
Instalado: JDK 25 (Oracle, LTS até ~2033), PostgreSQL 16 como serviço Windows (porta 5432, db nexus, user nexus), Git, VS Code (Extension Pack for Java + Svelte), Node.js/npm.
Sem Docker em dev — decisão consciente registrada no nexus.md §13. Manter foco no que era novo (Spring Boot) sem adicionar runtime de container ao mesmo tempo. Postgres direto resolve o mesmo problema com menos camadas. Docker volta na Fase 1 passo 5 (Deploy), porque o Railway aceita imagem.
JAVA_HOME apontando pro JDK, %JAVA_HOME%\bin no PATH. Maven vem do wrapper (mvnw), não global. WSL não, pgAdmin opcional.
Como o esqueleto do backend foi gerado e o que cada starter traz
Esqueleto gerado em start.spring.io: Maven, Java 25, Spring Boot 3.5.13, package io.nexus, JAR (Tomcat embarcado).
Seis dependências: Spring Web (Spring MVC + Tomcat + Jackson), Spring Data JPA (Hibernate + JpaRepository + HikariCP), Flyway (com flyway-database-postgresql separado), Spring Security, Validation (Bean Validation 3), PostgreSQL Driver.
A classe NexusApplication tem só o main com @SpringBootApplication — que junta @Configuration + @EnableAutoConfiguration + @ComponentScan. Auto-configure liga Tomcat, Jackson, DataSource, Hibernate, Flyway e Security por estarem no classpath. Maven escolhido sobre Gradle por familiaridade.
Onde o Spring Boot lê todas as configurações externas
Properties renomeado pra YAML (mais legível pra estrutura aninhada). Configura datasource (URL JDBC, user/senha), JPA, Flyway, virtual threads, server.port e logging.
Decisão crítica: ddl-auto: validate. Quem cria schema é o Flyway, não o Hibernate — dois donos causariam conflito. Validate só confere que entidades batem com o schema; falha cedo se divergir.
Outra armadilha: open-in-view: false. O default true mantém sessão JPA aberta até serializar resposta — esconde queries N+1 e prolonga transação. False força disciplina: tudo carrega no service, controller só vê dado materializado.
Profiles dev/prod ainda não separados — sintaxe ${VAR:default} permite override por env var, suficiente pra Fase 0.
A decisão arquitetural por trás de uma linha no YAML
Platform thread = 1-pra-1 com thread do SO, ~1MB por stack, pool fixo de centenas. Virtual thread = leve (KB), milhões concorrentes, suspende quando bloqueia liberando a platform thread debaixo. Modelo "uma thread por request" volta a fazer sentido.
WebFlux foi descartado: curva brutal (Mono/Flux, stack traces ilegíveis, thread local quebra), JPA não funciona (precisa R2DBC, ecossistema pequeno), várias libs Spring têm versão reactive separada. Nexus é single-user — escala extrema é over-engineering.
Virtual threads dão o melhor dos dois: código bloqueante normal (userRepository.findById) + concorrência alta de graça. Uma linha no YAML (spring.threads.virtual.enabled: true) liga em todos os endpoints, @Async e ThreadPoolTaskExecutor. Aprendizado também: stack mainstream + modernidade essencial, sem triplicar complexidade.
Ajuste mínimo da Fase 0: CORS, CSRF, sessão stateless, /health público
Só de ter o starter no pom, o Security fecha tudo: senha aleatória no log, usuário user default, CSRF ligado, autenticação obrigatória. Pra REST stateless usado por SPA, esse default não serve.
SecurityConfig da Fase 0 cobre 4 coisas: (1) CORS pra origem http://localhost:5173 (sem isso o navegador bloqueia); (2) CSRF desligado (não acrescenta proteção em auth via header Bearer JWT); (3) sessão STATELESS (sem HttpSession, casa com JWT e escala horizontal); (4) /health e /auth/** em permitAll(), resto authenticated.
Padrão restritivo — tudo bloqueado por default, abrir só o público. Preflight OPTIONS aparece no log antes de cada DELETE/PUT — comportamento normal do CORS pra requests não-simples.
Primeiro endpoint REST: ~15 linhas, @RestController + @GetMapping
HealthController com @RestController + @GetMapping("/health") retornando um Map.of("status","ok", "service","nexus-backend", "timestamp", Instant.now().toString()).
@RestController = @Controller + @ResponseBody implícito — qualquer retorno vira corpo HTTP. Jackson (vindo com spring-web) serializa Map em JSON automaticamente. Sem código manual.
Map ad-hoc em vez de DTO porque endpoint trivial; Instant em vez de LocalDateTime (UTC absoluto, ISO-8601 com Z). Pacote io.nexus.common (estrutura por feature, não por camada). Sem Actuator por enquanto — entra se precisar de healthcheck robusto que pingue banco.
Frontend gerado, estrutura, e os runes do Svelte 5
Frontend criado por npx sv create frontend (comando novo do Svelte 5). Skeleton + TypeScript + Prettier + ESLint, sem testes por enquanto.
Rotas file-based: src/routes/+page.svelte = /, +layout.svelte envolve subárvore, +page.server.ts roda no SSR, +page.ts universal.
Svelte 5 runes — maior mudança da linguagem desde 3: $state declara estado reativo (explícito agora, não mais mágico), $derived computa de outros, $effect roda na montagem e quando deps mudam, $props declara props. Vite serve dev (HMR sub-100ms), produção empacota com Rollup. adapter-auto detecta Vercel/Netlify/Cloudflare sozinho.
A request cruzando 5173 → 8080: 18 passos do clique à tela atualizando
Frontend monta → $effect dispara checkHealth → fetch cross-origin (5173 → 8080) → navegador adiciona header Origin → Tomcat recebe → CorsFilter avalia origem → permitAll() deixa passar /health → controller retorna Map → Jackson serializa → resposta volta com Access-Control-Allow-Origin → $state atualiza, Svelte re-renderiza. Tudo em milissegundos.
Por que 2 servers em portas diferentes: ciclos de dev incompatíveis. Frontend tem HMR sub-100ms; backend tem "compila e reinicia" em segundos. Misturar destrói a velocidade do front. Em produção continuam separados (Vercel + Railway).
Erros comuns: "Failed to fetch" (backend off), "No Access-Control-Allow-Origin" (CORS mal configurado), 401 (rota não em permitAll), 404 (controller fora do scan).
Episódio reflexivo — o projeto observado de fora
Episódio diferente: não-técnico, reflexivo. O Flávio pediu carta branca pro Claude expressar a perspectiva dele, encenada por dois apresentadores no NotebookLM.
Observações principais: nexus.md é raro (registra porquê de cada decisão); a escolha "Spring + JPA + virtual threads" é corajosa contra a moda do reactive; obsessão com o porquê é o que diferencia trabalho útil de palpite genérico (e ajuda o próprio Flávio do futuro); pausar o deploy conscientemente é vitória — mostra que projeto é maratona, não sprint; podcast no NotebookLM é workflow incomum que muda relação com material técnico.
Preocupações honestas: nexus.md vai ficar grande, vai precisar quebrar; tentação de cobrir tudo pode virar ruído; Fase 1 muito linear pode ficar inflexível. Sobre IA: 20 minutos escrevendo CLAUDE.md bom valem mais que cem prompts bem feitos.