Link web components to your package
In a repo that uses your web components, a tag such as <acme-button> has no package unless something links it to yours. With no package it has no version, and a lifecycle record on your package can't cover it. To link your tags in every repo that installs your package, ship a Custom Elements Manifest and point your package.json at it.
1. Ship the manifest
Generate a custom-elements.json with your usual tooling, or write one by hand. The scan reads only which tags you declare: each declaration needs "customElement": true and a tagName.
{
"schemaVersion": "1.0.0",
"modules": [{
"kind": "javascript-module",
"path": "src/button.js",
"declarations": [{ "kind": "class", "customElement": true, "name": "AcmeButton", "tagName": "acme-button" }]
}]
}
Make sure the file is published with the package. If your package.json has a files list, it must include the manifest.
2. Point package.json at it
Add a customElements field with the manifest's path, relative to package.json:
{
"name": "@acme/elements",
"version": "2.1.0",
"customElements": "dist/custom-elements.json"
}
The scan follows only this field. A custom-elements.json that no customElements field points at is ignored, even at the package root.
Publish a new version of the package.
3. Check a scan
In a repo that uses the tag, install the new version, then scan. The scan reads the manifest from the installed package, so install dependencies first.
npx scout scan --dry-run
jq '.components[] | select(.identity.tagName == "acme-button") | {status: .attribution.status, package: .attribution.target.packageName, version}' scout-scan.json
The tag's attribution is resolved to your package, and its version is set:
{
"status": "resolved",
"package": "@acme/elements",
"version": "2.1.0"
}
Once you upload a scan with npx scout scan, open the tag's page in the dashboard. A badge beside its name reads Web component, and the line under the name shows @acme/elements · v2.1.0 in place of <no package>. The tag is also listed in the Components table of the package's page (see Read a package page), and a lifecycle record on @acme/elements now covers it.
The manifest only tells the scan which package a tag belongs to. Descriptions, props, events and deprecation notes in it don't reach the scan or the dashboard. A tag's props and events are counted from what each place in the code passes, and only a lifecycle record marks it deprecated.
If it still has no package
The scan doesn't warn when it can't use a manifest: the tag's attribution.status just reads unknown, or conflict when two packages claim it. Check each of these:
- The repo doesn't install your package. The scan reads manifests only from packages installed in the scanned repo, so tags loaded from a CDN script stay without a package.
- The field is missing, or isn't a string path. Check
customElementsin the installed copy,node_modules/@acme/elements/package.json. - The file isn't at that path in the installed package. Look for it in
node_modules/@acme/elements/. Afileslist or a build step that leaves the manifest out gives a field that points at nothing. - The manifest isn't valid JSON. A file that doesn't parse, for example because of a trailing comma, is skipped.
- The declaration lacks
"customElement": trueor atagName. - Two installed packages declare the tag. The tag gets no package, and its
attribution.statusisconflict. Declare each tag in one package's manifest only: if@acme/uire-exports the elements of@acme/ui-core, don't copy the manifest into both. - The repo registers the tag with a class of its own. When the repo's code runs
customElements.define("acme-button", …)or uses@customElement("acme-button")with a class it defines itself, the tag belongs to that repo, not to your package: itsattribution.targetnames the file that defines the class. A class imported from@acme/elementslinks the tag to your package instead, with or without the manifest.