https://github.com/giacomo/elements-template
A modern, opinionated starter kit for building **Custom Web Components** (Web Components / Custom Elements) powered by **Angular 21**, **Tailwind CSS v4**, and **Vitest** — ready to drop into any web page or framework.
https://github.com/giacomo/elements-template
Last synced: about 17 hours ago
JSON representation
A modern, opinionated starter kit for building **Custom Web Components** (Web Components / Custom Elements) powered by **Angular 21**, **Tailwind CSS v4**, and **Vitest** — ready to drop into any web page or framework.
- Host: GitHub
- URL: https://github.com/giacomo/elements-template
- Owner: giacomo
- Created: 2026-05-13T06:37:52.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-13T06:39:00.000Z (about 1 month ago)
- Last Synced: 2026-06-01T10:04:04.540Z (17 days ago)
- Language: TypeScript
- Size: 32.4 MB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-angular - elements-template - A modern, opinionated starter kit for building custom Web Components powered by Angular 21, Tailwind CSS v4, and Vitest. (Site Templates / Free Templates)
- fucking-awesome-angular - elements-template - A modern, opinionated starter kit for building custom Web Components powered by Angular 21, Tailwind CSS v4, and Vitest. (Site Templates / Free Templates)
README
# 🧩 Angular Elements Starter Kit
> A modern, opinionated starter kit for building **Custom Web Components** (Web Components / Custom Elements) powered by **Angular 21**, **Tailwind CSS v4**, and **Vitest** — ready to drop into any web page or framework.





---
## ✨ Features
- **Dual-mode bootstrap** — runs as a normal Angular app in development; compiles to a self-contained `widget.js` in production
- **`@angular/elements`** — wraps Angular components as standard Custom Elements (``)
- **Shadow DOM encapsulation** — components are style-isolated by default via `ViewEncapsulation.ShadowDom`
- **Zoneless** — uses `provideZonelessChangeDetection()` for maximum performance and smaller bundles
- **Tailwind CSS v4** — utility-first styling included out of the box
- **Vitest** — fast unit testing via the Angular CLI Vitest builder
- **Single-file output** — `concat.js` post-build script produces one clean `dist/release/widget.js`
---
## 🔧 Prerequisites
| Tool | Version |
|------|---------|
| Node.js | ≥ 20 |
| Yarn | 4 (corepack) |
| Angular CLI | 21 (`npm i -g @angular/cli`) |
Enable Yarn 4 via Corepack (once):
```bash
corepack enable
```
---
## 🚀 Getting Started
```bash
# 1. Clone the repo
git clone https://github.com/your-org/elements-template.git
cd elements-template
# 2. Install dependencies
yarn install
# 3. Start the dev preview
yarn start
```
Open `http://localhost:4200` — you'll see the example chat widget rendered inside the Angular dev shell.
---
## 📜 Available Scripts
| Script | Description |
|--------|-------------|
| `yarn start` | Start the dev server at `localhost:4200` |
| `yarn build` | Standard Angular production build to `dist/` |
| `yarn build:wc` | **Build the Web Component** → outputs `dist/release/widget.js` |
| `yarn test` | Run unit tests with Vitest |
| `yarn watch` | Incremental dev build in watch mode |
---
## 🏗️ How It Works
### Dual-mode bootstrap (`src/main.ts`)
The entry point detects the environment flag and switches modes:
```
development → bootstrapApplication(App) full Angular dev shell
production → createApplication() +
createCustomElement(Example) registers
```
- **Dev mode** boots the standard Angular app so you can iterate fast with HMR.
- **Production mode** calls `createApplication()` (no root component) and registers each Angular component as a native Custom Element via `customElements.define()`.
### Build pipeline (`yarn build:wc`)
```
ng build --configuration production
└─ dist/elements-template/browser/main-.js
↓ concat.js
dist/release/widget.js ← single deployable file
```
`concat.js` locates the hashed main bundle and copies it to a stable, hash-free filename you can reference from any HTML page.
---
## 📦 Using the Widget
After running `yarn build:wc`, include the single output file in any HTML page — no Angular, no build tools needed on the consumer side:
```html
My Page
```
The widget is fully encapsulated — its styles live inside the Shadow DOM and will not bleed into or be affected by the host page's CSS.
---
## 🛠️ Creating a New Web Component
### 1. Generate the component
```bash
ng generate component components/my-widget
```
### 2. Enable Shadow DOM encapsulation
```typescript
// src/app/components/my-widget/my-widget.ts
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'app-my-widget',
templateUrl: './my-widget.html',
styleUrl: './my-widget.css',
encapsulation: ViewEncapsulation.ShadowDom, // ← required
})
export class MyWidget {}
```
### 3. Register it as a Custom Element (`src/main.ts`)
```typescript
import { MyWidget } from './app/components/my-widget/my-widget';
createApplication({ providers: [provideZonelessChangeDetection()] })
.then((appRef) => {
customElements.define(
'my-widget',
createCustomElement(MyWidget, { injector: appRef.injector })
);
});
```
### 4. Build & ship
```bash
yarn build:wc
# → dist/release/widget.js
```
> **Tip:** You can register multiple components from the same build by chaining additional `customElements.define()` calls inside the same `.then()` block.
---
## 🗂️ Project Structure
```
src/
├── main.ts # Dual-mode bootstrap
├── environments/
│ ├── environment.ts # production: true → Web Component mode
│ └── environment.development.ts # production: false → Dev shell mode
└── app/
├── app.ts / app.html # Dev-only shell (not part of the WC build)
└── components/
└── example/ # Sample chat widget component
├── example.ts # ViewEncapsulation.ShadowDom
├── example.html
└── example.css
concat.js # Post-build script → dist/release/widget.js
```
---
## 🔑 Key Technologies
| Technology | Role |
|------------|------|
| [Angular 21](https://angular.dev) | Component framework |
| [@angular/elements](https://angular.dev/guide/elements) | Custom Elements bridge |
| [Tailwind CSS v4](https://tailwindcss.com) | Utility-first styling |
| [Vitest](https://vitest.dev) | Unit test runner |
| [Yarn 4](https://yarnpkg.com) | Package manager |
---
## 📚 Resources
- [Angular Elements Guide](https://angular.dev/guide/elements)
- [Custom Elements (MDN)](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements)
- [Shadow DOM (MDN)](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM)
- [Angular CLI Reference](https://angular.dev/tools/cli)
- [Tailwind CSS v4 Docs](https://tailwindcss.com/docs)