Traditional VUE development requires creating a full CreateApp() instance and manually calling .mount('#some-id') on a specific DOM container for every place you want to use VUE. This typically has to be done in the bundled code, meaning every time you want to add new VUE instances, you have to re-build the entire project. Not fun and definitely not client friendly. This approach works well for simple applications but quickly becomes cumbersome when you want to use it in multiple spots, or on server-rendered content. You end up writing boilerplate setup code repeatedly, managing separate app instances, and worrying about mount order or conflicts between them. A far more elegant solution is to leverage the browsers customElements API. Instead of mounting apps, you define a reusable custom HTML tag like <pockets-app> that automatically apply full VUE behavior to its content the moment they appear in the DOM.
The magic happens by using the custom element’s connectedCallback method. When fired, it internally creates a VUE app instance on the element, using its innerHTML as a template. You write the inner VUE app logic once, adding any components/directives that you want available when you register it with customElements.define() and you're done. To use it you simply drop <pockets-app> tags anywhere in your HTML. No manual JavaScript orchestration; just declarative HTML that “wakes up” into a fully powered VUE driven app.
This pattern is dramatically more flexible than the classic root-app approach. You can sprinkle dozens of independent VUE powered snippets across a page without having to manage multiple app instances or worrying about global pollution. Each custom element is self-contained, lazy-loads its own bundle if you split code, and composes naturally with vanilla HTML. It eliminates the “one big app or nothing” mindset, making progressive enhancement trivial and allowing designers or backend teams to add interactive sections by simply using a custom tag and some HTML.
Creating the custom element
First we create a basic function that can be re-used to create different custom elements. Useful if you want to have different tags that have different components/directives/data attached to them.
First create a file:
And to use it, you'd put this somewhere in your project. For example, in your projects root app file:
Now you can use <pockets-app> anywhere and use any directives/components registered to it within that element. For example:
Final Thoughts...
By embracing custom elements that automatically bootstrap VUE, you break free from the rigid “one root app to rule them all” model that has dominated frontend development for years. No more hunting for the perfect #app container. No more juggling multiple createApp() calls, and no more fighting mount timing issues when content arrives from a CMS, a design system, or a legacy backend. Instead, every <pockets-app> becomes a self-contained, instantly reactive VUE island that lives wherever you place it; inside a WordPress widget, a static HTML snippet, a marketing landing page, or even alongside React or vanilla components.
This approach doesn’t just reduce boilerplate; it fundamentally changes how teams collaborate. Designers can drop interactive elements into templates without touching JavaScript. Backend developers can render VUE powered sections on the server and watch them hydrate seamlessly. Frontend engineers ship reusable widgets that are truly portable across projects and frameworks. The result is cleaner code, faster iteration, and a dramatically more flexible architecture; exactly what modern hybrid web development demands.
