Template System

Technical documentation for the module template and reset system

This document covers the technical implementation of module templates, installation, customization detection, and the reset mechanism.

Core Concepts

VendorManaged Flag

Every field, view, and reference has a VendorManaged boolean flag that indicates whether it came from a template or was created by the user.

VendorManagedMeaningReset Behavior
trueCreated by template installationReset will restore to template default
falseCreated by userNever modified by reset

This separation allows reset to restore template items without touching user customizations.

Template vs. Installed Schema

When a template is installed, Coherence stores:

  • Template definition - The original schema in the template catalog
  • Installed schema - The current state in the workspace

Reset compares these to identify what changed.

Customization Detection

How hasCustomizations Works

The marketplace shows "Reset to default" only when hasCustomizations: true. This is computed by comparing:

Template Definition:

{
  fields: ["first_name", "last_name", "email", "phone"],
  views: ["list", "detail"],
  references: ["account_id"]
}

Installed Schema (VendorManaged only):

{
  fields: ["first_name", "last_name", "email"],  // phone removed
  views: ["list"],                                // detail removed
  references: ["account_id"]
}

If any difference exists, hasCustomizations = true.

Query Logic

Only vendor-managed items are compared:

-- Get installed vendor-managed fields
SELECT DISTINCT "ModuleId", "Slug"
FROM "ModuleField"
WHERE "ModuleId" = ? AND "VendorManaged" = true;
 
-- Get installed vendor-managed views
SELECT DISTINCT "ModuleId", "Slug"
FROM "ModuleView"
WHERE "ModuleId" = ? AND "VendorManaged" = true;
 
-- Get installed vendor-managed references
SELECT DISTINCT "SourceModuleId" as "ModuleId", "Slug"
FROM "ModuleReference"
WHERE "SourceModuleId" = ? AND "VendorManaged" = true;

User-created items (VendorManaged = false) are ignored in the comparison because they're intentional additions, not deviations from the template.

Reset Process

Overview

Reset performs three operations:

  1. Delete - Remove vendor-managed items not in template
  2. Update - Restore vendor-managed items to template config
  3. Insert - Add template items that were deleted

User-created items are never touched.

Config Merging

Field configurations contain both static settings (type, label, options) and runtime state (auto-number sequences, formula caches). Reset uses a merge strategy:

// Template provides defaults
const templateConfig = { prefix: "PER-", padLength: 4 };
 
// Existing config has runtime state
const existingConfig = { prefix: "PER-", padLength: 4, nextValue: 157 };
 
// Merge: template defaults + existing overrides
const mergedConfig = { ...templateConfig, ...existingConfig };
// Result: { prefix: "PER-", padLength: 4, nextValue: 157 }

This preserves:

  • Auto-number nextValue sequences
  • Formula calculation caches
  • Any runtime state in the Config column

Reset Response

The reset endpoint returns a summary:

interface ResetResult {
  fieldsRemoved: number;   // User modifications to template fields
  fieldsAdded: number;     // Template fields that were deleted
  viewsAdded: number;      // Template views that were deleted
  referencesAdded: number; // Template references that were deleted
}

Database Schema

Module Table

CREATE TABLE "Module" (
  "ModuleId" UUID PRIMARY KEY,
  "AccountId" UUID NOT NULL,
  "Slug" VARCHAR(255) NOT NULL,
  "VendorManaged" BOOLEAN DEFAULT false,
  "TemplateSlug" VARCHAR(255),        -- Source template identifier
  "TemplateVersion" VARCHAR(50),       -- Installed template version
  ...
);

ModuleField Table

CREATE TABLE "ModuleField" (
  "ModuleFieldId" UUID PRIMARY KEY,
  "ModuleId" UUID NOT NULL,
  "Slug" VARCHAR(255) NOT NULL,
  "Type" VARCHAR(50) NOT NULL,
  "Config" JSONB,                      -- Type-specific configuration
  "VendorManaged" BOOLEAN DEFAULT false,
  ...
);

ModuleView Table

CREATE TABLE "ModuleView" (
  "ModuleViewId" UUID PRIMARY KEY,
  "ModuleId" UUID NOT NULL,
  "Slug" VARCHAR(255) NOT NULL,
  "Type" VARCHAR(50) NOT NULL,
  "Config" JSONB,
  "VendorManaged" BOOLEAN DEFAULT false,
  ...
);

ModuleReference Table

CREATE TABLE "ModuleReference" (
  "ModuleReferenceId" UUID PRIMARY KEY,
  "SourceModuleId" UUID NOT NULL,
  "TargetModuleId" UUID NOT NULL,
  "Slug" VARCHAR(255) NOT NULL,
  "VendorManaged" BOOLEAN DEFAULT false,
  ...
);

API Endpoints

List Template Catalog

GET /api/templates/catalog

Returns available templates with installation status:

{
  "templates": [
    {
      "templateSlug": "people",
      "name": "People",
      "description": "Track individuals...",
      "templateVersion": "1.0.0",
      "installed": true,
      "installedModuleId": "mod_abc123",
      "hasCustomizations": true
    }
  ]
}

Reset to Template

POST /api/modules/:moduleId/reset-to-template

Resets the module schema to match the template definition.

Response:

{
  "success": true,
  "fieldsRemoved": 2,
  "fieldsAdded": 1,
  "viewsAdded": 1,
  "referencesAdded": 0
}

Auto-Number Fields

Sequence Preservation

Auto-number fields store their sequence counter in the Config column:

{
  "prefix": "PER-",
  "padLength": 4,
  "nextValue": 157
}

Reset preserves nextValue through config merging, so existing records keep their numbers and new records continue the sequence.

Backfill Feature

To regenerate numbers for existing records:

PATCH /api/modules/:moduleId/fields/:fieldId
{
  "backfillExisting": true
}

This assigns sequential numbers to all records missing a value, starting from nextValue.

Implementation Files

FilePurpose
services/module-config/src/services/template-catalog-service.tsCatalog listing and hasCustomizations
services/module-config/src/services/workspace-bootstrap-service.tsReset and installation logic
packages/sdk/src/types.tsTypeScript types for templates
apps/web/src/pages/AddonsMarketplacePage.tsxMarketplace UI

Related: API Overview | Module Templates