Skip to content

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.

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.

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.

TagColor
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.

src/mods/signup/services/seed_organization_default_tags_service.rs
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.

All endpoints require an authenticated session.

MethodRouteDescription
GET/api/contact-tagsList all org tags (alphabetical)
POST/api/contact-tagsCreate 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.

MethodRouteDescription
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.

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.

  • Contact — parent module overview