Layout Customization
Create custom visual layouts for annotation tasks with HTML templates and CSS.
Layout Customization
New in v2.1.0
Potato provides two approaches for customizing the annotation interface layout:
- Auto-generated layouts: Potato generates an HTML layout file that you can edit
- Custom layout files: Create your own HTML template with full control over styling
Quick Start
Using Auto-generated Layouts
- Run your server once — Potato creates
layouts/task_layout.html - Edit the generated file to customize styling
- Your changes persist across server restarts (unless you modify
annotation_schemesin the config)
Using Custom Layout Files
- Create your layout file (e.g.,
layouts/custom_task_layout.html) - Reference it in your config:
task_layout: layouts/custom_task_layout.htmlLayout File Structure
A custom layout file must include:
<style>
/* Your custom CSS */
</style>
<div class="annotation_schema">
<!-- Your annotation forms -->
<form id="schema_name" class="annotation-form radio" data-annotation-id="0">
<fieldset schema="schema_name">
<legend>Question text</legend>
<!-- Input elements -->
</fieldset>
</form>
</div>Required Form Attributes
Each annotation scheme needs:
| Attribute | Description |
|---|---|
id | Must match the name in your config's annotation_schemes |
class | Include annotation-form and the type (e.g., radio, multiselect) |
data-annotation-id | Sequential index (0, 1, 2...) |
schema | Attribute on fieldset and inputs matching the schema name |
Required Input Attributes
<input class="schema_name annotation-input"
type="radio"
name="schema_name"
value="label_value"
schema="schema_name"
label_name="label_value"
onclick="onlyOne(this);registerAnnotation(this);">Example Layouts
Potato includes three example layouts demonstrating advanced customization:
1. Content Moderation Dashboard
Location: project-hub/layout-examples/content-moderation/
Features a warning banner header with content metadata, 2-column grid for violation categories, color-coded severity levels, and a professional moderation workflow.
python -m potato start project-hub/layout-examples/content-moderation/config.yaml -p 80002. Customer Service Dialogue QA
Location: project-hub/layout-examples/dialogue-qa/
Features a case header with metadata badges, grouped assessment sections, circular Likert-scale ratings, quality issues checklist, and color-coded resolution indicators.
python -m potato start project-hub/layout-examples/dialogue-qa/config.yaml -p 80003. Medical Image Review
Location: project-hub/layout-examples/medical-review/
Features professional medical UI styling, two-column layout for location/severity, grouped findings sections, structured medical reporting, and recommendation cards with descriptions.
python -m potato start project-hub/layout-examples/medical-review/config.yaml -p 8000CSS Techniques
Grid Layouts
Create multi-column layouts:
.annotation-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.full-width {
grid-column: 1 / -1;
}
@media (max-width: 768px) {
.annotation-grid {
grid-template-columns: 1fr;
}
}Color-Coded Options
Style radio buttons with severity colors:
.severity-option input[type="radio"] {
position: absolute;
opacity: 0;
}
.severity-label {
display: block;
padding: 10px;
border-radius: 6px;
border: 2px solid transparent;
cursor: pointer;
transition: all 0.2s;
}
/* Green for "None" */
.severity-none .severity-label {
background: #dcfce7;
color: #166534;
}
.severity-none input:checked + .severity-label {
background: #22c55e;
color: white;
}
/* Red for "Severe" */
.severity-severe .severity-label {
background: #fee2e2;
color: #991b1b;
}
.severity-severe input:checked + .severity-label {
background: #ef4444;
color: white;
}Section Styling
Create visual groupings:
.annotation-section {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
.section-title {
font-size: 13px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 2px solid #3b82f6;
}Circular Likert Ratings
.likert-circle {
width: 36px;
height: 36px;
border-radius: 50%;
border: 2px solid #e2e8f0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.likert-option input:checked + .likert-circle {
background: #8b5cf6;
color: white;
border-color: #7c3aed;
}Combining with Instance Display
Custom layouts work alongside instance_display configuration. The instance content (images, text, dialogues) renders separately above your annotation forms.
instance_display:
fields:
- key: image_url
type: image
display_options:
zoomable: true
task_layout: layouts/custom_task_layout.html
annotation_schemes:
- annotation_type: radio
name: category
labels: [A, B, C]Best Practices
- Match schema names: Form
idmust exactly matchnameinannotation_schemes - Sequential annotation IDs: Use 0, 1, 2... for
data-annotation-id - Include required handlers: Use
onclick="onlyOne(this);registerAnnotation(this);"for radio,onclick="registerAnnotation(this);"for checkbox - Test responsiveness: Use media queries for mobile support
- Keep accessibility: Use proper labels and maintain keyboard navigation
Troubleshooting
Annotations not saving
Check that:
- Form
idmatches annotation schemename - Inputs have
schemaandlabel_nameattributes - Click handlers (
registerAnnotation) are present
Styles not applying
- Ensure CSS specificity is high enough to override defaults
- Check that your
<style>block is inside the layout file - Use browser dev tools to inspect applied styles
Layout not loading
- Verify path in
task_layoutis relative to config file - Check for HTML syntax errors
- Review server logs for error messages
Further Reading
- Instance Display - Configure what content to show
- UI Configuration - Interface customization options
- Annotation Schemes - Available annotation types
For implementation details, see the source documentation.