Repository navigation
Releases: BernardoGiordano/srl
Release list
1.0.0
Introducing srl
I'm excited to share srl with the frontend community. srl is a reactive framework for single-page applications, built on Lit web components and signals. It needs no build step while you develop. You write JavaScript, HTML templates and CSS, and the browser runs those files as they are. If you've worked with modern Angular, the syntax and the project structure will feel familiar from your first component.
Version 1.0.0 is on npm today. You can see it at work in the live demo, a small CRM application that ships the unminified application source on purpose, and the blog you're reading runs on srl too.
No build while you develop
srl started from conversations with coworkers about prototyping faster. Most frontend stacks put a compiler between your editor and your browser, so every save waits while TypeScript, templates and stylesheets turn into something the browser understands. On a big project you pay that wait hundreds of times a day.
Browsers don't need that step anymore. They load ES modules natively, and import maps let them resolve names like lit or @srljs/core without a bundler. srl relies on both. The development server hands your source files to the browser unchanged, and Lit and the signals library arrive through the same import map. Tailwind's browser compiler styles the page during development, so there's no CSS build either.
You keep your types. Components are plain JavaScript with JSDoc annotations, and TypeScript checks them without emitting a single file. When you're ready to deploy, srl build produces minified, hash-named assets and compiles Tailwind into a static stylesheet. The build exists for production only.
Familiar if you know Angular
srl borrows Angular's vocabulary on purpose. A component is a class plus a sibling HTML template, and the template uses the bindings Angular developers already know.
import { defineComponent, signal, SignalElement } from '@srljs/core';
export class CounterButton extends SignalElement {
count = signal(0);
increment() {
this.count.value += 1;
}
}
await defineComponent({
tag: 'counter-button',
element: CounterButton,
module: import.meta.url,
});<button (click)="increment()">Clicked {{ count }} times</button>
<p *if="count >= 10">That's a lot of clicks.</p>There's no change detection to configure. A component renders again when a signal its template reads changes, and Lit updates only the bindings whose values moved. It works like signal-based Angular with OnPush on every component, and you never have to think about it.
| Angular | srl |
|---|---|
signal, computed, effect |
Same names |
OnPush change detection |
Automatic |
*ngIf, *ngFor with trackBy |
*if and *else, *for with key: |
inject() and providers |
inject(), provide() and typed tokens |
FormGroup, FormControl, Validators |
group(), field() and built-in validators |
ng new, ng g c, ng serve, ng build |
srl new, srl g c, srl serve, srl build |
| Module Federation | An import map plus app.manifest.json |
The full mapping also covers lifecycle hooks, content projection, outlets and route guards.
What's in the box
srl ships the pieces a business application usually pulls from separate libraries.
- Signals come with
computed,effectandbatch, plusresource()for async data that tracks loading and failure and cancels its request when the component goes away. - A root injector provides services through typed tokens, and an HTTP client talks to your API.
- The router handles route parameters, wildcards, guards, lazy-loaded routes and nested layouts. A failed navigation puts the previous view back.
- Reactive forms cover fields, groups and arrays, with sync and async validators, rules that span several fields, and disabled state.
- Localization switches language at runtime without a reload. It picks plural forms, falls back message by message, formats numbers, currencies and dates for the active locale, and supports right-to-left languages.
AuthSessionhandles sign-in, session restore, token refresh and coordination between browser tabs. Route guards can require a session or a specific scope.- Micro-frontends load as separately deployed remotes. Each remote declares itself in
app.manifest.json, and the shell gives it only the API paths and permissions it was granted. - Themes switch between light, dark, the system setting and your own palettes. UI preferences such as table columns and sidebar state persist through one storage API you can replace.
- Component tests run in a real browser against the same source files, through a
@web/test-runnerpreset thatsrl newsets up for you.
Checked before it runs
Skipping the compiler doesn't mean skipping the checks. srl check runs all of them in one pass.
- TypeScript checks your JSDoc-typed JavaScript.
- The template checker types every binding against its component class, including signals, loop variables and
$event. - The same checker reports unknown elements and components a template uses without importing them.
- The import map check confirms the map still matches the installed library, because a mismatch shows up as a blank page.
- The message check finds missing translations, unused keys and placeholders a call forgets to pass.
Every finding has a stable code and a file position, and srl check --json hands the list to CI or any other tool.
The same checker powers a language server. It gives you completion, hover, go to definition, find references, tag rename across templates, and a quick fix that adds a missing component import. It understands inline Lit templates in JavaScript files as well. The repository includes plugins for VS Code and WebStorm, and both will reach the extension marketplaces in the next few days. Any editor with an LSP client can run srl language-server directly.
Secure by default
Templates escape or sanitize each value for the place it lands in the DOM, and an application can enforce Trusted Types through its Content Security Policy. The production import map pins an integrity hash for every file the page loads, so the browser refuses a file whose bytes have changed. The build also writes a strict CSP made of hashes, and an artifact report that lists every file with its size and hash.
Fast, and measured
srl records its performance numbers in the repository, and a benchmark gate fails when a change pushes them past their budgets. The figures below come from an Apple M3 running Chrome.
| Workload | Median |
|---|---|
| Cold start of the demo, served as source, to the first routed view | 67 ms |
| Update one binding among 200 | under 0.1 ms |
| Reverse a keyed list of 1,000 rows | 1.1 ms |
| Mount a 10,000-row table with 50 rows visible | 2.8 ms |
| Sort 10,000 table rows in the browser | 20.6 ms |
| Production build of the whole demo, brotli-compressed | 161 KB |
The built demo also passes the same keyboard-driven user journey on Chromium, Firefox and WebKit, under its production CSP.
Made for coding agents too
I wanted srl to work well for coding agents as well as for people. Both packages ship the full documentation for their version, with an llms.txt index at the package root, so an agent reads docs that match the code you installed. srl new writes an AGENTS.md into every project. srl mcp starts a Model Context Protocol server that lets an agent run the checks, list your components and read the docs. The stable diagnostic codes help as well, since an agent can look up exactly what a finding means with srl check --codes.
What ships in 1.0.0
| Package | Contents |
|---|---|
@srljs/core |
The runtime library and the component collection |
@srljs/cli |
Scaffolding, development server, checks, language server, MCP server and production build |
The two packages always ship at the same version, and srl new pins them together.
The component collection is small for now, and it will grow over the next releases. It already includes an application shell with sidebar, top bar and breadcrumbs, menus and dialogs, a combobox, a date range picker and form fields. It also has a filter bar that shows active filters as chips, and a data table with client or server paging, sorting, row selection, sticky, resizable and reorderable columns, and virtual scrolling. The components handle behavior and accessibility, and you style them with your own classes or the default theme.
Try it
You need Node.js 22 or later.
npx @srljs/cli@1.0.0 new my-app
cd my-app
npm install
npm run devnpm run check runs every check, npm run build produces the production build, and npx --no-install srl g c user-card adds a component. srl is MIT licensed, and the code, the guides and the issue tracker live on GitHub.
Why "srl"?
In Italy, large companies usually register as an S.p.A. (società per azioni), and smaller ones as an S.r.l. (società a responsabilità limitata). Frontend developers read SPA as single-page application. A lighter way to build an SPA had to be called srl. The letters also stand for "source runs live", which is exactly what the framework does.