Litro vs Enhance
Enhance (by Begin.dev) and Litro are the two main frameworks for server-rendering web components without React or Vue. They share the same fundamental goal and differ significantly in how they get there.
What They Share
- Server-first web components — HTML is rendered on the server before any JavaScript runs
- No React, Vue, or Svelte in the component model
- Progressive enhancement — pages work without JavaScript
- TypeScript support
- Standard Custom Elements at runtime
Feature Comparison
| Feature | Enhance | Litro |
|---|---|---|
| Component format | HTML-first SFCs | Lit / FAST / Elena (pluggable) |
| Server rendering | ✓ | ✓ DSD (Lit/FAST) or light DOM (Elena) |
| Client-side routing | — (MPA by default) | ✓ LitroRouter |
| Server engine | Begin cloud / Arc | Nitro (Vercel, Cloudflare, AWS…) |
| Deployment flexibility | Begin-centric | All Nitro presets |
| JavaScript by default | Opt-in | Opt-in |
| Lit ecosystem (Shoelace, etc.) | — | ✓ |
| TypeScript | Partial | ✓ Full |
| SSG | ✓ | ✓ |
| File-based routing | ✓ | ✓ |
Component Authoring
Enhance uses its own HTML-first Single File Component format. Components are pure
functions that return HTML strings, with optional client-side enhancement via
<script> tags. This is intentionally minimal — no library layer.
Litro supports three web component frameworks via its adapter system: Lit (default), FAST Element, and Elena. Lit and FAST use Shadow DOM with Declarative Shadow DOM SSR; Elena uses light DOM with direct rendering — closer to Enhance's philosophy but with a full framework runtime. All three use the same routing, data fetching, and deployment infrastructure.
Enhance — app/elements/my-counter.mjs
export default function MyCounter({
html,
state: { attrs }
}) {
const count = attrs.count ?? 0;
return html`
<style>
button { padding: 0.5rem 1rem; }
</style>
<button>Count: ${count}</button>
<script type="module">
// client enhancement here
</script>
`;
}
Litro — Lit component
import { html, css, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('my-counter')
class Counter extends LitElement {
static styles = css`
button { padding: 0.5rem 1rem; }
`;
static override properties = {
_count: { state: true },
};
_count = 0;
render() {
return html`
<button @click=${() => this._count++}>
Count: ${this._count}
</button>
`;
}
}
Server and Deployment
Enhance is built for Begin's cloud platform and Arc (the AWS infrastructure-as-code tool Begin maintains). It works on AWS Lambda natively and has first-party Begin support. Other deployment targets require more manual configuration.
Litro uses Nitro, which has first-party deployment presets for Vercel, Cloudflare Workers, AWS Lambda, Deno Deploy, Netlify, Bun, and more. These are the same presets used by Nuxt.js in production across thousands of sites.
Client-Side Routing
Enhance is primarily a multi-page application (MPA) framework. Navigation triggers full
page loads by default. Client-side interactivity is added progressively via <script>
tags in component files. There's no built-in SPA router.
Litro includes LitroRouter — a built-in client-side router built on the
native URLPattern API. Navigation between routes is SPA-style with no full page reload.
Use <litro-link> for SPA navigation; plain <a> tags
do full page reloads.
When Enhance Fits Well
Enhance is worth considering if you want:
- Zero JavaScript by default — pages are static HTML, enhancement is strictly opt-in
- The simplest possible component authoring model (no library dependency)
- A Begin/Arc-centric deployment model (deep AWS integration out of the box)
- Minimal abstraction — components are functions, not classes
When to Choose Litro
Litro is a better fit if you want:
- Framework choice — Lit, FAST Element, or Elena via the
--adapterflag - Client-side routing (SPA-style navigation without full page reloads)
- The Lit ecosystem — Shoelace,
@lit/context, community components - Light DOM SSR via the Elena adapter — similar to Enhance's philosophy, with Nitro's deployment story
- Nitro's deployment flexibility (Vercel, Cloudflare Workers, and more)
- Migrating from Nuxt.js — the server layer is identical
- Full TypeScript across the component model
Litro