Introduced in v0.18.0, the Universal WC Engine enables openElement to automatically detect and classify third-party Web Component packages - deciding safely which ones can SSR and which must stay client-only.
Third-party Web Components come from different ecosystems. Some use Lit, some use vanilla classes, some are browser-only with real-DOM dependencies. openElement no longer assumes every package is SSR-safe - it reads their custom-elements.jsonmanifest and makes informed decisions.
Many popular Web Component libraries (e.g. @shoelace-style/shoelace)do not ship a custom-elements.json file. Without CEM, auto-detection returns no results for these packages, and they rely on explicitpackageIslands declarations in vite.config.ts.
| Tier | Meaning | Build Behavior |
|---|---|---|
ssr-capable | Explicit openElement SSR declaration or adapter support | Import in SSR bundle, participate in DSD rendering |
client-only | Browser-only, or no SSR declaration
| Exclude from SSR bundle, emit client registration/hydration metadata |
rejected | Invalid manifest, duplicate tags, unsafe paths | Fail before code generation |
experimental-dom | Opt-in DOM simulation candidate | Render only when flag is enabled, report all results |
During the Vite plugin's buildStart() phase, openElement automatically scansnode_modules for custom-elements.json files:
// Pseudocode - actual implementation in route-scanner.ts
for (const pkg of node_modules) {
const cemPath = join(pkg, 'custom-elements.json');
if (exists(cemPath)) {
const parsed = parseCem(cemPath); // CEM parser
const classified = classify(parsed); // compatibility classifier
results.push(classified);
}
}@org/pkg patternsThe build report now includes a cemCompatibility section:
{
"reportVersion": "1.1.0",
"cemCompatibility": {
"packageCount": 2,
"packages": [
{
"packageName": "@third-party/wc-button",
"tier": "client-only",
"reason": "No openElement SSR extension in CEM",
"componentCount": 5
}
]
}
}Each entry includes the package name, compatibility tier, reason, and component count for debugging and audit purposes.
Although v0.18.0 detection is live, the third-party packages used on this site -@shoelace-style/shoelace and media-chrome -do not ship custom-elements.json. So auto-detection returns no results for them. They continue to rely on explicitpackageIslands declarations in vite.config.ts.
| Scenario | CEM Detection | Behavior |
|---|---|---|
| Has CEM + openElement SSR extension | ssr-capable | Auto-added to SSR bundle |
| Has CEM + no SSR declaration | client-only | Safe fallback, no server rendering |
| No CEM | Empty (not detected) | Manual via packageIslands |
| No CEM + not in packageIslands | Empty | Not registered (requires explicit import) |
less validate-manifest CLI - pre-install validationopen add - one-click install and configure