📚 Módulo 06: Frontend - Setup Next.js, App Router e RSC

Bem-vindo à nova fronteira! Agora que nosso Backend NestJS está operante, construiremos a camada visual da TecLoja 04. Abandonaremos a arquitetura de Single Page Application (Vite) e adotaremos o framework React full-stack mais utilizado da atualidade: Next.js.


🚀 1. Inicializando o Projeto Next.js (Repositório 2)

O Next.js automatiza quase toda a complexidade do ecossistema React. Ele configura roteamento, Webpack, Babel e TypeScript instantaneamente.

No seu terminal, em uma pasta paralela ao backend, execute:

npx create-next-app@latest tecloja-frontend-next

Responda às perguntas interativas recomendadas pela comunidade corporativa:

Entre na pasta (cd tecloja-frontend-next) e limpe o boilerplate do arquivo src/app/page.tsx para podermos começar do zero.


🧠 2. React Server Components (RSC) vs Client Components

A principal inovação do App Router (introduzido no Next 13+) é o paradigma de componentes.

🌐 Server Components (Padrão)

Por padrão, todos os arquivos do Next.js rodam no servidor Node.js. Eles nunca enviam JavaScript para o navegador do cliente, apenas HTML puro pré-renderizado.

💻 Client Components ("use client")

Quando você precisa de interatividade (um botão que recalcula o carrinho, um input de formulário), você dita ao Next.js que aquele componente roda no cliente, adicionando a diretiva "use client" na primeira linha.

flowchart TD
    A[Acesso à Rota /] --> B{O Componente tem interatividade?}
    B -- Não (Catálogo de Imagens) --> C[React Server Component RSC]
    B -- Sim (Botão Adicionar Carrinho) --> D[Client Component use client]
    C --> E[HTML Rápido para SEO]
    D --> F[JavaScript Baixado no Browser]

A arquitetura perfeita é construir Server Components injetando pequenos Client Components dentro deles (apenas nos botões ou partes reativas).


🎨 3. Estilização: TailwindCSS vs CSS Puro

Nos projetos anteriores (TecLoja 02 e 03) criamos layouts Glassmorphic usando arquivos styles.css puros e injetando as classes manualmente. Na TecLoja 04, usaremos TailwindCSS, o motor utilitário embutido por padrão no Next.js.

🥊 Comparativo

Exemplo: Um botão azul com sombra e hover

Abordagem Antiga (CSS Puro)

/* Você precisava alternar entre o arquivo CSS e o TSX constantemente */
.btn-primary {
  background-color: #3b82f6;
  color: white;
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.btn-primary:hover {
  background-color: #2563eb;
}
<button className="btn-primary">Comprar</button>

Abordagem Moderna (TailwindCSS)

/* Todo o design é declarado no próprio elemento via classes utilitárias atômicas */
<button className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded shadow-md transition-colors">
  Comprar
</button>

Benefícios do Tailwind em E-commerces:

  1. Velocidade de Desenvolvimento: Não há “context-switching” (troca de tela) entre HTML e CSS. Você estiliza enquanto codifica a estrutura.
  2. Tamanho do Arquivo Mínimo: O Tailwind purge (remove) todas as classes que você não utilizou no build de produção. Seu CSS final terá pouquíssimos KBs.
  3. Consistência de Design System: As cores (blue-500) e espaçamentos (p-4) são matemáticas estritas, impedindo aquele CSS caótico legado.

🖥️ 4. O Catálogo: Server Component Fetching

Vamos construir a nossa página principal da loja (O Catálogo). Como vitrines de e-commerce precisam de SEO, utilizaremos um Server Component.

Diferente do React padrão, no Next.js Server Components, a função do componente pode ser async e fazer a chamada para nossa API NestJS diretamente do lado do servidor, eliminando telas de Loading horríveis.

src/app/page.tsx

// Sem o 'use client', este arquivo roda no Node.js do servidor Vercel
import React from 'react';
import Link from 'next/link';

// Tipagem correspondente ao nosso DTO do NestJS
interface Produto {
  id: number;
  nome: string;
  descricao: string;
  preco: number;
  estoque: number;
}

// O componente é ASSÍNCRONO!
export default async function CatalogoPage() {
  
  // A requisição acontece no servidor do Next.js antes de enviar a página pro cliente
  // O 'cache: no-store' garante que o Next.js não guarde a tela estática se o estoque mudar
  const res = await fetch('http://localhost:3000/produtos', { cache: 'no-store' });
  const produtos: Produto[] = await res.json();

  return (
    <div className="min-h-screen bg-slate-900 text-slate-100 font-sans p-8">
      <header className="flex justify-between items-center mb-12 border-b border-slate-800 pb-4">
        <h1 className="text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-cyan-300">
          🛒 TecLoja Enterprise
        </h1>
        <nav className="flex gap-4">
          <Link href="/carrinho" className="text-slate-400 hover:text-white transition">Carrinho</Link>
          <Link href="/admin" className="text-slate-400 hover:text-white transition">Admin</Link>
        </nav>
      </header>

      <main className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6">
        {produtos.map((p) => (
          // Efeito de Glassmorphism elegante construído com Tailwind
          <div key={p.id} className="bg-slate-800/50 backdrop-blur-md border border-slate-700/50 rounded-xl p-6 shadow-xl hover:shadow-cyan-900/20 hover:-translate-y-1 transition-all duration-300">
            <h2 className="text-xl font-semibold mb-2">{p.nome}</h2>
            <p className="text-slate-400 text-sm mb-4 h-12 overflow-hidden">{p.descricao}</p>
            
            <div className="flex justify-between items-center mb-4">
              <span className="text-2xl font-bold text-cyan-400">R$ {p.preco}</span>
              <span className={`text-xs px-2 py-1 rounded ${p.estoque > 0 ? 'bg-emerald-900/50 text-emerald-400' : 'bg-rose-900/50 text-rose-400'}`}>
                {p.estoque > 0 ? `${p.estoque} uni.` : 'Esgotado'}
              </span>
            </div>

            {/* Este botão precisa de interatividade. No Módulo 08, o transformaremos num Client Component! */}
            <button disabled={p.estoque <= 0} className="w-full bg-blue-600 hover:bg-blue-500 disabled:bg-slate-700 text-white font-medium py-2 rounded-lg transition-colors">
              Adicionar
            </button>
          </div>
        ))}
      </main>
    </div>
  );
}


✅ Pré-Requisitos deste Módulo

Antes de passar para a configuração do BFF e cookies HttpOnly no Módulo 07, certifique-se de que:


🤔 Por que fizemos assim?


🔍 Checkpoint

  1. Setup do Next.js: Verifique se as dependências do TailwindCSS e TypeScript foram configuradas com sucesso no arquivo package.json no frontend.
  2. Catálogo Renderizado: Execute o servidor local do frontend com npm run dev, acesse http://localhost:3000 e certifique-se de que a vitrine de eletrônicos didáticos semeados no banco carrega instantaneamente.
  3. RSC em Ação: Inspecione o código-fonte da página no navegador (Ctrl+U) e confirme se os produtos e preços do catálogo constam gravados diretamente no HTML enviado pelo servidor (comprovando a pré-renderização).

⚠️ Erros Comuns

Erro Causa Solução
Erro React hooks cannot be used in Server Components ao tentar renderizar a página O desenvolvedor tentou utilizar hooks de estado (useState) ou de ciclo de vida em um Server Component. Server Components rodam estritamente no servidor e não suportam interatividade. Adicione a diretiva "use client" como a primeiríssima linha do arquivo para transformá-lo em Client Component.
Alterações de preço ou estoque no banco de dados não aparecem no catálogo do Next.js O Next.js armazena requisições HTTP em cache de build por padrão, agindo como Static Site Generation (SSG). Adicione a opção { cache: 'no-store' } no segundo parâmetro da chamada de fetch() para forçar a renderização dinâmica (SSR) de dados a cada acesso.
O layout da página aparece desconfigurado e sem os estilos do TailwindCSS O arquivo de configuração do Tailwind não está mapeando a pasta /app ou a pasta /src nas diretivas de leitura. Abra tailwind.config.ts e certifique-se de que a propriedade content inclui todas as pastas de componentes e páginas contendo classes do Tailwind.

🏁 Conclusão

Sensacional! Com apenas um arquivo, nossa vitrine foi renderizada de forma ultrarrápida, já integrada à API NestJS do Módulo 03, e altamente otimizada para o GoogleBot! O uso do Tailwind entregou um layout “Glassmorphic” dark-mode deslumbrante sem a necessidade de um único arquivo .css auxiliar.

No Módulo 07, resolveremos a maior vulnerabilidade técnica do frontend: Autenticação. Criaremos um BFF (Backend For Frontend) via Next Route Handlers para ocultar nosso token JWT.


Voltar para o Sumário