pnpm lint # ESLint, including jsx-a11y
pnpm typecheck # tsc --noEmit
pnpm test # Vitest
pnpm test:coverage # Vitest with thresholds
pnpm format:check # Prettier
pnpm build # Next static export
pnpm security:audit
pnpm check runs lint, typecheck, tests and build in sequence.
.github/workflows/ci.yml is a reusable workflow with three gating jobs:
src/content/content.json, so content that breaks a schema rule fails here..github/workflows/pages.yml calls the whole workflow as a prerequisite of build, so any
failing gate stops the deploy rather than being reported afterwards.
The dependency audit is a gating job. It checks the public site, the panel UI’s separate lockfile, and the pinned Python requirements; a moderate-or-higher advisory blocks deployment.
Site. Coverage is scoped to src/content and src/lib — the pure logic and the content
contracts — with 80% thresholds. There are still no component or end-to-end tests: rendering
is not covered, and the build failing on a type or schema error is what catches most breakage.
Stating this plainly because an untested claim is worse than an absent one.
Control panel. admin/content/tests.py covers the API: who can read what, that a wrong
password and an unknown user are indistinguishable, that nested writes replace child collections
in one transaction and leave existing rows untouched when validation rejects, that the export
excludes drafts and matches the shape the site parses, and that the project list stays ordered by
position. That last test exists because the ordering regressed once and returned 200 while
doing nothing visible.
Panel UI. Type checked and built in CI; no component tests.
The content tests are the interesting ones. Beyond slug uniqueness and safe external links,
src/content/content.test.ts enforces the editorial rules of the site:
TODO, lorem ipsum, seu-usuario, seudominio) can reach a page.That last one exists because this repository previously shipped placeholder GitHub links and a placeholder email address to production.
FilterableProjectGrid and ThemeToggle, the only two pieces of real
client-side state."use client" only for the theme, reveal animation, pressable
card, filter grid and contact form.currentColor — no diagram library, no extra
request, and they follow the theme toggle exactly.transform and opacity, and every animation respects
prefers-reduced-motion.