A Production-Ready Web Component Starter Template

Starting a new web component from scratch usually means rebuilding the same scaffolding: test setup, build configuration, linting, CI/CD, docs, and all the rest. After building—and rebuilding—more components than I care to count, I pulled those patterns into a starter template so you can spend your time on component behavior instead of project plumbing.

The Web Component Starter Template is based on architecture and patterns I’ve refined across recent projects. It incorporates Google’s Custom Element Best Practices and advice from other web component practitioners, including the always-brilliant Dave Rupert.

What’s included

The template includes most everything you need to ship a production-ready web component:

  • Interactive setup wizard that scaffolds everything for your component.
  • Multiple import patterns supporting both auto-define and manual registration.
  • Demo pages for development, documentation, and CDN examples.
  • Code quality tools including ESLint and Prettier with sensible defaults.
  • Modern testing setup with Vitest, Happy DOM, and coverage reporting.
  • CI/CD workflows for GitHub Actions with automated testing and npm publishing.
  • Publishing ready with proper npm package configuration and OIDC support.

Quick start with interactive setup

Getting started is straightforward. If you’re a GitHub user, you can create a new repository directly from the template. Alternatively, clone it locally:

git clone https://github.com/aarongustafson/web-component-starter.git my-component
cd my-component
npm install
npm run setup

The setup wizard asks for your component name and description, then automatically:

  • Renames all files based on your component name,
  • Updates all code and configuration templates with your details,
  • Generates a proper README from the included template,
  • Cleans up all template-specific files, and
  • Initializes the git repository.

You’re left with a fully scaffolded repository, ready for you to develop your component.

Flexible import patterns

One of the key features is support for multiple registration patterns. Folks can choose what works best for them:

Manual registration for full control:

import { ComponentNameElement } from '@yourscope/component-name';

customElements.define('my-custom-name', ComponentNameElement);

Auto-define for convenience:

import '@yourscope/component-name/define.js';

Or call the helper directly:

import { defineComponentName } from '@yourscope/component-name/define.js';

defineComponentName();

The auto-define approach includes guards, so it only runs in browser environments and only when customElements is available. That keeps it safe for server-side rendered (SSR) scenarios.

Testing made easy

The template includes a comprehensive testing setup using Vitest:

import { describe, it, expect } from 'vitest';

describe('MyComponent', () => {
  it('should render', () => {
    const el = document.createElement('my-component');
    expect(el).toBeInstanceOf(HTMLElement);
  });
});

Happy DOM provides a lightweight browser environment, and the included scripts support:

  • Watch mode for development: npm test
  • Single run for CI: npm run test:run
  • Interactive UI: npm run test:ui
  • Coverage reports: npm run test:coverage

Automated publishing with OIDC

The template is configured for secure automated publishing to npm using OpenID Connect (OIDC), which is more secure than long-lived tokens. After you manually publish the first version and configure OIDC on npm, create a GitHub release and the workflow handles publishing automatically.

Manual publishing is still supported if you prefer that approach.

Following best practices

The template bakes in best practices from the start:

  • Shadow DOM with proper encapsulation
  • Custom Elements v1 API
  • Reflection of properties to attributes
  • Lifecycle callbacks used appropriately
  • Accessible patterns and ARIA support
  • Progressive enhancement approach

The included WEB-COMPONENTS-BEST-PRACTICES.md document explains the reasoning behind each pattern, making it a learning resource as well as a starter template.

Why I built this

After creating components like form-obfuscator, tabbed-interface, and several others, I kept copying and adapting the same project structure. This template captures those patterns so I—and now you—can start faster without skipping the fundamentals.

If you build something with it, I’d love to hear about it!


Webmentions

  1. @Aaron Looking good! What lead you to leverage Happy DOM as opposed to Playwright at test time?

  2. I never see these sorts of goodies until I’ve already built like 50+ components lol. Hey, but, I thought I was wrong to use vitest (and not open-wc/testing which I didn’t discover until I was too far in). Thoughts comparing the two? I’ve only been writing web components more seriously in 2025 so…
  3. front-end folks, ICYMI, this looks very smart from Aaron Gustafson. www.aaron-gustafson.com/notebook/a-w...
  4. I love that he includes an explainer on why he used certain patterns. github.com/aarongustafs...