
Hi, I'm back with a boring, non-AI topic this week 🙂 Vocabularies are probably one of the most boring (but also one of the most used) features in Nuxeo. They're basically lists of predefined values, easy to use and integrate into any custom UI element. However, since everyone is "AI-powering" their Nuxeo lately, vocabularies have suddenly become a hot topic.
Think about a use case like this: every time you ingest content into Nuxeo, AI is classifying and extracting metadata from it (I promise, it is a REAL use case: pretty much every client we work with experiments with AI these days!). But most of the time, you don't want the AI to come up with random metadata, you want it to pick from a list of predefined values relevant to your business (context!).
That list is your Nuxeo vocabulary.
So, when you send context to AI along with the document, more context is better. For each entry in a vocabulary, you might want to add a short description to clarify when that specific value should be applied.
Let's say you have a vocabulary called ReportingStatement with the following values (Nuxeo default).
Now you'd like to add an extra description field to give the AI more context about each value (Nuxeo enhanced).
If your vocabulary is in Studio, you'll basically override it from your GitHub project. (If you're creating it from scratch, just follow the steps below and create it directly outside Studio.) If you already have it in Studio and are feeling lazy, you can copy-paste what Studio generates and start from there:
First, download the Studio JAR, open the extension.xml file, and copy the contribution for your vocabulary. It will look something like this:
<extension target="org.nuxeo.ecm.directory.GenericDirectory" point="directories">
<directory name="VOC_ReportingStatement" extends="template-vocabulary">
<autoincrementIdField>false</autoincrementIdField>
<createTablePolicy>on_missing_columns</createTablePolicy>
<dataLoadingPolicy>update_duplicate</dataLoadingPolicy>
<table>studio_vocabulary_VOC_ReportingStatement</table>
<dataFile>data/vocabularies/VOC_ReportingStatement.csv</dataFile>
<cacheEntryName>vocab-VOC_ReportingStatement-cache</cacheEntryName>
<cacheEntryWithoutReferencesName>vocab-VOC_ReportingStatement-cache-without-references</cacheEntryWithoutReferencesName>
</directory>
</extension>
Save the CSV file from the same JAR. You'll find it under: data/vocabularies/VOC_ReportingStatement.csv
In your GitHub project, create a new schema file: schema/enhancedvocabulary.xsd
<?xml version="1.0"?>
<xs:schema
targetNamespace="http://www.nuxeo.org/ecm/schemas/vocabulary"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="id" type="xs:string"/>
<xs:element name="label" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="obsolete" type="xs:integer" default="0"/>
<xs:element name="ordering" type="xs:integer" default="10000000"/>
</xs:schema>
👉 Notice the extra description field!
Create a new contribution inspired by what you copied from Studio:
<component name="mycustom.directories.contrib">
<require>studio.extensions.myStudioProject</require>
<extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema">
<schema name="enhancedvocabulary" src="schemas/enhancedvocabulary.xsd" />
</extension>
<extension target="org.nuxeo.ecm.directory.GenericDirectory" point="directories">
<directory name="VOC_ReportingStatement" extends="template-xvocabulary">
<schema>enhancedvocabulary</schema>
<autoincrementIdField>false</autoincrementIdField>
<createTablePolicy>on_missing_columns</createTablePolicy>
<dataLoadingPolicy>skip_duplicate</dataLoadingPolicy>
<cacheEntryName>vocab-VOC_ReportingStatement-cache</cacheEntryName>
<cacheEntryWithoutReferencesName>vocab-VOC_ReportingStatement-cache-without-references</cacheEntryWithoutReferencesName>
</directory>
</extension>
</component>
require for studio.extensions.myStudioProject). This ensures the custom contribution loads after Studio's. You can find the name of the Studio contribution inside the extension.xml file in the Studio JAR. (If you're defining the vocabulary entirely here, or removed it from Studio, you don't need the require.)<dataFile> entry anymore. That's intentional: if your production instance already has values, there's no need to reload from CSV (unless you use always as the loading policy, which you should not!). But if it's a new vocabulary, definitely add it back (and include a description column in your CSV!).Since the vocabulary now uses a new schema, it also needs a new web UI layout to display the extra field. Nuxeo loads directory layouts based on naming conventions, so create your new layout at this exact location:
directory/enhancedvocabulary/nuxeo-enhancedvocabulary-edit-layout.html
You can copy the existing element from: directory/vocabulary/nuxeo-vocabulary-edit-layout.html ...and simply add:
<nuxeo-input
role="widget"
label="Description"
name="description"
value="{{entry.properties.description::change}}">
</nuxeo-input>
And that's it: your vocabulary now carries extra semantic context for AI (and for humans, too). When your AI workflows use these vocabularies, they'll have clearer, more consistent metadata to work with and fewer "creative" guesses from the model.
Keep reading
Imagine flipping through billions of images, PDFs, and documents—instantly finding exactly what you need, without lifting a finger to tag or classify. That’s the magic we’re unveiling today.
Read articleAlready running Nuxeo? You have everything you need to add serious AI capabilities—embeddings, semantic search, MCP, async pipelines. Here’s why and how.
Read articleIn today’s digital landscape, efficient search capabilities are critical for managing and retrieving vast amounts of information. Traditional keyword-based search methods often fail to capture the semantic meaning behind user queries, leading to suboptimal results. By leveraging AI-powered embeddings, we can enhance search functionality, making it more intelligent and context-aware. In this post, we will […]
Read articleTell us what you're struggling with, and we'll tell you how we can help you.
Talk to us