Status: canonical metadata schema for VLCode-Lite and DocCenter Path
4Scope:
- Defines the canonical
ProjectMetaJSON consumed by metadata diff, workflow regeneration, project context, and DocCenter-backed tooling- Normalizes legacy extractor output into one stable shape
- Aligns Theme metadata with VL 3.7 / THEME 6.6
- Clarifies that DocCenter / workflow document bindings live in project config as
Doc ID, not insideProjectMeta
ProjectMeta is the machine-readable project model for a VL workspace.
It exists to support:
Apps/, Sections/, ExtComponents/, Services/, Database/, and Theme/This spec defines the canonical schema. Legacy field names may still be accepted by importers, but they are not canonical output.
Canonical root object:
{
"$schema": "VL-ProjectMeta/3.0",
"projectName": "SmartCampus",
"projectDescription": "optional",
"vlVersion": "3.7",
"config": {
"deviceTarget": "web",
"screenResolution": "1440x900"
},
"fileManifest": [],
"valueDomains": {},
"apps": [],
"sections": [],
"components": [],
"services": [],
"dataSchema": {
"tables": [],
"relations": []
},
"theme": null,
"dependencyGraph": null
}
apps[*].id is the canonical app identifiersections[*].id is the canonical section identifiercomponents[*].id is the canonical component identifierservices[*].domainId is the canonical service-domain identifierservices[*].methods[*].id is the canonical method identifierservices[*].methods[*].serviceId is the canonical fully-qualified service identifier, normally domainId.methodIddataSchema.tables[*].id is the canonical table identifiertheme.id is the canonical theme identifierLegacy aliases such as appId, sectionId, componentId, tableName, serviceDomains, servicesUsed, and componentRefs are compatibility inputs only.
Canonical default file locations:
Apps/<id>.vxSections/<id>.scExtComponents/<id>.cpServices/<domainId>.vsDatabase/<projectName>.vdb or explicit per-table/file-level mapping when availableTheme/Theme.vthIf filePath is omitted during normalization, tooling may synthesize the conventional path above.
ProjectMeta must not inline DocCenter binding configuration for core specs or workflow prompts.
The following values belong to IDE / project profile configuration, not metadata schema:
coreDocIdsdocIdOverridesDoc Ref or viewer URL such as vl://doc/16 or /doc-center.html?docId=16Reason:
ProjectMeta models the project itself{
"id": "AdminApp",
"filePath": "Apps/AdminApp.vx",
"vlVersion": "3.7",
"device": "web",
"resolution": "1440x900",
"description": "",
"globalVars": [],
"pages": [
{
"id": "Dashboard",
"route": "/dashboard",
"sections": ["DashboardMain"],
"sectionRefs": [
{
"sectionId": "DashboardMain",
"instanceId": "mainSection",
"layoutProps": {}
}
],
"componentRefs": [],
"layout": []
}
],
"routeMap": {
"/dashboard": "DashboardMain"
},
"homeRoute": "/dashboard",
"wiring": [],
"navSectionInstanceId": null,
"navEventName": null
}
Rules:
pages[*].id must be stable inside the apppages[*].sections contains section IDs onlypages[*].sectionRefs[*].sectionId must resolve to an existing sectionrouteMap is a convenience index, not a second source of truth{
"id": "DashboardMain",
"filePath": "Sections/DashboardMain.sc",
"vlVersion": "3.7",
"previewSize": null,
"publicProps": [],
"publicEvents": [],
"publicMethods": [],
"globalVars": [],
"derivedVars": [],
"consumesServices": [
"CampusService.getOverview",
"CampusService.listAlerts"
],
"usesComponents": [
"StatCard",
"AlertTable"
],
"interactiveElements": [],
"internalMethods": [],
"pipeFuncs": [],
"isNavSection": false,
"navMenuItems": [],
"navItemInstanceId": null,
"keyStates": {},
"description": ""
}
Rules:
consumesServices is an array of service ID strings, not nested service objectsusesComponents is an array of component ID strings, not component ref objectsconsumesServices[*] must resolve to an existing services[*].methods[*].serviceIdusesComponents[*] must resolve to an existing components[*].id{
"id": "StatCard",
"filePath": "ExtComponents/StatCard.cp",
"vlVersion": "3.7",
"previewSize": null,
"publicProps": [],
"publicEvents": [],
"derivedVars": [],
"interactiveElements": [],
"internalMethods": [],
"pipeFuncs": [],
"description": ""
}
{
"domainId": "CampusService",
"filePath": "Services/CampusService.vs",
"vlVersion": "3.7",
"envVars": [],
"methods": [
{
"id": "getOverview",
"serviceId": "CampusService.getOverview",
"type": null,
"params": [],
"returns": {},
"expose": null,
"sig": null
}
],
"virtualTables": [
{
"id": "OverviewView",
"source": "campus_overview",
"fields": ["id", "title"],
"extraSpecs": {}
}
],
"transactions": [],
"backendComponents": []
}
Rules:
domainId is canonical; id/name are compatibility inputs onlymethods[*].id is canonical; methods[*].name is compatibility input onlymethods[*].serviceId should be emitted even when it can be derivedvirtualTables[*].source must reference an existing table ID when it points to a physical table{
"dataSchema": {
"tables": [
{
"id": "campus_overview",
"name": "campus_overview",
"filePath": "",
"fields": [
{
"name": "id",
"type": "STRING",
"notNull": true,
"default": null,
"enumRef": null,
"sourceField": null
}
],
"indexes": [],
"seedData": null
}
],
"relations": [
{
"id": "overview_to_building",
"from": "campus_overview",
"to": "building",
"cardinality": "N:1"
}
]
}
}
Rules:
id, not tableNamefields; columns is compatibility input onlyenumRef must resolve into valueDomains.enums[*].name when used{
"theme": {
"id": "Theme",
"name": "Theme",
"filePath": "Theme/Theme.vth",
"vlVersion": "3.7",
"rootTag": "Theme-Enterprise-6.6",
"meta": {
"mode": "light",
"version": "6.6.0",
"styleSpaceVersion": "1.6",
"base_theme": "Platform/Theme-Default-Light@1",
"profile": "enterprise"
},
"slots": {
"intent.primary.intentBg": "#2563EB",
"size.md.sizeMinHeight": "40px",
"state.focus.stateShadow": "@intent.intentFocusRing"
},
"designTokens": [],
"componentVariants": [],
"bindingRules": [],
"overrides": []
}
}
Rules:
# Meta plus # Point Slot Valuestheme.slots is the canonical compiled metadata view of .vth point-slot assignmentsdesignTokens, componentVariants, bindingRules, and overrides are compatibility carry-through fields only; new tooling should not require themValidation must reject or flag at least the following:
enumRef points at a non-existent enumNormalizers may accept the following legacy inputs:
| Legacy input | Canonical output |
|---|---|
project.name / project.projectName |
projectName |
database |
dataSchema |
serviceDomains |
services |
appId |
apps[*].id |
sectionId |
sections[*].id |
componentId |
components[*].id |
servicesUsed / services / serviceDomains on section |
consumesServices |
componentRefs / components on section |
usesComponents |
tableName / entityId |
dataSchema.tables[*].id |
columns |
fields |
methods[*].name |
methods[*].id |
theme.pointSlotValues / theme.pointSlots |
theme.slots |
Compatibility input does not change canonical output names.
Any producer that claims compliance with Metadata Spec 3.1 must emit:
$schema: "VL-ProjectMeta/3.0"sections[*].consumesServices as string IDssections[*].usesComponents as string IDsservices[*].methods[*].iddataSchema.tables[*].idtheme.slots when theme slot data is availableConsumers should:
Use exactly:
VL-ProjectMeta/3.0