This project is V-Mail. V-Mail is a self-hosted, web-based email client designed for personal use. It uses the layout and keyboard shortcuts of Gmail to make it immediately familiar for ex-Gmail users. It connects to an IMAP server and provides the web UI to read and send email.
Compared to Gmail, this project does not include:
- Client-side email filters. The user should set these up on the server, typically via Sieve.
- A visual query builder for the search box. A simple text field is fine.
- A multi-language UI. The UI is English-only.
- 95% of Gmail's settings. V-Mail has some basic settings like emails per page and undo send delay, but that's it.
- Automatic categorization such as primary/social/promotions.
- The ability to collapse the left sidebar.
- Signature management.
- Smiley/emoji reactions to emails. This is Google's proprietary thing.
V-Mail uses a Postgres database, a Go back end, a REST API, and a React front end with TypeScript. V-Mail needs a separate, self-hosted Authelia instance for authentication.
Always follow this process when developing in this project:
- Before developing a feature, make sure to do the planning and know exactly what you want to achieve and have a task list.
- Before touching code of a specific domain, read the related docs within
/docsor similar. List folders if you need to. Example:docs/backend/auth.mdfor auth logic,backend/migrations/*.sqlfor DB schema. - Do the changes, in small iterations. Adhere to the style guide!
- Use
./scripts/check.shto check that everything is still working.- Or use a subset, for example, if you only touch the front end or tests. See the script's readme
- Even fix gocyclo's cyclomatic complexity warnings! I know it's a pain, but it's helpful to keep Go funcs simple.
- Make sure to add tests for the new code. Think about unit tests, integration tests, and end-to-end tests.
- Check if you added new patterns, external dependencies, or architectural changes. Update all related docs.
- Also consider updating
AGENTS.md(incl. this very process) to keep the next agent's work streamlined. - Before you call it done, see the diff of your changes (
git diff) and make sure all changes are actually needed. Revert unneeded changes. - Rerun
./scripts/check.shto make sure everything still works. - Suggest a commit message, in the format seen in the style guide.
Always keep the dev process and style guide in mind.
- Frontend: React 19 + Vite. Entry:
frontend/src/main.tsx. State: Zustand. - Backend: Go 1.25 (Standard lib HTTP). Entry:
backend/cmd/server. - Architecture: Handlers (
api/) -> Service/core logic (internal/) -> DB (db/). - Testing: Playwright (E2E), Vitest (unit), Go
testingpackage,testifyfor assertions and mocking support,mockeryfor generating mocks.
- Tool versions: We use mise. Go, Node, pnpm, etc. are in
mise.toml.mise installinstalls. scripts/check.shis the primary quality control tool. It runs linting, formatting, and back/front end+E2E tests../scripts/check.sh --frontend,./scripts/check.sh --backendare options, and so is./scripts/check.sh --check <check-name>(use./scripts/check.sh --helpto list them).- Front end:
pnpm lint,pnpm lint:fix,pnpm format,pnpm test, andpnpm test:e2e. - `pnpm exec playwright test --config=../playwright.config.ts --grep "{test-name}" is also helpful for context-efficient re-running of E2E-tests.
migrate up(using golang-migrate)- For recurring updates of tools, dependencies, and infra, see
docs/maintenance.md.
- Always make check.sh happy, including warnings and gocyclo complexity!
- Modular architecture, no global state, no package cycles.
- Sentence case titles and labels
- If you add a new tool, script, or architectural pattern, you MUST update this file (
AGENTS.md) and any relevant docs before finishing your response.
- Commits: First line max 50 chars. Blank line. Detailed description, usually as concise bullets.
- Writing: Friendly, active voice, and ALWAYS sentence case titles and labels!
- Complexity: Max cyclomatic complexity of 15 per function. (checked by gocyclo)
- No classes: Use modules and functional components only.
- Strict types:
no-explicit-anyis enforced. - Imports: Organized by groups (builtin, external, internal, parent, sibling, index).
- Formatting: Prettier is the authority.
- React: Hooks rules enforced, no dangerous HTML.
- Comments: Meaningful comments for public functions/types.
- DB: Plural table names, singular columns. Add comments in SQL and Go structs.