One Codebase, N Deployment Contexts: The Web Component Configuration Pattern
TLDR
Deploying specialized variants of a canvas tool (e.g., Electrical Schematics, AEC Floorplans, UML Diagrams) by copying and pasting main HTML/JS files leads to code drift and fragmented bug fixes. Encapsulating the core canvas engine inside a Web Component (<schema-editor>) and passing domain configurations via HTML attributes (domain="electrical") allows host pages to act as thin shells while maintaining a single, unified engine codebase.
| Deployment Model | Source Code Structure | Bug Fix Maintenance | Scalability for New Domains |
|---|---|---|---|
| Copy-Pasted HTML Files | N independent copies | High (Fixes must be manually copied) | Fragile (Code drift within weeks) |
| Web Component Shells | Single Canonical Engine (schema-editor.js) | Zero (Fixes apply everywhere) | High (New domain = 15-line shell) |
Problem statement: the multi-domain drift tax
Our schema editor supports multiple specialized engineering domains:
- Electrical: Requires logic symbol palettes, grid snapping, and netlist exports.
- Floorplan: Requires wall/door symbols, dimensioning tools, and DXF exports.
- UML Architecture: Requires class node palettes and flowchart connectors.
index.html into domain subdirectories (electrical/index.html, floorplan/index.html).
Within weeks, bug fixes applied to electrical/index.html were omitted from floorplan/index.html, causing feature drift and duplicate bug reports.
Technical failure mode: fragmented code engines
Duplicating HTML and script setups produces independent codebase copies:
- Divergent Implementations: Engine improvements made in one file are missed in others.
- High Maintenance Overhead: Updating canvas routing or rendering logic requires editing N separate files.
The fix & architecture: Web component encapsulation
Encapsulate core canvas logic inside a Web Component custom element (<schema-editor>). Domain pages import the component script and pass configuration via the domain attribute:
Step 1: Web component definition (schema-editor.js))
// Central Canvas Engine Web Component
class SchemaEditorElement extends HTMLElement {
static get observedAttributes() {
return ['domain'];
}
connectedCallback() { const domain = this.getAttribute('domain') || 'general'; this.initEngine(domain); }
attributeChangedCallback(name, oldValue, newValue) { if (name === 'domain' && oldValue !== newValue) { this.switchDomainConfig(newValue); } }
initEngine(domainKey) { const config = DOMAIN_CONFIGURATIONS[domainKey] || DOMAIN_CONFIGURATIONS.general;
this.setupPalette(config.palette); this.setupGridSnap(config.snapGridSize); this.setupExporters(config.exportFormats); } }
customElements.define('schema-editor', SchemaEditorElement);
Step 2: centralized configuration registry
const DOMAIN_CONFIGURATIONS = {
electrical: {
palette: ['resistor', 'capacitor', 'ic', 'gnd'],
snapGridSize: 10,
exportFormats: ['svg', 'netlist', 'bom']
},
floorplan: {
palette: ['wall', 'door', 'window', 'hvac'],
snapGridSize: 50,
exportFormats: ['svg', 'dxf']
}
};
Step 3: declarative host page shells
Domain host pages become 15-line shells:<!-- electrical/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Electrical Schematic Editor</title>
<script type="module" src="/src/components/schema-editor.js"></script>
</head>
<body>
<schema-editor domain="electrical"></schema-editor>
</body>
</html>
Rule of thumb: Encapsulate multi-context tools inside Web Components using attribute interfaces (domain="electrical"). Treat domain HTML files as thin declarative shells.