Zammad Helpdesk Development Guide
AI coding assistant for the Zammad open-source helpdesk/customer support platform.
What This Skill Does
Provides you with a comprehensive mental model of the Zammad codebase to ship changes efficiently. Zammad is a Ruby on Rails application with two modern Vue 3 frontends (desktop-view and mobile) and one legacy desktop-app.
Instructions
1. Understand the Architecture
Zammad consists of three main frontend applications:
**Legacy desktop-app** (`app/assets/`): CoffeeScript/Sprockets, Spine.js MVC, REST API**Desktop-view** (`app/frontend/apps/desktop`): Vue 3 + TypeScript + GraphQL**Mobile** (`app/frontend/apps/mobile`): Vue 3 + TypeScript + GraphQL2. Locate Authoritative Documentation
Before making changes, always consult:
Developer Manual: `doc/developer_manual/` (index at `doc/developer_manual/index.md`)Configuration files: `package.json`, `Gemfile`, `config/database.yml`, `Procfile.dev`, `vite.config.mjs`, `tsconfig.base.json`, `eslint.config.ts`, `.oxlintrc.json`3. Navigate the Project Structure
**Frontend:**
`app/assets/`: Legacy desktop-app (CoffeeScript)`app/frontend/`: Vue + TypeScript frontends`app/frontend/apps/desktop`: Desktop-view app`app/frontend/apps/mobile`: Mobile app`app/frontend/shared/`: Shared components, utils, stores, GraphQL, i18n`app/frontend/tests/`: Vitest setup and test helpers**Backend (Rails standard):**
`app/controllers/`: Controllers`app/models/`: Models`app/views/`: Views`app/jobs/`: Background jobs`app/mailers/`: Mailers`app/channels/`: ActionCable channels`app/policies/`: Authorization policies`app/services/`: Business logic modules`app/graphql/`: GraphQL API definitions and resolvers**lib/ Directory:**
Contains core extensions, helpers, integrations, and business logic:
Helpers: `email_helper.rb`, `migration_helper.rb`, `sql_helper.rb`, etc.Integrations: `github/`, `gitlab/`, `microsoft_graph/`, `facebook.rb`, `telegram_helper.rb`, `whatsapp/`Features: `auto_wizard.rb`, `escalation/`, `knowledge_base/`, `password_policy/`, `secure_mailing/`Core extensions: `core_ext/`Background services: `background_services/`, `sequencer/`, `transaction_dispatcher.rb`**Other key folders:**
`bin/`: Executables`config/`: Configuration`db/`: Database migrations and seeds`spec/`: RSpec tests`test/`: QUnit tests for legacy app4. Tech Stack Reference
**Legacy desktop-app:**
CoffeeScript, Spine.js, Sprockets, REST APILinting: `coffeelint.json`Testing: QUnit in `test/`**Modern Vue apps (desktop-view and mobile):**
Vue 3, TypeScript, Pinia (state), Apollo Client (GraphQL)Tailwind CSS, VueUse, Vitest, Testing Library, CypressBuild: pnpm, vite-plugin-ruby, vite-plugin-pwaLinting: ESLint, Stylelint, Prettier**Backend:**
Ruby on Rails, PostgreSQL, RedisActionCable (WebSockets), Delayed Job (background jobs)GraphQL API5. Coding Guidelines
**For Legacy desktop-app:**
Location: `app/assets/javascripts` and `app/assets/stylesheets`Uses Spine.js MVC frameworkCommunicates via REST API endpointsPrefer minimal changes; move new features to desktop-view/mobile**For Vue apps:**
Use path aliases defined in `tsconfig.base.json`Do NOT cross-import between desktop/mobile apps (ESLint enforces boundaries)Write unit/component tests with Vitest and Testing LibraryStyle with Tailwind CSS utilitiesLint with Stylelint and PrettierWrap all user-facing strings for i18n (see `eslint.config.ts` for rules)**General:**
All runtime and environment constraints are in config filesConsult the Developer Manual for setup, testing, linting, and standardsKeep PRs focused and include tests for new code6. When Working on a Task
1. **Read relevant documentation** from `doc/developer_manual/` first
2. **Identify the correct layer:**
- Backend change? → Rails (controllers/models/services/graphql)
- Legacy UI? → `app/assets/` (minimize changes)
- Modern UI? → `app/frontend/apps/desktop` or `app/frontend/apps/mobile`
- Shared frontend logic? → `app/frontend/shared/`
3. **Check existing patterns** in similar files before implementing
4. **Write tests** appropriate to the layer (RSpec for backend, Vitest for Vue, QUnit for legacy)
5. **Verify linting** passes (ESLint, Stylelint, Prettier, coffeelint)
6. **Reference config files** for tool versions, scripts, and environment variables
7. When in Doubt
The Developer Manual (`doc/developer_manual/`) is the source of truthPrefer referencing config files over guessingFor path aliases, see `tsconfig.base.json`For copyright/i18n rules, see `eslint.config.ts`Examples
**Example 1: Adding a new GraphQL query for desktop-view**
1. Create resolver in `app/graphql/gql/resolvers/`
2. Define type/query in `app/graphql/gql/types/` or `app/graphql/gql/queries/`
3. Add query file in `app/frontend/apps/desktop/pages/.../graphql/queries/`
4. Write Vitest test in corresponding `__tests__/` directory
5. Use Apollo Client to fetch in Vue component
**Example 2: Fixing a bug in legacy desktop-app**
1. Locate the Spine.js controller/view in `app/assets/javascripts/app/`
2. Make minimal CoffeeScript changes
3. Add QUnit test in `test/`
4. Verify with coffeelint
**Example 3: Creating a shared component**
1. Add component to `app/frontend/shared/components/`
2. Import using path alias (e.g., `#shared/components/...`)
3. Write Vitest + Testing Library test
4. Use in desktop-view or mobile app without cross-app imports
Constraints
Do not cross-import between desktop and mobile appsPrefer new development in modern Vue apps over legacy desktop-appAlways wrap user-facing strings for i18nInclude tests with all new codeFollow linting rules enforced by ESLint, Stylelint, Prettier, and coffeelint