Skip to content

Contributing

José Carrillo edited this page Jun 13, 2026 · 2 revisions

Contributing

Contributions are welcome. This page covers local setup, conventions, and the rules that keep Zefer consistent and secure. See also the repository's docs/CONTRIBUTING.md, CLAUDE.md, and AGENTS.md.

Local setup

git clone https://github.com/carrilloapps/zefer.git
cd zefer
npm install
npm run dev          # http://localhost:3000
npm test             # 161 Vitest tests (must pass before any commit)
npm run build        # production build

Node.js 20+ is recommended.

Core rules

  1. Never hardcode colors. Use theme-* classes or var(--*) CSS variables. Zero Tailwind color classes in components.
  2. All user-facing text lives in app/lib/i18n.ts with translations in es, en, pt. Never hardcode strings.
  3. Security metadata stays inside the encrypted payload. The public header may only contain iterations, compression, hint, note, mode. Everything else (expiration, IPs, secret question, max attempts) goes inside the AES-256-GCM ciphertext.
  4. Minimum passphrase: 6 characters, enforced in the encrypt form.
  5. WCAG 2.1 AA — all text must pass a 4.5:1 contrast ratio; test both themes.
  6. No emails exposed — contact is the GitHub profile only.
  7. SSR hydration-safe — providers start with defaults and hydrate from localStorage in useEffect; pages must server-render real content.

Conventions

  • Components are "use client" with PascalCase filenames.
  • Icon-only buttons: minimum 36×36px (w-9 h-9) with a dynamic aria-label.
  • Strict heading hierarchy (h1 → h2 → h3); footers use <p>, not headings.
  • Internal navigation uses Next.js <Link> (prefetched, no full reloads); external links and static files (/llms.txt) use <a>.
  • Layout widths: max-w-2xl for hero/subtitle, max-w-3xl for content. Never max-w-4xl+.
  • All animations respect prefers-reduced-motion.
  • Every page.tsx exports metadata built via app/lib/seo.ts (pageMetadata()).

Adding a new encrypt/decrypt option

Each new option needs a long + short URL alias wired in both EncryptForm and DecryptForm, the field UI, i18n keys (es/en/pt), and — if it is security metadata — storage inside the encrypted payload (never the public header).

Releasing a version

When cutting a release, update all of these together:

  1. CHANGELOG.md — new version entry
  2. package.jsonversion
  3. app/layout.tsxsoftwareVersion in the JSON-LD
  4. app/opengraph-image.tsx — version badge
  5. app/twitter-image.tsx — version badge
  6. app/sitemap.tslastModified

Testing

npm test must pass (161 tests, 100% line coverage; the password/crypto engines are coverage-gated). Add tests alongside new crypto, format, or password logic.

Reporting security issues

Please follow responsible disclosure — see the Security Policy and the /security page rather than opening a public issue for vulnerabilities.


📖 Glossary — terms on this page: public header · AES-256-GCM · IV · PBKDF2. Full list in the Glossary.

Clone this wiki locally