Guia pratico, padroes comuns e resolucao de problemas.
// Errado: erro silencioso
exports.criar = async (req, res) => {
const item = await Model.create(req.body);
// Se der erro, o front trava!
};
// Correto: sempre ter try/catch + next
exports.criar = async (req, res, next) => {
try {
const item = await Model.create(req.body);
res.status(201).json(item);
} catch (err) { next(err); }
};
// Errado: ignora validacoes do schema
Model.findByIdAndUpdate(id, dados);
// Correto
Model.findByIdAndUpdate(
id,
dados,
{ new: true, runValidators: true }
);
// Errado
res.json(usuario);
// Correto: nunca retornar a senha
res.json({
id: usuario._id,
nome: usuario.nome,
email: usuario.email
});
// .gitignore (OBRIGATORIO)
node_modules
.env
// Usar .env.example para referencia
MONGODB_URI=sua_url_aqui
JWT_SECRET=seu_segredo_aqui
// Errado: body vai como texto
fetch('/api/items', {
method: 'POST',
body: JSON.stringify(dados)
});
// Correto
fetch('/api/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dados)
});
// Errado: fetch nao lanca erro em 4XX
const data = await fetch(url);
const json = await data.json();
// Correto
const res = await fetch(url);
if (!res.ok) {
const err = await res.json();
throw new Error(err.erro);
}
const data = await res.json();
// Perigoso: usuario pode injetar script
el.innerHTML = dados.nome;
// Seguro: escapar o HTML
function escapeHTML(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
// Errado
headers: {
'Authorization': 'Bearer abc123...'
}
// Correto
const token = localStorage.getItem('token');
headers: {
'Authorization': `Bearer ${token}`
}
// Mostrar loading antes do fetch
btn.disabled = true;
btn.textContent = 'Salvando...';
try {
await fetch('/api/items', { ... });
mostrarMensagem('Salvo!', 'sucesso');
} catch (err) {
mostrarMensagem(err.message, 'erro');
} finally {
btn.disabled = false;
btn.textContent = 'Salvar';
}
async function api(url, opts = {}) {
const token = localStorage.getItem('token');
const res = await fetch(url, {
...opts,
headers: {
'Content-Type': 'application/json',
...(token && {
'Authorization': `Bearer ${token}`
}),
...opts.headers
}
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.erro);
}
if (res.status === 204) return;
return res.json();
}
/* Defina seu tema em :root */
:root {
--primary: #6366f1;
--bg: #0f172a;
--bg-card: #1e293b;
--text: #e2e8f0;
--radius: 12px;
}
/* Use em todo lugar */
.card {
background: var(--bg-card);
border-radius: var(--radius);
color: var(--text);
}
/* Mobile first: comeca pequeno */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
/* Desktop: adiciona colunas */
@media (min-width: 768px) {
.grid {
grid-template-columns:
repeat(auto-fill,
minmax(280px, 1fr));
}
}
console.log(req.body) para ver os dados recebidosconsole.log(err) no catch para ver o erro completoSim, desde que saiba justificar. O front do projeto benchmark usa CSS puro como referencia.
Nao. O front deve ser HTML + CSS + JavaScript vanilla, conforme aprendido nas aulas.
Sim! O minimo e um CRUD completo, mas ter mais modelos enriquece o projeto.
Nao ainda. O deploy sera feito nas aulas 38-39. Foque no desenvolvimento local.
Sim. Cada membro precisa ter commits no repositorio. Sera verificado no historico.
Como referencia, sim. Mas o projeto deve ter tema e funcionalidades diferentes.
Desenvolvimento + revisao de codigo (code review).