- Users
- Managing Models and Releases
- Uploading Artifacts
- Using a Model
- Reviews
- Reviewing Releases and Access Requests
- Reviewed Releases and Access Requests
- Programmatically using Bailo
- Administration
- Getting Started
- Helm
- Schema
- Migrations
Creating and Uploading schemas
Bailo makes use of the RJSF (react-jsonschema-form) library in order to dynamically create its upload & access request forms. These forms are constructed using existing widgets, or custom widgets that have been created specifically for Bailo.
Example / minimal schemas
Bailo includes both an example schema for uploads and for deployments. You can find them in
backend/src/scripts/example_schemas
. It is important to note that these schemas contain all of mandatory fields that
the application needs in order to run. These fields are hard-coded in various places in the source code.
Create a schema
Simple questions
A typical object inside the schema will look like this:
"firstName": {
"type": "string",
"title": "First name",
"default": "Chuck",
"description": "This is for your first name"
}
The type property can be altered depending on what value you want the question to return. The title property will be displayed as the question itself, and the description will appear under the question to include any additional information that might help the user. Please note that if you do not include a title property, the library will use the name of the object (in this case firstName) instead.
Dates
Dates can be added like this:
"date": {
"type": "string",
"title": "Date of birth",
"format": "date"
}
Sections
When using Bailo you will see that the upload form is made up of a number of pages. Each page is a separate object inside the first "properties" property of the schema. For example:
"properties": {
"firstPage": {
"type": "object",
"title": "Page 1",
"properties": {
...
}
},
"secondPage": {
"type": "object",
"title": "Page 2",
"properties": {
...
}
}
}
Creating sub-sections works identically to how we defined our pages above. If we take the first page of our example above, and then amend it so it looks like this:
"properties": {
"firstPage": {
"type": "object",
"title": "Page 1",
"properties": {
"sectionOne": {
"type": "object",
"title": "Section 1"
"properties": {
"questionOne": {
"type": "number",
"title": "Enter a number",
}
}
},
"sectionTwo": {
"type": "object",
"title": "Section 2"
"properties": {
"questionTwo": {
"type": "string",
"title": "Enter a string",
}
}
}
},
...
}
}
Hiding sections from the model card
Sections will display on the model card page by default, but in the case whereby a section needs to be hidden from the model card, then add the following property:
"myPage": {
"title": "Page 1",
"type": "object",
"properties": {
...
},
"displayModelCard": false,
}
Note: This will only hide it from the model page, the data will still persist in the version metadata.
Dependencies
A dependency is useful when the answer to one question might warrant some additional information; for example, a boolean question might not need a detailed response if the answer is 'no', but if the user answer is 'yes' you might want to ask them for some additional details.
To avoid validation errors, Bailo schema dependencies need to be handled slightly differently to the ones provided in the RJSF documentation. Here is an example of how we handle dependencies for Bailo schemas:
"myPage": {
"title": "Page 1",
"type": "object",
"properties": {
"questionOne": {
"type": "boolean",
"title": "True or false?",
},
"questionTwo": {
"title": "More information please!",
"type": "string",
}
},
"dependencies": {
"questionOne": {
"oneOf": [
{
"properties": {
"questionOne": {
"enum": [false],
"readOnly": false
},
"questionTwo": {
"readOnly": true
}
},
"required": ["questionOne"],
"additionalProperties": false
},
{
"properties": {
"questionOne": {
"enum": [true],
"readOnly": false
},
"questionTwo": {
"readOnly": false
}
},
"required": ["questionOne", "questionTwo"],
"additionalProperties": false
}
]
}
},
"required": ["questionOne"]
}
Inside dependencies
we have defined a case of only having one of two different situations. Firstly, if questionOne
is set to false
, then questionTwo
will be set to read only, whereas if we set questionOne
to true
then
questionTwo
will not be set as read only. This method might seem slightly more convoluted than the documentation
online, but it allows for answers to be changed without making the schema invalid. The current design of RJSF's
dependencies works as so:
- User selects
true
forquestionOne
- User enters data into
questionTwo
- User changes their mind and selects
false
forquestionOne
- User data for
questionTwo
remains in the form data, despite not being visible on the form itself
This behaviour is so that any user data is retained in case the user wishes to select true
for questionOne
again.
From a user perspective this nice as it means there is less chance of data being lost when changing answers, but it does
have a knock-on affect whereby in certain situations it will make the schema fail validation. Our approach is set the
additional questions to read only when they are not in use. The downside to this approach is that we potentially include
unwanted additional data, but this can be removed by the user if this happens.
Copyright © Crown Copyright 2025.