CONTRIBUTING
Template Creation
Learn how to create custom asset templates for specialized collections in Invenicum.
Asset templates allow you to define custom structures for specific types of collections. Whether you’re cataloging books, wine, vintage cameras, or trading cards, templates provide a standardized way to capture the metadata that matters for your collection.
What Are Templates?
Custom Fields
Specific attributes for your assets — e.g. ISBN for books, vintage year for wine
Field Types
Text, numbers, dates, dropdowns, checkboxes and more
Validation Rules
Required fields, min/max values, regex patterns
Categories
Classification for organizing and discovering templates
Metadata
Name, description, author information, download count
Template Structure
Templates are represented by the AssetTemplate model (asset_template_model.dart:3):
class AssetTemplate {
final String id;
final String name;
final String description;
final String category;
final List<String> tags;
final String author;
final String? authorAvatarUrl;
final String? downloadUrl;
final List<CustomFieldDefinition> fields;
final bool isOfficial;
final bool isPublic;
final int downloadCount;
final DateTime? createdAt;
final DateTime? updatedAt;
}Getting Started
Plan Your Template
Before creating a template, answer these questions:
Understand Custom Fields
Custom fields are the building blocks of templates. Each field has:
Name
Display label — e.g. "Publication Year"
Key
Internal identifier — e.g. "publication_year"
Type
Data type: text, number, date, boolean, dropdown
Required
Whether the field must be filled
Validation
Rules for valid input
Choose a Category
Creating Your First Template
Let’s create a template for a book collection step by step.
{
"name": "Book Collection",
"description": "Track books with ISBN, author, genre, and reading status",
"category": "Literature",
"tags": ["books", "reading", "library"],
"author": "your-github-username",
"isPublic": true,
"fields": []
}{
"fields": [
{
"name": "ISBN", "key": "isbn",
"type": "text", "required": false,
"validation": { "pattern": "^[0-9-]{10,17}$" }
},
{
"name": "Author", "key": "author",
"type": "text", "required": true
},
{
"name": "Publication Year", "key": "publication_year",
"type": "number",
"validation": { "min": 1000, "max": 2100 }
},
{
"name": "Genre", "key": "genre",
"type": "dropdown",
"options": ["Fiction", "Non-Fiction", "Mystery",
"Science Fiction", "Fantasy", "Biography", "History", "Other"]
},
{
"name": "Reading Status", "key": "reading_status",
"type": "dropdown",
"options": ["To Read", "Reading", "Completed", "On Hold"]
},
{
"name": "Favorite", "key": "is_favorite",
"type": "boolean", "description": "Mark as a favorite book"
},
{
"name": "Date Acquired", "key": "date_acquired",
"type": "date"
},
{
"name": "Notes", "key": "notes",
"type": "textarea", "description": "Personal notes and thoughts"
}
]
}Once tested, publish your template to share it with the Invenicum community marketplace.
See the Publishing section below for full steps
Field Types Reference
textSingle-line text inputValidation Options
maxLength — Maximum character countminLength — Minimum character countpattern — Regular expression pattern
{
"name": "Title", "key": "title",
"type": "text", "required": true,
"validation": {
"maxLength": 200,
"pattern": "^[a-zA-Z0-9\\s]+$"
}
}textareaMulti-line text for longer contentValidation Options
maxLength — Maximum character count
{
"name": "Description", "key": "description",
"type": "textarea", "required": false,
"validation": { "maxLength": 1000 }
}numberNumeric input with optional min/maxValidation Options
min — Minimum valuemax — Maximum valuestep — Increment (e.g. 0.01 for decimals)
{
"name": "Quantity", "key": "quantity",
"type": "number", "required": true,
"validation": { "min": 0, "max": 10000 }
}dateDate picker inputNo additional validation options — date format is handled automatically.
{
"name": "Purchase Date", "key": "purchase_date",
"type": "date", "required": false
}dropdownSelect from predefined optionsValidation Options
options — Array of selectable string values
{
"name": "Condition", "key": "condition",
"type": "dropdown", "required": true,
"options": ["Mint", "Excellent", "Good", "Fair", "Poor"]
}booleanCheckbox for true / false valuesValidation Options
defaultValue — Initial boolean value
{
"name": "In Stock", "key": "in_stock",
"type": "boolean", "required": false,
"defaultValue": true
}urlValidated URL input — clickable in item viewsValidation Options
pattern — e.g. "^https?://.*"
{
"name": "Product Link", "key": "product_url",
"type": "url", "required": false,
"validation": { "pattern": "^https?://.*" }
}Template Categories
Template Service API
The TemplateService (template_service.dart:5) provides the following methods:
Get Market Templates
Retrieve all publicly available templates
Future<List<AssetTemplate>> getMarketTemplates() async {
const url = '/templates/market';
final response = await _dio.get(url);
final List<dynamic> data = response.data;
return data.map((json) =>
AssetTemplate.fromJson(json)).toList();
}Publish Template
Publish a template to the marketplace
Future<AssetTemplate> publishTemplate(
AssetTemplate template) async {
final response = await _dio.post(
'/templates/publish',
data: template.toJson(),
);
return AssetTemplate.fromJson(response.data['data']);
}Get User Library
Get templates created by the current user
Future<List<AssetTemplate>> getUserLibrary() async {
const url = '/templates/my-library';
final response = await _dio.get(url);
final List<dynamic> data = response.data;
return data.map((json) =>
AssetTemplate.fromJson(json)).toList();
}Track Downloads
Increment download counter when template is used
Future<void> trackDownload(String templateId) async {
final url = '/templates/$templateId/download';
await _dio.post(url);
}Advanced Template Examples
Wine Collection Template
11 fields · Wine & Spirits · vintage, region, tasting notes
Wine Collection Template
11 fields · Wine & Spirits · vintage, region, tasting notes
{
"name": "Wine Collection",
"description": "Track wine bottles with vintage, region, and tasting notes",
"category": "Wine & Spirits",
"tags": ["wine", "cellar", "tasting"],
"fields": [
{ "name": "Vineyard", "key": "vineyard", "type": "text", "required": true },
{ "name": "Vintage Year", "key": "vintage_year", "type": "number", "required": true,
"validation": { "min": 1900, "max": 2026 } },
{ "name": "Wine Type", "key": "wine_type", "type": "dropdown", "required": true,
"options": ["Red", "White", "Rosé", "Sparkling", "Dessert", "Fortified"] },
{ "name": "Grape Varietal", "key": "grape_varietal", "type": "text" },
{ "name": "Region", "key": "region", "type": "text",
"description": "e.g., Bordeaux, Napa Valley" },
{ "name": "Alcohol Content (%)", "key": "alcohol_content", "type": "number",
"validation": { "min": 0, "max": 25, "step": 0.1 } },
{ "name": "Bottle Size (ml)","key": "bottle_size", "type": "dropdown",
"options": ["375", "750", "1000", "1500"] },
{ "name": "Drink By Year", "key": "drink_by_year", "type": "number" },
{ "name": "Tasting Notes", "key": "tasting_notes", "type": "textarea" },
{ "name": "Rating (1-5)", "key": "rating", "type": "number",
"validation": { "min": 1, "max": 5 } },
{ "name": "Cellared", "key": "is_cellared", "type": "boolean" }
]
}Camera Collection Template
10 fields · Electronics · manufacturer, model, sensor, condition
Camera Collection Template
10 fields · Electronics · manufacturer, model, sensor, condition
{
"name": "Vintage Cameras",
"description": "Catalog vintage and modern cameras with technical specs",
"category": "Electronics",
"tags": ["cameras", "photography", "vintage"],
"fields": [
{ "name": "Manufacturer", "key": "manufacturer", "type": "text", "required": true },
{ "name": "Model", "key": "model", "type": "text", "required": true },
{ "name": "Year Released", "key": "year_released", "type": "number",
"validation": { "min": 1800, "max": 2026 } },
{ "name": "Camera Type", "key": "camera_type", "type": "dropdown", "required": true,
"options": ["Film SLR", "Digital SLR", "Mirrorless", "Rangefinder",
"Medium Format", "Large Format", "Point & Shoot"] },
{ "name": "Sensor/Film Size","key": "sensor_size", "type": "dropdown",
"options": ["Full Frame", "APS-C", "Micro 4/3", "35mm Film", "120 Film", "4x5 Film"] },
{ "name": "Megapixels", "key": "megapixels", "type": "number",
"description": "For digital cameras" },
{ "name": "Working Condition","key": "working_condition","type": "dropdown","required": true,
"options": ["Fully Functional", "Partially Working", "Not Working", "Untested"] },
{ "name": "Cosmetic Condition","key": "cosmetic_condition","type": "dropdown",
"options": ["Mint", "Excellent", "Good", "Fair", "Poor"] },
{ "name": "Serial Number", "key": "serial_number", "type": "text" },
{ "name": "Included Accessories","key": "accessories", "type": "textarea",
"description": "Lenses, cases, manuals, etc." }
]
}Trading Card Template
11 fields · Collectibles · rarity, grading, market value
Trading Card Template
11 fields · Collectibles · rarity, grading, market value
{
"name": "Trading Cards",
"description": "Track sports, Pokemon, and other collectible trading cards",
"category": "Collectibles",
"tags": ["cards", "collectibles", "trading-cards"],
"fields": [
{ "name": "Card Name", "key": "card_name", "type": "text", "required": true },
{ "name": "Card Type", "key": "card_type", "type": "dropdown", "required": true,
"options": ["Sports - Baseball", "Sports - Basketball", "Sports - Football",
"Sports - Soccer", "Pokemon", "Magic: The Gathering", "Yu-Gi-Oh!", "Other TCG"] },
{ "name": "Set Name", "key": "set_name", "type": "text" },
{ "name": "Card Number", "key": "card_number", "type": "text" },
{ "name": "Year", "key": "year", "type": "number" },
{ "name": "Rarity", "key": "rarity", "type": "dropdown",
"options": ["Common", "Uncommon", "Rare", "Ultra Rare", "Secret Rare", "Legendary"] },
{ "name": "Graded", "key": "is_graded", "type": "boolean" },
{ "name": "Grade", "key": "grade", "type": "text",
"description": "e.g., PSA 10, BGS 9.5" },
{ "name": "Grading Company", "key": "grading_company", "type": "dropdown",
"options": ["PSA", "BGS", "CGC", "SGC", "Other"] },
{ "name": "Condition (Ungraded)","key": "condition", "type": "dropdown",
"options": ["Mint", "Near Mint", "Excellent", "Good", "Fair", "Poor"] },
{ "name": "Market Value", "key": "market_value", "type": "number",
"description": "Estimated current market value" }
]
}Quality Guidelines
Naming
- Use clear, descriptive names
- Avoid abbreviations unless widely recognized
- "Vintage Cameras" not "Cameras"
Descriptions
- Explain what the template is for
- Mention key fields included
- Keep it under 200 characters
- No marketing language
Field Design
- Order fields logically — most important first
- Use appropriate field types
- Add descriptions for non-obvious fields
- Set reasonable validation rules
- Mark truly required fields only
Categories & Tags
- Choose the most relevant category
- Add 3–5 descriptive tags
- Use consistent formatting (lowercase, hyphens)
Testing
- Test with real data before publishing
- Verify all validations work correctly
- Check field order makes sense
- Ensure dropdown options are comprehensive
Publishing Your Template
Finalize Your Template
Publish to Marketplace
Monitor Usage
Best Practices
Start Simple
Begin with essential fields. You can always add more in updates. Too many fields overwhelm users.
Use Dropdowns Wisely
Dropdowns are great for standardization but limit flexibility. Use them for fields with a known, limited set of options.
Think About Searching
Fields users will search/filter by should be consistent — dropdowns and standardized text work best.
Consider Market Standards
If your collection type has industry standards (ISBN, UPC, model numbers), include those fields.
Plan for Growth
Design templates that can evolve. Avoid overly specific fields that might not apply to all items.
Troubleshooting
Template Won’t Save
- Verify all required fields are filled
- Check for duplicate field
keyvalues - Ensure field keys use only valid characters (letters, numbers, underscores)
Validation Not Working
- Verify validation syntax matches the field type
- Test with edge cases (min, max, empty values)
- Check for typos in validation rules
Published Template Not Appearing
- Wait a few minutes for marketplace sync
- Verify
“isPublic”is set totrue - Check that the category is valid
- Ensure the template has at least one field
Next Steps
Plugin Development
Extend Invenicum with custom plugins
Contributing Guide
Contribute to the Invenicum project
Resources
Plugin Development
Section complete