Browser Modules

Basic Example

If you have written a bit of JS for your app that has an external dependency, you’ll likely want to bundle your script with its dependency.

Let’s use Algolia’s autocomplete as an example.

import { autocomplete } from '@algolia/autocomplete-js'

addEventListener('DOMContentLoaded', () => {
    container: '#autocomplete',
    // ...

Assuming this file is located at /utils/autocomplete.mjs, update your .arc file (adding the @bundles line if needed) with this entry:

autocomplete '/utils/autocomplete.mjs'

The bundled asset will now be available at /_public/bundles/autocomplete.mjs and can be imported or referenced in a script tag.

<script type="module" src="/_public/bundles/autocomplete.mjs">

Multi-file Source to Single Bundle

If your project grows to a certain size, it is beneficial to extract Web Component definitions (that is JS classes that extend HTMLElement) from their source in /app/elements/ into a common place.

For this example, we’ll create an arbitrary directory outside of app/ called “components/” and place a couple classes there with an index file:

├── .arc
├── app/
└── components/
    ├── todo-list.mjs
    ├── todo-item.mjs
    └── index.mjs

The index file works as a manifest, exporting all requirements:

export { default as TodoList } from './todo-list.mjs'
export { default as TodoItem } from './todo-item.mjs'

We’ll update our .arc file, adding @bundles if it’s not already present:

todos '/components/index.mjs'

These classes can now be imported as needed.

import { TodoList, TodoItem } from '/_public/bundles/todos.mjs'

Bundling External Modules

You may want to install an external dependency for use in the browser. Enhance @bundles handles this, as well.

Example: wc-toast

wc-toast provides a nice custom element definition and accompanying API for creating alert messages in an application. We’ll install it as a project dependency:

npm i wc-toast

The wc-toast project ships with a nice entry point for a bundle. We will bundle and expose wc-toast’s main index file as “wc-toast” by updating .arc with:

wc-toast './node_modules/wc-toast/src/index.js'

The name “wc-toast” can be anything you’d like, but we prefer to stick as close to the source library’s name as possible.

Now, we’re able to import bundle, or a named export in this case, from the /_public/bundles/ endpoint:

import { toast } from '/_public/bundles/wc-toast.mjs'

TypeScript Web Components

With the @bundles feature, you can write browser code with TypeScript. It is automatically converted to browser compatible JavaScript and served to the client.

Example .ts Definition

Imagine we have a simple Web Component definition that lives in a components/ folder in our project root:

export class TodoItem extends HTMLElement {
  public label: string;
  public completed: boolean;
  checkbox: HTMLInputElement | null;

  constructor() {

    this.label = this.getAttribute("label") || "";
    this.completed = typeof this.getAttribute("completed") === "string";
    this.checkbox = this.querySelector("input");

  public static get observedAttributes(): string[] {
    return ["label", "completed"];

customElements.define("todo-item", TodoItem);

This example doesn’t do a whole lot yet, but it’s a good starting place. To have our todo-item.ts transpiled and served to our front end, just give it a name and a path in the project’s .arc file:

todo-item /components/todo-item.ts

Now it can be imported from your custom element or with a script tag:

import TodoItem from '/_public/bundles/todo-item.mjs'
<script type="module" src="/_public/bundles/todo-item.mjs">

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!