---
title: "Name custom elements with the project · Agent Wranglers"
url: https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/custom-element-names
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Name custom elements with the project prefix

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/html-css/rules.json) holds every rule of this playbook as JSON.

- Level: Recommended
- Chapter: [HTML structure and reuse](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse)
- Rule: Give every custom element a name that starts with one project prefix and a hyphen, such as `bakery-basket`. Define each name in exactly one file.
- How: The HTML Standard requires a hyphen and a lowercase first letter in every custom element name. It also makes `customElements.define` throw when a name is already taken, so two libraries with the same short name break the page. A project prefix keeps your names apart from third-party ones. Use the element name as the module prefix for its classes and stylesheet, as [Give each component exactly one stylesheet](https://agentwranglers.se/playbook/html-css/structure-and-files/component-stylesheet) describes.
- Check: Every name passed to `customElements.define` matches `^bakery-[a-z0-9]+(-[a-z0-9]+)*$`, with the project's own prefix. Each name appears in exactly 1 `define` call across the source.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
// bakery-basket.js: one element, one file, one stylesheet named bakery-basket.css
class BakeryBasket extends HTMLElement {
  connectedCallback() { this.dataset.state = 'ready'; }
}
customElements.define('bakery-basket', BakeryBasket);
```

### Python example

```python
# Build check: every custom element carries the prefix and is defined once
import pathlib, re, sys
from collections import Counter
VALID = re.compile(r"^bakery-[a-z0-9]+(-[a-z0-9]+)*$")
names = [name for p in pathlib.Path("src").rglob("*.js")
         for name in re.findall(r"customElements\.define\(\s*['\"]([^'\"]+)", p.read_text())]
bad = [n for n in names if not VALID.match(n)] + [n for n, c in Counter(names).items() if c > 1]
print("\n".join(f"FAIL {name} breaks the prefix or is defined twice" for name in bad))
sys.exit(1 if bad else 0)
```

### HTML example

```html
<bakery-basket class="bakery-basket" aria-live="polite"></bakery-basket>
```

## Sources

- [HTML Standard on valid custom element names](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name)
- [HTML Standard on customElements.define](https://html.spec.whatwg.org/multipage/custom-elements.html#dom-customelementregistry-define)

## Related rules

- [Give each component exactly one stylesheet](https://agentwranglers.se/playbook/html-css/structure-and-files/component-stylesheet) in HTML and CSS

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/custom-element-names">Agent Wranglers HTML and CSS playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Clone markup that scripts add from a template element](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/template-element)
- [HTML structure and reuse](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse)
