How it fits together
For whoever is running the desk, and anybody deciding whether to.
One Laravel application, one database, one server. Everything below is part of that application unless it says otherwise.
The pieces
┌──────────────────────────────────────────┐ agents ─────────► │ Staff web app (Vue) │ │ ────────────────────────────────────── │ clients ────────► │ Integration API ← platform module │ (through their │ Chat widget + site snippet │ billing portal) │ Public status feed / report intake │ └───────────────┬──────────────────────────┘ │ Laravel (PHP) ┌─────────┴─────────┐ │ │ ┌─────▼─────┐ ┌──────▼──────┐ │ MySQL / │ │ Queue │ emails, AI, campaigns, │ MariaDB │ │ workers │ knowledge, webhooks └───────────┘ └──────┬──────┘ │ ┌───────────┐ ┌──────▼──────┐ │ storage/ │ │ Scheduler │ mail polling, holds, │ (files) │ │ (cron) │ closures, pruning └───────────┘ └─────────────┘ ┌─────────────────────────────────┐ │ Reverb (websockets) optional │ └─────────────────────────────────┘- The staff web app is a single-page Vue application talking to the same API everything else uses.
- The queue workers do everything slow or outward-facing. No worker, no email.
- The scheduler is one cron entry a minute that triggers everything periodic.
- Reverb pushes live updates. Optional; without it the app polls.
- Files (attachments, inbound originals, repository mirrors) are plain files under
storage/app.
How people reach it
| Who | How |
|---|---|
| Agents and administrators | The web app, signed in with a password plus optional two-factor or a passkey |
| Clients with an account | Their billing portal, through a module that calls the integration API |
| Clients without one | A guest ticket and an emailed link, or by writing to a mailbox the desk reads |
| Anybody on your website | The chat widget, the announcement bar, the status embed |
| Bug and security reporters | The public report form |
| Scripts and assistants | An automation key scoped to one project |
Brands are the boundary
Everything in the desk belongs to a brand: departments, clients, tickets, tags, canned responses, knowledge, rules, mailboxes, chat settings, AI configuration, projects. One install can run any number of companies without them seeing each other.
Staff belong to brands and to departments within them, and that membership is enforced in the policies that answer every request, not in the screens. An agent who is not in a brand cannot see its tickets through the list, through search, through the API, or through an AI answer.
Read Brands next; it is the concept the rest of the desk hangs off.
What can be switched off
Most of the desk is optional, and a small install can ignore most of this documentation:
| Feature | Off means |
|---|---|
| Live chat | No widget, no visitor tracking; tickets and email work as normal |
| Inbound email | Clients reach you through the portal or the widget only |
| AI | No drafts, summaries, triage or console; nothing is sent to any provider |
| Knowledge base | No reference answers; canned responses still work |
| Issue tracker | No projects, boards, releases or repositories |
| Reports | No public bug or security intake |
| Status page | No components, incidents or subscribers |
| Mass mail | No campaigns |
| Platform connection | Clients are guests, or records you make yourself |
Nothing here is a licence tier; they are switches, and an unused feature costs nothing but the rows it does not have.
The data, in one paragraph
Tickets belong to a department, which belongs to a brand. A ticket is opened by a client (an account, or a guest sender) and carries replies, notes, attachments and activity. Tickets can be linked to issues, which live in projects, which belong to a brand and may be restricted to named members. Reports from the public land as issues too. Everything anybody did is in the audit log, kept for as long as you configure. Files never live in the database; the database holds the row that names the file.