Toolbox
Configuración, design tokens, Git, Docker y utilidades que uso a diario.
Docker : referência rápida
# Acessar shell de um container em execução
docker exec -it $(docker ps --format "{{.ID}} {{.Names}}" | grep "NOME_DO_SERVICO.1" | cut -f1) sh
# Listar containers com formato personalizado
docker ps --format "table {{.ID}} {{.Names}} {{.Status}} {{.Ports}}"'
# Build com tag
docker build -t minha-app:1.0 .
# Run com porta e variáveis de ambiente
docker run -p 3000:3000 -e NODE_ENV=production minha-app:1.0
# Modo detached (background)
docker run -d --name api minha-app:1.0
# Ver logs
docker logs -f api
# Shell interativo
docker exec -it api sh
# Docker Compose
docker compose up -d # inicia em background
docker compose down --volumes # para e remove volumes
docker compose logs -f api # logs do serviço api
docker compose exec db psql -U user mydb # acessa banco
# Limpeza
docker system prune -af # remove tudo não usado
docker volume prune # remove volumes órfãos💡 Dica
.dockerignore para excluir node_modules, .git, .env e arquivos de desenvolvimento do contexto de build. Imagens menores = deploys mais rápidos.node_modules
.git
.gitignore
*.md
.env*
.next
dist
coverage
*.logtailwind.config.ts
A configuração do Tailwind define design tokens reutilizáveis, cores, fontes, espaçamentos e breakpoints, que mantêm o design consistente em todo o projeto.
import type { Config } from "tailwindcss";
const config: Config = {
// Paths para o Tailwind escanear e gerar apenas as classes usadas
content: [
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
],
// darkMode: "class" ativa dark mode via classe .dark no <html>
darkMode: "class",
theme: {
// Sobrescreve completamente (use para projetos sem defaults do Tailwind)
// container: { center: true, padding: "1rem" },
extend: {
// ===== CORES SEMÂNTICAS =====
colors: {
// Cores base do sistema
base: "#020617", // fundo principal
surface: {
DEFAULT: "#0f172a", // superfície
elevated: "#1e293b", // superfície elevada
card: "#162032", // card
},
border: {
DEFAULT: "#1e293b", // borda padrão
subtle: "#334155", // borda sutil
},
text: {
DEFAULT: "#f1f5f9", // texto principal
muted: "#94a3b8", // texto secundário
dim: "#64748b", // texto terciário
},
accent: {
DEFAULT: "#38bdf8", // cor de destaque
hover: "#0ea5e9",
muted: "#0c4a6e", // destaque com baixa saturação
},
// Brand customizado
brand: {
50: "#f0f9ff",
100: "#e0f2fe",
500: "#0ea5e9",
600: "#0284c7",
900: "#0c4a6e",
},
},
// ===== FONTES =====
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
mono: ['"JetBrains Mono"', '"Fira Code"', "ui-monospace", "monospace"],
serif: ["Georgia", "serif"],
},
// ===== FONT SIZES CUSTOMIZADOS =====
fontSize: {
"2xs": ["0.625rem", { lineHeight: "0.875rem" }],
},
// ===== ESPAÇAMENTOS EXTRA =====
spacing: {
"18": "4.5rem",
"88": "22rem",
"128": "32rem",
},
// ===== BORDER RADIUS =====
borderRadius: {
"4xl": "2rem",
},
// ===== ANIMAÇÕES CUSTOMIZADAS =====
keyframes: {
"fade-in": {
from: { opacity: "0", transform: "translateY(8px)" },
to: { opacity: "1", transform: "translateY(0)" },
},
"pulse-once": {
"0%, 100%": { opacity: "1" },
"50%": { opacity: "0.5" },
},
},
animation: {
"fade-in": "fade-in 0.3s ease-out",
"pulse-once": "pulse-once 1s ease-in-out 1",
},
},
},
plugins: [
// require("@tailwindcss/typography"), // prose classes
// require("@tailwindcss/forms"), // form reset styles
// require("@tailwindcss/aspect-ratio"),
],
};
export default config;Design Tokens
Design tokens são variáveis nomeadas que representam decisões de design, cores, tipografia, espaçamento. Em Tailwind, você os define no theme.extend e usa como classes utilitárias.
// Tokens de cor usados como classes Tailwind
function TokenExample() {
return (
<div className="bg-base"> {/* #020617 */}
<div className="bg-surface"> {/* #0f172a */}
<div className="bg-surface-elevated"> {/* #1e293b */}
<p className="text-text-DEFAULT"> {/* #f1f5f9 */}
Texto principal
</p>
<p className="text-text-muted"> {/* #94a3b8 */}
Texto secundário
</p>
<p className="text-accent"> {/* #38bdf8 */}
Destaque
</p>
<div className="border border-border"> {/* #1e293b */}
Borda padrão
</div>
</div>
</div>
</div>
);
}
// Botão com tokens
function Button({ children }: { children: React.ReactNode }) {
return (
<button className="
bg-accent hover:bg-accent-hover
text-base font-semibold
px-4 py-2 rounded-lg
transition-colors
focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2
focus-visible:ring-offset-surface
">
{children}
</button>
);
}#020617
#0f172a
#1e293b
#334155
#38bdf8
#f1f5f9
#94a3b8
#4ade80
@layer base, components, utilities
As diretivas @layer controlam a ordem de cascata e permitem adicionar estilos customizados sem perder a possibilidade de sobrescrever com utilidades.
@tailwind base;
@tailwind components;
@tailwind utilities;
/* @layer base : estilos globais de reset e defaults */
@layer base {
:root {
--font-mono: "JetBrains Mono", monospace;
color-scheme: dark;
}
html { scroll-behavior: smooth; }
body {
@apply bg-base text-text font-sans antialiased;
}
/* Typography global */
h1 { @apply text-3xl font-bold tracking-tight; }
h2 { @apply text-2xl font-semibold; }
/* Focus ring global */
:focus-visible {
@apply outline-none ring-2 ring-accent ring-offset-2 ring-offset-base;
}
::selection {
@apply bg-accent-muted text-sky-100;
}
}
/* @layer components : componentes reutilizáveis */
@layer components {
.btn-primary {
@apply bg-accent hover:bg-accent-hover text-base
font-medium px-4 py-2 rounded-lg transition-colors
focus-visible:ring-2 focus-visible:ring-accent;
}
.card {
@apply bg-surface-card border border-border rounded-lg p-4
hover:border-border-subtle transition-colors;
}
.input {
@apply w-full bg-surface border border-border rounded-lg
px-3 py-2 text-sm text-text placeholder:text-text-dim
focus-visible:ring-2 focus-visible:ring-accent
focus-visible:border-transparent;
}
}
/* @layer utilities : utilidades customizadas */
@layer utilities {
.text-balance { text-wrap: balance; }
.scrollbar-thin::-webkit-scrollbar { width: 4px; height: 4px; }
.scrollbar-thin::-webkit-scrollbar-track { @apply bg-surface; }
.scrollbar-thin::-webkit-scrollbar-thumb { @apply bg-border rounded; }
}Responsividade
Tailwind usa breakpoints mobile-first. As classes sem prefixo se aplicam a todos os tamanhos; prefixos como sm: se aplicam a esse tamanho e acima.
| Prefixo | Min-width | Uso comum |
|---|---|---|
| — (nenhum) | 0px | mobile |
sm: | 640px | tablet pequeno |
md: | 768px | tablet |
lg: | 1024px | desktop |
xl: | 1280px | desktop largo |
2xl: | 1536px | ultrawide |
// Grid responsivo
<div className="
grid
grid-cols-1 // mobile: 1 coluna
sm:grid-cols-2 // sm+: 2 colunas
lg:grid-cols-3 // lg+: 3 colunas
xl:grid-cols-4 // xl+: 4 colunas
gap-4
">
// Tipografia fluida com clamp (sem breakpoints)
<h1 className="text-[clamp(1.75rem,4vw,3rem)] font-bold">
// Visibilidade por breakpoint
<nav className="hidden lg:flex"> // esconde no mobile
<button className="lg:hidden"> // mostra só no mobile
// Padding responsivo
<div className="px-4 sm:px-6 md:px-8 lg:px-12">
// Flex → Grid em desktop
<div className="
flex flex-col gap-4
lg:grid lg:grid-cols-[300px_1fr] lg:gap-8
">
<aside>Sidebar</aside>
<main>Conteúdo</main>
</div>Dark Mode
// tailwind.config.ts
const config = {
darkMode: "class", // ativa via classe .dark no <html>
// ou "media" para respeitar prefers-color-scheme do sistema
};
// Uso de dark: nas classes
<div className="bg-white dark:bg-slate-900">
<p className="text-slate-900 dark:text-slate-100">Texto</p>
<div className="border border-slate-200 dark:border-slate-800">
<span className="text-blue-600 dark:text-sky-400">Link</span>
</div>
</div>
// Toggle de tema (Client Component)
"use client";
import { useEffect, useState } from "react";
export function ThemeToggle() {
const [dark, setDark] = useState(true);
useEffect(() => {
document.documentElement.classList.toggle("dark", dark);
}, [dark]);
return (
<button onClick={() => setDark((d) => !d)} aria-label="Alternar tema">
{dark ? "🌙" : "☀️"}
</button>
);
}Git : comandos e boas práticas
Conventional Commits
Formato: type(scope): description
feat:nova funcionalidadefix:correção de bugrefactor:refatoração sem mudança de comportamentochore:tarefas de manutençãodocs:documentaçãotest:testesperf:melhoria de performance
# Branch por feature
git checkout -b feat/user-auth
# Commit convencional
git commit -m "feat(auth): add JWT refresh token rotation"
# Rebase interativo (ajustar histórico antes do PR)
git rebase -i origin/main
# Stash com nome
git stash push -m "wip: form validation"
git stash list
git stash pop
# Log visual
git log --oneline --graph --all --decorate
# Desfazer último commit (preserva mudanças)
git reset --soft HEAD~1
# Cherry-pick de commit específico
git cherry-pick abc1234
# Comparar branch com main
git diff main...HEAD
# Blame para contexto de mudança
git log -p --follow -S "functionName" -- src/auth.ts[alias]
lg = log --oneline --graph --all --decorate
st = status -sb
co = checkout
br = branch
undo = reset --soft HEAD~1
aliases = config --get-regexp alias