Note: when React, Vue, and Angular each require their own UI library, code gets duplicated — teams spend up to 30% of time rewriting the same buttons and modals. We solved this problem with Stencil: a compiler that generates native Web Components and wrappers for all popular frameworks from a single TypeScript codebase. Over 5 years, we've created more than 20 UI libraries, including a fintech app project with 15 components — used in React, Vue, and Angular without modifications, cutting new feature implementation time by 40%. Another example: an e‑commerce platform UI kit of 25 components. After integrating into three services, the team halved interface approval time. Each component is covered by unit and E2E tests, eliminating integration bugs. Our clients save from 30% of their UI development budget and get a stable library for the entire application lifecycle.
Problems We Solve
Code Fragmentation
Without a unified library, each project writes its own buttons, inputs, and modals. The result is bloated code, inconsistent UX, and complex maintenance. According to our data, companies spend up to 30% of development time duplicating UI components, leading to a 20–30% budget overrun.
Integration Complexity
Native Web Components don't always work correctly with React (event bubbling, prop types) or Angular (two-way binding, forms). Stencil generates framework-specific wrappers that solve these problems. Developers don't need to write adapters manually — this saves up to 2 weeks on initial integration and reduces error risks.
Performance
Stencil compiles components into native Custom Elements with minimal overhead. Unlike Lit, it additionally creates tree-shakeable builds and can work with SSR. In tests, bundle size is reduced by 60% compared to traditional framework libraries.
How We Do It: Diving into Stencil
Project Architecture
We start by initializing a Stencil project. Typical structure:
npm init stencil@latest -- --type component cd my-library && npm install The project is organized as a monorepo with packages for each framework.
Component: ui-button Example
We create a component using @Component, @Prop, @Event decorators. It uses TSX like in React. Important: enabling Shadow DOM (shadow: true) for style isolation.
// ui-button.tsx import { Component, h, Prop, Event, EventEmitter } from '@stencil/core'; @Component({ tag: 'ui-button', styleUrl: 'ui-button.css', shadow: true, }) export class UiButton { @Prop() variant: 'primary' | 'secondary' = 'primary'; @Prop() disabled = false; @Event() uiClick!: EventEmitter<MouseEvent>; render() { return ( <button class={`btn btn--${this.variant}`} disabled={this.disabled} onClick={e => this.uiClick.emit(e)} > <slot /> </button> ); } } Configuration: Multiple Output Targets
The key feature of the tool: one code, many builds. We configure stencil.config.ts to generate:
- Native Web Components (dist)
- Tree-shakeable custom elements (dist-custom-elements)
- React wrappers
- Vue wrappers
- Angular wrappers
// stencil.config.ts import { Config } from '@stencil/core'; import { reactOutputTarget } from '@stencil/react-output-target'; import { vueOutputTarget } from '@stencil/vue-output-target'; import { angularOutputTarget } from '@stencil/angular-output-target'; export const config: Config = { outputTargets: [ { type: 'dist', esmLoaderPath: '../loader' }, { type: 'dist-custom-elements' }, reactOutputTarget({ componentCorePackage: 'core', proxiesFile: '../react/src/components.ts' }), vueOutputTarget({ componentCorePackage: 'core', proxiesFile: '../vue/src/components.ts' }), angularOutputTarget({ componentCorePackage: 'core', directivesProxyFile: '../angular/src/proxies.ts' }), { type: 'docs-readme' }, ], }; After building, each framework package contains ready-made typed components. They can be imported as usual. The library works in React, Vue, Angular, and even plain HTML — without additional configuration.
Work Process
- Analysis — determine the set of components, design tokens, a11y requirements.
- Design — architect components, props, events.
- Implementation — write components in Stencil, style, add tests (Jest + Puppeteer).
- Integration — generate wrappers for target frameworks, test in their environments.
- Documentation — create Storybook and automatic documentation from Stencil.
- Publication — set up CI/CD on GitHub Actions, publish npm packages.
What's Included
- Source code of components in Stencil (TypeScript, CSS)
- Builds for React, Vue, Angular (if required)
- Unit and E2E tests (Jest + Puppeteer)
- Documentation (README, Storybook, JSDoc)
- CI/CD configuration (GitHub Actions, npm publication)
- 2 weeks of free support after completion
Timelines
| Library size | Timeline |
|---|---|
| 5–8 components (React only) | 2–3 weeks |
| 10–20 components (React + Vue + Angular) | 6–8 weeks |
| Full UI kit (30+ components) | 8–12 weeks |
Cost is calculated individually — depends on component complexity, number of frameworks, and testing needs.
Why Stencil Is Better Than Lit for Enterprise Libraries?
Stencil provides ready-made output targets for popular frameworks. This cuts integration time by 2–3 times. Additionally, it generates documentation and TypeScript types automatically. Our experience shows that Stencil projects require 40% less time for cross-framework compatibility maintenance.
How Stencil Solves Hydration in React?
When using native Web Components in React, hydration errors occur due to server-client render mismatch. Stencil generates React wrappers that correctly handle events and attributes, eliminating hydration issues.
Example usage in React
import { UiButton } from 'my-ui-react'; function App() { return <UiButton variant="primary" onUiClick={e => console.log(e.detail)}>Click me</UiButton>; } Comparison: Stencil vs Lit
| Parameter | Stencil | Lit |
|---|---|---|
| Framework wrapper generation | Built-in (React, Vue, Angular) | Requires manual implementation |
| Prop typing | Automatic from TSX | Manual via generics |
| Tree-shaking | Yes (dist-custom-elements) | Partial |
| Documentation | Auto-generated from components | Separate tool |
Order a turnkey library development. Get a consultation on architecture. Contact us for a project assessment.







