Contact Tags
Contact tags are organisation-scoped labels that can be applied to any number of contacts. Each tag has a name (unique per org) and a hex color for visual identification.
Data Model
Section titled “Data Model”ContactTag
Section titled “ContactTag”pub struct ContactTag { pub id: Uuid, pub name: String, // Unique per organisation pub color: String, // Hex color code, e.g. "#3B82F6"}Tags are organisation-level entities — not per-contact. Creating a tag makes it available to all contacts in the org. Each contact can hold multiple tags, and each tag can be assigned to multiple contacts.
Default Tags
Section titled “Default Tags”Every new organisation starts with 10 pre-seeded tags. These are inserted during signup (both email/password and Google OAuth flows) before any other setup steps.
| Tag | Color |
|---|---|
| New Lead | #6366f1 (Indigo) |
| Hot Lead | #f97316 (Orange) |
| Existing Client | #22c55e (Green) |
| Follow-up Needed | #eab308 (Yellow) |
| Appointment Scheduled | #3b82f6 (Blue) |
| Complaint | #ef4444 (Red) |
| Urgent | #dc2626 (Dark Red) |
| VIP | #a855f7 (Purple) |
| Unqualified | #94a3b8 (Slate) |
| Do Not Contact | #1e293b (Dark Slate) |
The seeding service uses INSERT ... ON CONFLICT DO NOTHING on the (organization_id, name) unique constraint, making it idempotent. If seeding fails, the entire signup rolls back — both the user and organisation are deleted.
pub async fn seed_organization_default_tags( organization_id: Uuid, db: &DatabaseConnection,) -> Result<(), AppError>Orgs created before this feature have no default tags. There is no backfill migration — existing orgs can create tags manually.
API Endpoints
Section titled “API Endpoints”All endpoints require an authenticated session.
Organisation Tags
Section titled “Organisation Tags”| Method | Route | Description |
|---|---|---|
GET | /api/contact-tags | List all org tags (alphabetical) |
POST | /api/contact-tags | Create a tag (name, color) |
DELETE | /api/contact-tags/{id} | Delete a tag — cascades to all assignments |
Tag names must be unique per organisation. Deleting a tag removes all contact assignments via database cascade.
Contact Assignment
Section titled “Contact Assignment”| Method | Route | Description |
|---|---|---|
POST | /api/contacts/{contact_id}/tags/{tag_id} | Assign tag to contact (idempotent) |
DELETE | /api/contacts/{contact_id}/tags/{tag_id} | Unassign tag from contact |
Assignment and unassignment both verify that the contact and tag belong to the same organisation.
UI Components
Section titled “UI Components”ContactTagSelector — dropdown for assigning tags to a contact. Includes inline tag creation with a color picker. Filters the list as you type.
ContactTagBadge — colored pill displaying the tag name with its hex background color. Used inline in contact cards and the detail view.
Contact cards in the list view display up to 3 tags. If a contact has more, an overflow indicator (+N more) is shown. The contact detail view provides full tag management.
Related
Section titled “Related”- Contact — parent module overview