Bug reports, feature requests, documentation, translations, and code are all welcome. This guide covers the conventions shared across every Bulwark repository; individual repos may add their own notes.
By participating in this project, you agree to abide by our Code of Conduct. Please read it before contributing.
Before opening a bug report:
- Check the existing issues to avoid duplicates
- Make sure you are reproducing the issue on the latest version
When filing a bug report, please include:
- A clear and descriptive title
- Steps to reproduce the issue
- Expected vs. actual behavior
- Screenshots or screen recordings if relevant
- Your environment (OS, browser, Bulwark version, Stalwart version)
- Open a feature request issue with a detailed description
- Explain the problem you're solving and why this feature would be valuable
- Include mockups or examples if helpful
- Fork the repository on GitHub
- Clone your fork locally
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes following the code style guidelines below
- Run checks:
npm run typecheck && npm run lint && npx vitest run - Commit using the conventional commits format
- Push to your fork and open a Pull Request
git clone https://github.com/your-username/webmail.git
cd webmail
npm install
cp .env.dev.example .env.local
npm run devThe .env.dev.example enables the built-in mock JMAP server so you can develop without an external mail server.
Code quality commands:
npm run typecheck # TypeScript type checking
npm run lint # ESLint
npm run lint:fix # Auto-fix lint issues
npm run build # Production build
npx vitest run # Unit tests
npm run test:translations # Locale files vs. English
npm run test:integration # Playwright against Stalwart in DockerThese checks run automatically on commit via Husky pre-commit hooks.
- Use TypeScript throughout: define proper types and avoid
any - Use Tailwind CSS for styling, avoiding custom CSS where possible
- Follow existing code patterns and folder structure
- Use
"use client"directive only when necessary - Reusable UI primitives go in
components/ui/ - Custom hooks go in
hooks/ - State management uses Zustand stores in
stores/
Bulwark ships 24 languages, three of them right-to-left. When adding user-facing text:
- Never hardcode strings. Always use translations via
next-intl:const t = useTranslations("namespace"); return <div>{t("key")}</div>;
- Translation files live in
/locales/{lang}/common.json - Add new keys to English (
en) first. It's the source of truth; missing keys in other locales fall back to it, so translations can follow in the same PR or a later one. - Run
npm run test:translationsto check the locale files for drift against English
Follow Conventional Commits:
| Prefix | Purpose |
|---|---|
feat: |
New features |
fix: |
Bug fixes |
docs: |
Documentation changes |
style: |
Code style / formatting |
refactor: |
Code refactoring |
test: |
Adding or updating tests |
chore: |
Maintenance tasks |
Examples:
feat: add email threading support
fix: resolve attachment download issue on mobile
docs: update keyboard shortcuts guide
chore: upgrade next.js to 16.2
- Keep PRs focused on a single change
- Write a clear description of what changed and why
- Include screenshots or videos for UI changes
- Reference related issues with
Closes #123orFixes #123 - Update translations if your change adds or modifies user-facing text
- Ensure the build and type checks pass before requesting review
If you have questions about contributing, feel free to open a discussion or reach out through GitHub issues.