# Packaging app in a web component

**URL:** <https://discourse.aurelia.io/t/packaging-app-in-a-web-component/6464>\
**Category:** vNext\
**Created:** [July 1, 2025, 10:12am UTC](https://discourse.aurelia.io/t/packaging-app-in-a-web-component/6464 "2025-07-01T10:12:58Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ivan](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/ivan/32/2022_2.png) [@ivan](https://discourse.aurelia.io/u/ivan)\
**Post date:** [July 1, 2025, 10:12am UTC](https://discourse.aurelia.io/t/packaging-app-in-a-web-component/6464/1 "2025-07-01T10:12:58Z")

</div>

Just doing some experimenting and trying to package an aurelia app in a web component.

e.g.

```auto
import Aurelia from 'aurelia'
import { MyApp } from './my-app'

export default class MyWebComponentApp extends HTMLElement {
  constructor() {
    super()

    this.attachShadow({ mode: 'open' })

    this.shadowRoot!.innerHTML = '<my-app></my-app>'
  }

  async connectedCallback() {
    const host = this.shadowRoot!.querySelector('my-app') as HTMLElement

    Aurelia
      .app({ host: host, component: MyApp })
      .start()
  }
}

customElements.define('my-web-component-app', MyWebComponentApp)

```

Seems to be working, but aurelia adds stylesheets to the `head` tag of the page, rather than to the shadow root. Anyay to overcome this?

 ![image](https://canada1.discourse-cdn.com/flex027/uploads/aurelia/original/2X/7/7f400f85a33d6f4702689a2e1e328b34d468e7ba.png)

Here is a repo to test it out: [GitHub - ivanbacher/root-web-component](https://github.com/ivanbacher/root-web-component)

---

<div class="post-metadata">

**Author:** ![dwaynecharrington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/dwaynecharrington/32/11_2.png) [@dwaynecharrington](https://discourse.aurelia.io/u/dwaynecharrington)\
**Post date:** [July 4, 2025, 11:27pm UTC](https://discourse.aurelia.io/t/packaging-app-in-a-web-component/6464/2 "2025-07-04T23:27:26Z")

</div>

This is because Aurelia doesn’t know you’re instantiating the app inside of a web component. It won’t traverse the DOM and determine if the root is shadow or not.

You’ll need to make your my-app component a shadow component:

```auto
// my-app.ts
import { customElement, shadowCSS, useShadowDOM } from 'aurelia';
import template from './my-app.html';
import styles from './my-app.css';

@useShadowDOM({ mode: 'open' })
@customElement({
  name: 'my-app',
  template,
  dependencies: [shadowCSS(styles)]
})
export class MyApp {
  message = 'Hello World!';
}

```

---

<div class="post-metadata">

**Author:** ![ivan](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/ivan/32/2022_2.png) [@ivan](https://discourse.aurelia.io/u/ivan)\
**Post date:** [July 7, 2025, 8:38am UTC](https://discourse.aurelia.io/t/packaging-app-in-a-web-component/6464/3 "2025-07-07T08:38:46Z")

</div>

Thanks for the info @dwaynecharrington. I gave it a go, and this brought up some more questions. Maybe you can answer them 🙂.

I updated `my-app` to the version below.

```auto
import { customElement, shadowCSS, useShadowDOM } from 'aurelia'
import template from './my-app.html'
import styles from './my-app.css?raw'

import { ComponentOne } from './components/component-one'
import { ComponentTwo } from './components/component-two'

@customElement({
  name: 'my-app',
  template,
  dependencies: [shadowCSS(styles), ComponentOne, ComponentTwo]
})

@useShadowDOM({ mode: 'open' })

export class MyApp {
  public message = 'Hello World!'
}

```

This is working, but `my-app.css` is still being added to the `head` tag of the page. Is this the intended behaviour?

I also need to register all additional components that `my-app` uses and the `css` of these components gets added to the `head` tag, but this is probably because I need to also make them shadow components?

Also this fail’s to build in Vite due to a HTML parsing error ( this might be more of a Vite issue?)

```auto
[vite:build-html] Unable to parse HTML; parse5 error code unexpected-character-in-unquoted-attribute-value
 at /Users/.../Desktop/root-web-component/src/my-app.html:6:44

export const name = "my-app";
export const template = "\n\n\n<div class=\"message\">${message}</div>\n\n<component-one></component-one>\n<component-two></component-two>";

```

I updated the repo: [GitHub - ivanbacher/root-web-component](https://github.com/ivanbacher/root-web-component)

This might just be an stupid use case. Feel free to let me know if this sis the case. Thanks for your time.
