Introduction
In many Directus projects, you might find yourself needing to customize the default system collections such as directus_users
, directus_roles
, directus_files
, or other core collections. While creating separate collections might seem like a solution, it's often more practical to extend the existing system collections. However, this presents a challenge: the default fields can't be easily rearranged or hidden through the standard interface.
This guide will show you how to:
- Customize the default `directus_users` collection fields
- Organize fields using the Group Tabs interface
- Hide unnecessary fields
- Improve the overall user experience
Understanding Directus System Collections
Directus system collections (like directus_users
, directus_roles
, directus_files
, etc.) are defined in the Directus source code. The field configurations for these collections are stored in YAML files within the Directus repository. For example, the users collection configuration can be found in the Directus GitHub repository.
The techniques described in this guide can be applied to any Directus system collection, not just the users collection. This means you can customize the appearance and behavior of fields in collections like:
directus_roles
directus_files
directus_folders
directus_permissions
- And other system collections
Prerequisites
- Directus instance with admin access
- Group Tabs Interface Extension installed
- API tool like Postman or similar for making the PATCH requests
⚠️ Important Disclaimers
Before we dive into the customization process, please note the following important points:
- Use at your own risk: This customization involves modifying system fields which may affect core functionality.
- Test First: Always test these changes on a non-production instance before applying them to your live environment.
- Backup Regularly: Before applying these or any significant system modifications, always ensure you have a complete backup of your Directus instance (database and files).
- Known Issues:
- The
policies
field appears visually duplicated in the interface and cannot be properly arranged (solution: hide it) - though it functions correctly - Three fields are not being properly translated:
tfa_secret
- Dark Theme Overrides (shows as 'Overrides' instead of 'Customization')
- Light Theme Overrides (shows as 'Overrides' instead of 'Customization')
- Dividers that need to be hidden:
- Preferences divider
- Theme divider
- Admin divider
- A persistent horizontal rule (hr) element may still appear, but can be partially hidden using the appearance tab with a single CSS line
- The
Step 1: Understanding the Current Structure
The default Directus users collection comes with several predefined fields that are essential for the system's functionality. These include:
- Basic information (id, first_name, last_name, email)
- Authentication (password, token)
- Preferences (language, appearance)
- Administrative fields (role, status)
Step 2: Understanding How to Modify System Fields
When you create new fields in Directus, the system automatically creates corresponding entries in the directus_fields
collection. However, system fields (like those in directus_users
) don't have these entries by default, which is why you can't modify them through the standard interface.
To make system fields editable, we need to create corresponding entries in the directus_fields
collection and use the PATCH endpoint to update their configurations.
Step 3: Making the API Request
The field configurations we'll use are based on the original definitions from the Directus source code, specifically from the users.yaml file.
Show cURL Request & JSON Configuration
curl -X PATCH 'https://your-directus-instance/fields/directus_users' \
-H 'Authorization: Bearer YOUR-TOKEN' \
-H 'Content-Type: application/json' \
-d '[
{
"field": "id",
"meta": {
"special": ["uuid"],
"interface": "input",
"options": {
"iconRight": "vpn_key"
}
}
},
{
"field": "first_name",
"meta": {
"interface": "input",
"options": {
"iconRight": "account_circle"
},
"width": "half"
}
},
{
"field": "last_name",
"meta": {
"interface": "input",
"options": {
"iconRight": "account_circle"
},
"width": "half"
}
},
{
"field": "email",
"meta": {
"interface": "input",
"options": {
"iconRight": "account_circle"
},
"width": "half"
}
},
{
"field": "password",
"meta": {
"special": ["hash", "conceal"],
"interface": "input-hash",
"options": {
"iconRight": "lock",
"masked": true
},
"width": "half"
}
},
{
"field": "avatar",
"meta": {
"interface": "file",
"display": "image"
}
},
{
"field": "location",
"meta": {
"interface": "input",
"options": {
"iconRight": "place"
},
"width": "half"
}
},
{
"field": "title",
"meta": {
"interface": "input",
"options": {
"iconRight": "work"
},
"width": "half"
}
},
{
"field": "description",
"meta": {
"interface": "input-multiline"
}
},
{
"field": "tags",
"meta": {
"interface": "tags",
"special": ["cast-json"],
"options": {
"iconRight": "local_offer"
},
"display": "labels",
"display_options": {
"choices": null,
"format": false
}
}
},
{
"field": "preferences_divider",
"meta": {
"interface": "presentation-divider",
"options": {
"icon": "face",
"title": "$t:fields.directus_users.user_preferences"
},
"special": ["alias", "no-data"],
"hidden": true
}
},
{
"field": "language",
"meta": {
"interface": "system-language",
"width": "half",
"options": {
"includeProjectDefault": true
}
}
},
{
"field": "tfa_secret",
"meta": {
"interface": "system-mfa-setup",
"special": ["conceal"],
"width": "half"
}
},
{
"field": "email_notifications",
"meta": {
"interface": "boolean",
"width": "half",
"special": ["cast-boolean"]
}
},
{
"field": "theming_divider",
"meta": {
"interface": "presentation-divider",
"options": {
"icon": "palette",
"title": "$t:theme"
},
"special": ["alias", "no-data"],
"hidden": true
}
},
{
"field": "appearance",
"meta": {
"interface": "select-dropdown",
"options": {
"choices": [
{
"value": null,
"text": "$t:default_sync_with_project"
},
{
"value": "auto",
"text": "$t:appearance_auto"
},
{
"value": "light",
"text": "$t:appearance_light"
},
{
"value": "dark",
"text": "$t:appearance_dark"
}
]
},
"width": "half"
}
},
{
"field": "theme_light",
"meta": {
"interface": "system-theme",
"options": {
"appearance": "light",
"includeNull": true
}
}
},
{
"field": "theme_light_overrides",
"meta": {
"interface": "system-theme-overrides",
"options": {
"appearance": "light"
},
"special": ["cast-json"]
}
},
{
"field": "theme_dark",
"meta": {
"interface": "system-theme",
"options": {
"appearance": "dark",
"includeNull": true
}
}
},
{
"field": "theme_dark_overrides",
"meta": {
"interface": "system-theme-overrides",
"options": {
"appearance": "dark"
},
"special": ["cast-json"]
}
},
{
"field": "admin_divider",
"meta": {
"interface": "presentation-divider",
"options": {
"icon": "verified_user",
"title": "$t:fields.directus_users.admin_options",
"color": "var(--theme--danger)"
},
"special": ["alias", "no-data"],
"hidden": true
}
},
{
"field": "status",
"meta": {
"interface": "select-dropdown",
"options": {
"choices": [
{
"text": "$t:fields.directus_users.status_draft",
"value": "draft"
},
{
"text": "$t:fields.directus_users.status_invited",
"value": "invited"
},
{
"text": "$t:fields.directus_users.status_unverified",
"value": "unverified"
},
{
"text": "$t:fields.directus_users.status_active",
"value": "active"
},
{
"text": "$t:fields.directus_users.status_suspended",
"value": "suspended"
},
{
"text": "$t:fields.directus_users.status_archived",
"value": "archived"
}
]
},
"width": "half"
}
},
{
"field": "role",
"meta": {
"interface": "select-dropdown-m2o",
"options": {
"template": "{{ name }}"
},
"special": ["m2o"],
"width": "half",
"display": "related-values",
"display_options": {
"template": "{{ name }}"
}
}
},
{
"field": "policies",
"meta": {
"interface": "list-m2m",
"options": {
"layout": "list"
},
"display": "related-values",
"special": ["m2m"],
"hidden": true
}
},
{
"field": "token",
"meta": {
"interface": "system-token",
"special": ["conceal"]
}
},
{
"field": "last_page",
"meta": {
"width": "half"
}
},
{
"field": "last_access",
"meta": {
"width": "half",
"display": "datetime",
"readonly": true,
"display_options": {
"relative": true
}
}
},
{
"field": "provider",
"meta": {
"width": "half",
"interface": "select-dropdown",
"options": {
"choices": [
{
"text": "$t:default_provider",
"value": "default"
}
]
}
}
},
{
"field": "external_identifier",
"meta": {
"width": "half",
"options": {
"iconRight": "account_circle"
},
"interface": "input"
}
},
{
"field": "auth_data",
"meta": {
"hidden": true
}
}
]'
Notice the Key Customizations:
Hidden Fields:
- Set
hidden: true
for dividers and unnecessary fields - Special handling for the
policies
field - Temporarily hidden fields until better solutions are available:
preferences_divider
theming_divider
admin_divider
policies
field (due to visual duplication)
Step 4: Adding the Group Tabs Interface Extension
The Group Tabs interface helps organize fields into logical sections. Here's a suggestion how to structure your user profile:
Create a new group tab field and name it tab_group
with the interface group-tabs
. Inside this group, add the following group-detail
fields to organize your user profile into logical sections:
Tab Structure Configuration:
- 📋 Basic Information Tab (
basic_info_group
):- Avatar
- First name
- Last name
- Title
- Location
- Description
- Tags
- ⚙️ Preferences Tab (
preferences_group
):- Language
- Email notifications
- Theme preference (dark/light mode)
- 🔒 Security (
security_group
):- Password
- Two-Factor Authentication
- Account status
- Role
- Token
- Provider
- External identifier
- Authentication data (hidden)
width: "half"
for related fields that should appear side-by-sidewidth: "full"
for description fields and primary identifiers- Add appropriate icons using
iconRight
oriconLeft
options
Step 5: Handling Visual Issues
To address the persistent horizontal rule issue that may appear despite hiding dividers, you can add custom CSS to your Directus appearance settings. This solution targets specific divider elements that cause visual artifacts:
/* Hide the specific divider - replace PRIMARY_KEY with your divider's primary key */
.field.full.first-visible-field:has(div[field="$system_divider"][primary-key="PRIMARY_KEY"]) {
display: none !important;
}
Important: Make sure to replace PRIMARY_KEY
with the actual primary key of your divider. You can find this in the browser's developer tools by inspecting the divider element.
Extending to Other Collections
The same approach can be used to customize other Directus system collections. Here's how:
- Identify the Collection: Determine which system collection you want to customize
- Find the Source: Locate the corresponding YAML file in the Directus repository
- Analyze Fields: Review the field definitions and their current configurations
- Plan Changes: Decide which fields to modify, hide, or rearrange
- Apply Customizations: Use the PATCH endpoint for that collection (e.g.,
/fields/directus_roles
for roles)
The core principle remains the same: identify the fields from the collection's YAML definition in the Directus repository, then craft a JSON payload similar to the one for directus_users
to define their appearance and behavior in the directus_fields
collection.
Conclusion
Customizing the default Directus fields can significantly improve the user experience and make the system more suitable for your specific needs. While there are some limitations and known issues, the benefits of having a well-organized user interface often outweigh these challenges.
Note: This guide is based on Directus version 10 and 11. Some features and behaviors might vary in different versions.