Elements are the reusable building blocks of your Enhance application. They are pure functions authored as single-file components and can be static or update dynamically to state changes. Elements live in the app/elements/ folder in the Enhance starter project.


The file name of your element will be the tag name you author with. Meaning app/elements/my-message.mjs will be authored as <my-message></my-message> in your HTML page. Enhance elements are HTML custom elements, so they require two or more words separated by a dash.

app/elements/my-message → <my-message></my-message>
app/elements/my-link → <my-link></my-link>

When a project grows to include more elements than can comfortably fit in a single folder, they can be divided into sub-directories inside app/elements/. The folder name becomes part of the custom element tag name:

app/elements/blog/comment → <blog-comment></blog-comment>
app/elements/blog/comment-form → <blog-comment-form></blog-comment-form>


Elements are pure functions meaning given the same input they return the same output every single time. Your element function will be passed an arguments object containing an html render function that is used to expand nested custom elements.

export default function MyHeader({ html }) {
  return html`
      <my-link href="/about"></my-link>


Your element function is also passed a state object in the arguments object. This state object is comprised of attrs; an object of key value pairs representing the attributes added to your custom element tag and store; an object containing application state.

export default function MyHeader({ html, state }) {
  const { attrs, store } = state
  const { heading = 'Default' } = attrs
  const href = store.aboutPath

  return html`
      <my-link href="${href}"></my-link>

Community Resources

Visit Enhance on GitHub.
Join our Discord server to chat about development and get help from the community.
Follow Enhance in the Fediverse. We're huge fans of the IndieWeb!