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.
Example
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).
Step 1: If Your Vocabulary Is in Studio
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
Step 2: Create a New XSD Schema
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!
Step 3: Add a New XML Contribution
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>
Two Important Notes
- We're overriding the vocabulary from Studio (that's why there is a
requireforstudio.extensions.myStudioProject). This ensures the custom contribution loads after Studio's. You can find the name of the Studio contribution inside theextension.xmlfile in the Studio JAR. (If you're defining the vocabulary entirely here, or removed it from Studio, you don't need the require.) - You'll notice there is no
<dataFile>entry anymore. That's intentional: if your production instance already has values, there's no need to reload from CSV (unless you usealwaysas 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!).
Step 4: Update the UI Layout
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>
Wrapping Up
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.
Work with Maretha
Working through a content platform challenge?
Bring your platform, constraints and questions. Let us help you work through the approach.
Discuss your project ↗