Client-Server Architecture
A base do desenvolvimento web reside no modelo Cliente-Servidor. Esta arquitetura descentralizada separa os provedores de recursos (Servidores) dos requisitantes de serviços (Clientes).
O que é o Cliente?
O cliente é a interface final que consome os recursos da rede. Ele envia requisições estruturadas (Requests) e renderiza a resposta final em interfaces visuais. Exemplos: Google Chrome, Safari, Apps Mobile.
O que é o Servidor?
O servidor é a máquina receptora que escuta portas de rede, processa a lógica de negócio, autentica solicitações, acessa os bancos de dados e responde estruturadamente. Exemplos: Express (Node.js), Spring Boot (Java), Laravel (PHP).
Ciclo de Request/Response
A web funciona estritamente baseada em ciclos fechados. Um cliente envia exatamente uma requisição (Request) e aguarda uma resposta (Response) de volta. O servidor nunca inicia uma comunicação de forma ativa sem uma requisição inicial.
HTTP Protocol Deep Dive
O protocolo HTTP (Hypertext Transfer Protocol) define o formato de mensagens entre o cliente e o servidor. Cada transação é composta por Headers, Body e Metadados específicos.
Clique nos códigos de status abaixo para ver seus significados técnicos, exemplos práticos e como implementá-los no servidor.
HTTP Request Structure
Composta pela linha inicial contendo o método (GET, POST), o recurso requisitado (/index.html) e a versão do protocolo (HTTP/1.1). Segue-se os Headers (metadados como Cookies e User-Agent) e opcionalmente o Body.
HTTP Response Structure
Contém o status code (ex: 200 OK), headers da resposta (Content-Type, Server) e o payload de retorno (HTML, CSS, JSON ou imagens), que o cliente usará para montar e exibir o conteúdo.
HTTP Methods & REST API Simulator
Métodos HTTP (verbos) instruem o servidor sobre qual ação executar em um recurso específico. Numa API REST, cada verbo mapeia para operações de banco de dados (CRUD).
Selecione uma chamada de endpoint abaixo, preencha o payload se necessário, envie a requisição e observe a mudança em tempo real do banco de dados simulado no rodapé do painel.
// Server Response Status: -- Headers: {"Content-Type": "application/json"} Body: []
JavaScript: História, Evolução e Motores
Criado sob pressão em apenas 10 dias por Brendan Eich em 1995 na Netscape, o JavaScript superou críticas iniciais e a fragmentação da Guerra dos Navegadores para se tornar a linguagem soberana da Web moderna, rodando hoje de navegadores a foguetes espaciais.
"Don't Break the Web"
A filosofia central do JavaScript é a compatibilidade retrátil. Isso significa que qualquer script escrito em 1995 ainda deve rodar perfeitamente nos navegadores modernos hoje em dia, evitando que sites antigos quebrem.
Processo de Proposta TC39
A evolução da linguagem é gerida pelo comitê técnico TC39 através de 5 estágios estritos: Stage 0 (Strawman), Stage 1 (Proposal), Stage 2 (Draft), Stage 3 (Candidate) e Stage 4 (Finished/Standardized).
JS no Espaço
O JavaScript não está limitado à web. As telas sensíveis ao toque (touchscreens) das espaçonaves Dragon da SpaceX usam Chromium com JavaScript para renderizar sua interface de controle interativo!
O JavaScript é interpretado/compilado Just-in-Time (JIT) por motores embutidos nos ambientes de execução:
Motor de altíssima performance presente no Google Chrome, Microsoft Edge e nativamente no backend com o Node.js.
O primeiro motor JS da história, desenvolvido por Brendan Eich, hoje mantido e otimizado pela Mozilla para o Firefox.
Motor altamente eficiente focado em baixo consumo energético, utilizado pela Apple no navegador Safari (WebKit).
Estratégias de Carregamento de Scripts
Como o navegador interpreta a tag <script> afeta diretamente a performance e a renderização do HTML da página.
Escolha um método de carregamento e veja como o parser do HTML e o download/execução do script se comportam na linha do tempo.
| Tag HTML | Download | Execução | Bloqueia Parser? | Garante Ordem? |
|---|---|---|---|---|
<script> |
Bloqueia Parser | Imediata | Sim | Sim |
<script async> |
Paralelo | Imediata (assim que baixa) | Sim (durante execução) | Não |
<script defer> |
Paralelo | Após fim do Parser HTML | Não | Sim |
JavaScript Fundamentals
Demonstrações ao vivo de variáveis, arrays, objetos, funções, loops, eventos e manipulação do DOM.
Variáveis & Template Literals
Arrays — map, filter, reduce
// Clique nos botões acima
Manipulação do DOM
Eventos & Loops
Clique no botão para
gerar N
elementos com um loop for:
O JavaScript evoluiu o gerenciamento de escopo no ES6, introduzindo block scope e mitigando erros gerados pelo comportamento de Hoisting (içamento).
| Característica | var | let | const |
|---|---|---|---|
| Escopo | Função / Global | Bloco { } |
Bloco { } |
| Hoisting (Içamento) | Sim (Inicializa como undefined) |
Sim (Inacessível na Zona Morta Temporal) | Sim (Inacessível na Zona Morta Temporal) |
| Redeclaração | Permitida | Bloqueada | Bloqueada |
| Reatribuição | Permitida | Permitida | Bloqueada (Mutável) |
JavaScript possui 8 tipos de dados nativos. Sendo fracamente tipado, realiza conversões implícitas de tipos (type coercion) automaticamente durante certas operações.
Number: Inteiros e flutuantes (ex: 30, 5.5).BigInt: Inteiros gigantes sem limites (ex: 9007199254740991n).String: Texto delimitado por aspas ou template literals.Boolean: Verdadeiro ou falso (true / false).Undefined: Variável declarada mas sem valor atribuído.Null: Ausência intencional de valor. Bug histórico: typeof null retorna "object".Symbol: Identificador imutável único de propriedade.Object: Estruturas complexas (arrays, objetos literais, funções).Digite uma expressão ou escolha um atalho de coerção:
Expressão: -- Valor Resolvido: -- Tipo de Dado: --
Introduzido no ES6, o açúcar sintático de class simplifica a criação de objetos e relacionamentos de herança por protótipos em JavaScript.
class Pessoa { constructor(nome, idade) { this.nome = nome; this.idade = idade; } apresentar() { return `Olá, meu nome é ${this.nome}`; } } class Aluno extends Pessoa { constructor(nome, idade, curso) { super(nome, idade); // Chama o construtor pai this.curso = curso; } estudar() { return `${this.nome} está estudando ${this.curso}`; } }
Utilizamos blocos try...catch para capturar exceções antes que elas quebrem o fluxo principal da aplicação. A palavra-chave throw lança erros personalizados e o bloco finally executa incondicionalmente no encerramento.
try { // Bloco monitorado let x = y + 1; } catch (err) { // Tratador de erro console.error(err.message); } finally { // Roda sempre console.log("Sempre executa!"); }
JavaScript DOM Manipulation
O DOM (Document Object Model) é a representação em memória do HTML gerada pelo navegador. O JavaScript o manipula para alterar dinamicamente a estrutura, conteúdo e estilo dos elementos.
Card Alvo
Você pode modificar o conteúdo e o estilo deste card usando os controles ao lado.
// Operações DOM executadas em tempo real document.getElementById('dom-target').textContent = ...;
O CSSOM é a árvore que representa todos os estilos aplicados ao documento. O JavaScript pode ler estilos computados finais do navegador ou aplicar novos estilos diretamente nos elementos como CSS inline.
// 1. Acessando estilo inline (escrita) element.style.color = "..."; element.style.borderRadius = "...";
// 2. Consultando estilos computados finais (somente leitura) const styles = window.getComputedStyle(element); console.log(styles.color); // Retorna: "rgb(...)" console.log(styles.borderRadius); // Retorna: "..."
JavaScript Events
Eventos são interações detectadas pelo navegador causadas pelo usuário ou ciclo do documento. Ao anexar Event Listeners, ativamos scripts dinamicamente.
Form Validation
A validação de formulários assegura a integridade dos dados enviados. Deve ser aplicada em camadas: HTML5 nativa no front-end para UX imediata, JavaScript para regras de negócio específicas, e obrigatoriamente no back-end.
Validador de Cadastro
Esperar o submit final do formulário para verificar se os dados estão vazios por meio de
alertas nativos do navegador alert(). Isso cria fricção, apaga dados que o
usuário já preencheu e tem péssima acessibilidade.
Dar feedback inline em tempo real à medida que o usuário digita nos campos (validação no
evento input), estilizar os campos como válidos/inválidos dinamicamente e
desabilitar o botão de envio até que os critérios de segurança sejam preenchidos.
Expressões Regulares (Regex)
Expressões regulares são padrões utilizados para realizar buscas, extrações e validações avançadas em strings (como emails, CEPs e senhas).
Escolha um padrão pré-definido ou digite o seu próprio, digite um texto de entrada e veja a validação e substituição ocorrerem ao vivo.
.test() Result: -- .match() Result: -- .replace() Result: --
JSON (JavaScript Object Notation)
JSON é o formato leve e padrão de transferência de dados na web moderna. Possui regras sintáticas estritas e deve ser convertido entre strings e objetos.
JSON Text Editor (String)
Visualizador de Árvore JSON (Object)
Fetch API: Estados e Simulação
A Fetch API fornece uma interface JS moderna e baseada em Promises para obter e enviar recursos da rede assincronamente sem recarregar a página inteira.
Simule requisições assíncronas para entender estados pendentes (Loading), retornos de sucesso e tratamento de erros de API.
// Código Javascript executado fetch('https://api.exemplo.com/dados') .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.error(err));
Fetch API: Integração Real (AJAX)
Busca de dados reais da API pública JSONPlaceholder com loading state, tratamento de erros e renderização dinâmica.
JSONPlaceholder API — jsonplaceholder.typicode.com
// Exemplo de fetch com async/await async function loadPosts() { try { const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5'); const data = await res.json(); renderPosts(data); // Renderiza no DOM } catch (err) { showError(`Erro: ${err.message}`); // Tratamento de erro } }
Clique nos botões acima para carregar dados da API.
REST APIs (Representational State Transfer)
O modelo REST organiza endpoints de redes baseado em recursos representados por substantivos e manipulados pelos verbos HTTP adequados.
/users
Retorna uma lista JSON de todos os usuários cadastrados na base de dados.
/users
Cria um novo usuário na base usando o payload enviado no body da requisição.
/users/12
Deleta permanentemente da base de dados o usuário que possui a chave identificadora correspondente.
Componentes JavaScript Interativos
Apps completos construídos com Vanilla JavaScript: calculadora, to-do list, quiz, countdown timer e catálogo de produtos dinâmico.
🧮 Calculadora
✅ To-Do List
0 tarefas
⏱️ Countdown Timer
🛍️ Catálogo de Produtos (Array → DOM)
🧠 Mini Quiz — JavaScript & JSON
🕹️ Jogo do Clique Rápido
Teste seus reflexos! Você tem 5 segundos para clicar o máximo de vezes possível.
Web APIs Explorer (Navigator)
O navegador moderno oferece dezenas de APIs poderosas para interagir com o hardware e o sistema operacional do usuário.
Battery API
Verifique o nível de carga e se o dispositivo está conectado à energia.
Geolocation API
Obtenha as coordenadas geográficas (latitude/longitude) do usuário.
Vibration API
Faça o dispositivo vibrar (apenas mobile). Útil para notificações e jogos.
Notifications API
Envie notificações do sistema para o usuário, mesmo com a aba em background.
Network Status
Monitore se o usuário está online ou offline em tempo real.
Web Share API
Abra o diálogo nativo de compartilhamento do SO (mobile/tablet).
Media Devices
Liste câmeras e microfones conectados ao dispositivo.
Web Security Fundamentals (HTTP vs HTTPS)
HTTPS (Secure) adds an SSL/TLS cryptographic layer on top of plain HTTP to prevent credential theft and eavesdropping.
Envie dados confidenciais através de conexões com e sem criptografia e veja como terceiros interceptam as informações trafegadas.
Authentication vs Authorization
Enquanto a Autenticação confirma que você é quem diz ser (Quem você é?), a Autorização valida se você tem as permissões necessárias para acessar um recurso (O que você pode acessar?).
Selecione uma credencial de usuário abaixo e veja quais pastas e ações da plataforma simulada são permitidas ou bloqueadas (403 Forbidden).
Autenticação Stateless com JWT (JSON Web Tokens)
O modelo REST prega a comunicação stateless (sem estado), onde o servidor não armazena sessões na memória. O JWT resolve este problema transportando as informações cifradas e assinadas diretamente no token.
Preencha as informações do payload, gere um token assinado fictício e veja como o JWT é dividido em Header (vermelho), Payload (azul) e Signature (verde).
1. Payload Claims (Dados do Usuário)
2. Front-end salva o token no LocalStorage.
3. Requisições enviam no Header:
Authorization: Bearer [token].4. Servidor valida a assinatura usando a chave secreta.
2. String do Token JWT Gerada
3. Decodificador das Partes
{}
{}
HMACSHA256(...)
Cookies, Sessions, and Local Storage
O navegador oferece diferentes métodos para persistência de dados. A escolha depende da necessidade de compartilhamento com o servidor, capacidade e tempo de expiração.
Adicione chaves e valores abaixo para armazená-los diretamente no LocalStorage do seu navegador e veja a tabela atualizar em tempo real.
| Recurso | Capacidade | Tempo de Vida | Envio Automático ao Servidor? |
|---|---|---|---|
| LocalStorage | ~5MB a 10MB | Até ser excluído manualmente | Não |
| SessionStorage | ~5MB | Excluído ao fechar a aba/navegador | Não |
| Cookies | ~4KB | Definido manualmente via Header | Sim (Enviado em cada HTTP Request) |
Frontend vs Backend
A divisão clássica do desenvolvimento web moderna separa as tecnologias do lado do cliente (Frontend) daquelas executadas do lado do servidor (Backend).
Front-end (Client-Side)
O foco do front-end é a experiência do usuário. Ele engloba a estrutura semântica (HTML5), estilização responsiva (CSS3, Flexbox/Grid) e comportamento lógico e assíncrono (JavaScript, React, Vue).
Back-end (Server-Side)
O foco do back-end é o processamento de regras, orquestração e segurança da aplicação. Ele processa requisições complexas, gerencia conexões a bancos de dados persistentes e gerencia a lógica de permissões.
Banco de Dados, ORM e Padrão MVC
A camada de persistência garante que as informações permaneçam salvas. Para organizar esse acesso com segurança e clareza, dividimos a lógica no padrão MVC e utilizamos mapeadores (ORMs) ou consultas SQL diretas.
🗄️ Relacional (PostgreSQL) vs NoSQL
Relacional: Armazena dados em tabelas (linhas/colunas), priorizando consistência e transações seguras (ACID). Padrão utilizado no curso: PostgreSQL (porta padrão: 5432, conexão Supabase / Localhost).
Não Relacional (NoSQL): Armazena documentos flexíveis sem esquemas rígidos (ex: MongoDB).
-- Criar tabela de Usuários CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL ); -- Inserir dados INSERT INTO users (name, email) VALUES ('Juliana Costa', 'juliana@alphatech.com');
🏗️ Conexão Node + DB e Mapeamento ORM
A conexão direta no Node.js é feita pelo módulo pg, alimentado por variáveis secretas salvas no arquivo .env (dotenv).
# Arquivo .env
DB_USER=postgres
DB_PASSWORD=admin
DB_NAME=postgres
DB_HOST=127.0.0.1
DB_PORT=5432
ORM (Object Relational Mapping): Abstrai o SQL puro usando objetos da linguagem (Prisma, Sequelize).
| Abordagem | Vantagens | Desempenho |
|---|---|---|
| SQL Puro | Controle total e rapidez | Mais rápido (~40% mais ágil) |
| ORM | Produtividade e Migrations | Overhead adicional |
Criado em 1979, o MVC separa a aplicação em três camadas principais: a representação de dados (Model), a interface (View) e o controle de rotas/regras de negócios (Controller).
Frameworks Modernos (React, Vue, Angular)
Quando a aplicação cresce, frameworks ajudam a organizar o código através de componentização, estado reativo e roteamento.
React
Biblioteca do Facebook baseada em componentes e Virtual DOM. Foco em declarar como a UI deve ser.
Vue.js
Framework progressivo e versátil. Conhecido pela curva de aprendizado suave e excelente documentação.
Angular
Framework robusto do Google. Inclui tudo o que é necessário para grandes aplicações enterprise.
O Pensamento Reativo (Exemplo React)
function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Contagem: {count} </button> ); }
Diferente do Vanilla JS, onde
você
manipula o DOM manualmente (appendChild), em frameworks você apenas atualiza o
Estado e a UI reage automaticamente.