Up front: this is my own project, so I'm not exactly neutral here ;-)
Where I'm coming from
I work completely differently than I did two or three years ago. For most of my career I wanted to write pretty much every line myself, and I was a bit proud of that. That has changed a lot. Instead of programming I now mostly write specifications and review what the AI generates. On the one hand that's great, I can turn new ideas into working software much faster than before. On the other hand there's the risk of stepping into the same traps with AI-generated code again and again.
And that's where I noticed something. Every time I started a new project, I found myself explaining the same things to the AI. This goes into a plugin. That stays out of the core. No domain logic in the shell. Please don't invent a third way of doing tabs. The AI would nod, generate something that looked right, and two days later I'd find a slightly different version of the same sidebar with a slightly different bug.
There are things I really don't want to explain over and over. A good, preferably deterministic base is getting more important, not less. I don't want to explain proven architectures from scratch every time. I'd rather build on established solutions where I can, ones the AI understands and can just use.
So for my new projects I built exactly that, and put it on GitHub as open source. Why Angular? Well, simply because I think it's a great framework and I've had a lot of good experiences with it over the last 10 years.
What it is, and what it isn't
LoomWeaver is a workbench shell for Angular. Not a component library. Think of the frame VS Code gives you: a rail on the left, sidebars, a top bar, a status bar, and in the middle tabs and panes you can split and drag around. That frame is what most workbench-style products build themselves, every time, slightly differently. LoomWeaver gives you that frame, and your own domain moves in as plugins.
The core contains zero domain logic. Even my own product UI goes through the same plugin contract a third party would use. That sounds like a purity thing, but it's actually what makes the AI part work, I'll get to that.
Twenty-seven seconds, no cuts. The rail, the panes, the palette and the status bar are the platform's. Everything inside them comes from plugins, the theme at the end included. There's a better quality version on the site.
What's in the box, out of the box:
- tab groups with drag-to-split panes, and any tab pops out into its own window
- a command palette (⌘K) and quick open (⌘P), with preview tabs and pinning
- named workspaces that remember their own arrangement
- theming from semantic tokens: bring Tailwind, bring Bootstrap, bring nothing
- i18n with namespaced composition, so two plugins can never collide on a key
- WCAG 2.1 AA accessibility the host meets and your plugins inherit
- an installable PWA with an update flow that actually works
- live state sync across windows and tabs
- save, discard or cancel when an editor closes with unsaved work
- auth-aware chrome: contributions declare the access they need, the shell reacts
- a plugin system with three trust levels, from your own in-process code to sandboxed iframes to plugins installed at runtime from a catalog
- an AG-UI adapter, so any agent speaking that standard can run your commands
And it ships no server. Settings, session and secrets are ports you implement against your own backend. That's a decision, not a gap. I already have a backend, and so do you.
Five minutes to a running product
This is the whole setup, against a fresh Angular app or the one you already have:
# a fresh Angular app, or the one you already have
ng new my-studio --style=css --ssr=false && cd my-studio
# the platform
npm install @loomweaver/shell @loomweaver/plugin-sdk @angular/cdk @jsverse/transloco \
@ng-icons/heroicons \
@angular/service-worker@$(node -p "require('@angular/core/package.json').version")
npm install -D tailwindcss @tailwindcss/postcss @tailwindcss/typography
# your product, and a first plugin already contributing to it
npx @loomweaver/cli distribution --name my-studio --title "My Studio" --out . --force
npx @loomweaver/cli weaver --id notes --command --shortcut 'mod+shift+n' --out src/notes
ng serve
The scaffold writes eleven files and deletes nothing. Your README.md stays yours. And a plugin, which I call a weaver because, well, it weaves on a loom, is a manifest and one activate():
import { Plugin } from '@loomweaver/plugin-sdk';
export const notesWeaver: Plugin = {
manifest: { id: 'notes', name: 'Notes', capabilities: ['contributions', 'ui', 'host'] },
activate(ctx) {
// ctx.registerSurface / registerCommand / registerBarItem / registerRailItem
// ctx.ui.* (dialogs, toasts, settings)
// ctx.host.* (version, update)
},
};
Capabilities are default-deny. A weaver declares what it needs, the distribution grants it, and everything else is simply not there. What a weaver hands the workbench are ordinary standalone Angular components against the router you already use. Nothing about how you write Angular changes.
The part that's actually about AI
This is the bit I care about most, and it's three things.
The contract is written down, as specs. Everything the platform guarantees lives as one specification per capability in the repo. Not as prose in a wiki, as the thing the tests are derived from. When I change behaviour, the spec changes first. That's what I meant by a deterministic base: my AI assistant doesn't have to guess how tabs work, and neither do I.
Your AI can read it directly. There's an llms.txt and an llms-full.txt on the site, and there's an MCP server. Drop this into your assistant's config and it can scaffold weavers and distributions in your own repository, with the actual contract in front of it:
{
"mcpServers": {
"loomweaver": { "command": "npx", "args": ["-y", "@loomweaver/mcp"] }
}
}
An agent can drive your product, and only as far as the user could. The workbench speaks AG-UI, the open protocol between a user-facing app and an agentic backend. You don't describe your actions a second time. A command you register with callable: true is a tool an agent is offered:
ctx.registerCommand({
id: 'invoices.export',
title: 'Export invoices',
description: 'Export the selected invoices as CSV',
arguments: [
{ name: 'range', kind: 'choice', choices: ['month', 'quarter', 'year'], required: true },
],
callable: true,
run: (_context, args) => exportInvoices(String(args?.['range'])),
});
A call from an agent comes back through the same seam a button, a shortcut and the command palette already run through. Permissions and access gating aren't checked again for agents, because they were never bypassed in the first place. If you want a confirmation before the expensive ones, there's a before hook, and it can only narrow, never widen.
No lock-in on CSS
The base layout is built with Tailwind, but you don't need it in your project. The shell ships as a pre-compiled stylesheet, the design tokens are plain CSS variables, so you can put whatever CSS framework you like next to it in its own cascade layer. For Bootstrap there's even a preset that maps the tokens onto Bootstrap's own variables, so both worlds share one palette:
npx @loomweaver/cli theme --preset bootstrap
Plugins don't have to be Angular either. A sandboxed weaver runs in its own iframe with an opaque origin, no reach into your DOM, and you can write its body in React, Vue, Svelte or plain JS. The tour above shows one.
Honest bits
It's young. It targets Angular 22 and Node 24, nothing older. It's for products that are a workbench, several things open at once, a surface other people extend. It is not for a site of plain pages, and it is not a component library, you bring your own buttons. And yes, a lot of the code was AI-assisted. What gets reviewed, tested and released is the contract in the specs, plus a nightly end-to-end suite that actually clicks through the workbench.
I'd be really happy about constructive feedback, the harsher the better. Docs and the live demo are at loomweaver.dev, the code is at github.com/yesbert/loomweaver, Apache 2.0. And if you feel like it, you're very welcome to get involved.
This article was originally published by DEV Community and written by Norbert Rosenwinkel.
Read original article on DEV Community