Angular templates, edited by markup match — and what it refuses
Click an element in your running Angular app and PortBay writes the change into the .html template that holds it. Angular templates are not stamped, so this is the text-matching lane — precise about what it can do and explicit about what it refuses. Pro, early access, opt-in.
Can I edit Angular component templates visually?
Angular compiles its templates through the CLI's own builder rather than a dev server a third-party tool can hand a plugin to, so nothing can give an Angular element a precise source coordinate the way it can on Vite. What remains possible is matching the element's markup back to the template file holding it. PortBay does exactly that: click an element in your running app, change its text, classes or an attribute, and the edit is written into the .html template by locating that markup in your source. Structural edits are refused rather than guessed, and a class bound through [class] or [ngClass] cannot be targeted, because the rendered value is not in the file. Page title and description write into src/index.html, which really is the shell every route renders through. The editor is Pro, in early access, and absent from the open-source build.
Verified against the product, 2026-09-05.
An Angular app on the matching lane
PortBay runs your Angular project at its own .test URL with trusted HTTPS and dispatches board cards into it. The visual editor edits that same running app in your real browser — one live page, not a multi-frame design canvas.
Your first Angular template edit
Four steps. There is nothing to install in your project on this lane, because there is nothing PortBay can install that would help — see the section below for why.
- Install PortBay and add your Angular project
- Turn the visual editor on
- Open Edit in browser
- Switch to Edit and change something
Install PortBay and add your Angular project
Homebrew installs the app and the bundled portbay CLI. Add the project folder and PortBay recognises Angular from @angular/core in your package.json, runs your dev server, and serves it at its own .test hostname over trusted HTTPS.
brew tap portbay-app/portbay && brew install --cask portbayTurn the visual editor on
It ships to Pro under early access and is off by default. Sign in to Pro, then flip the Early Access toggle. The open-source build does not include the editor at all — it is not compiled in.
Settings › Account › Early AccessOpen Edit in browser
The project's Visual editing section has one button. It opens your normal browser at your normal .test URL with the edit bar docked at the top, booting in Preview mode where the page and its router stay fully interactive — which matters more on Angular than on a static stack, because you often need to navigate to the route you want before editing it.
https://myapp.testSwitch to Edit and change something
Double-click text to type into the live page, or use the right rail for classes and attributes. On Save, PortBay finds that markup in your component templates and rewrites it. Anything it cannot resolve to exactly one place is put to you before it writes, rather than being applied to the first match.
What writes, and what Angular puts out of reach
Angular's own features are the limit here, not a missing PortBay feature. A value the framework computes at runtime is not in your template file, so there is nothing in the file to change.
The four write lanes — text, attribute, class and page settings — are all proven against a real Angular fixture in PortBay's cross-stack test, which edits src/app/app.component.html and reads the changed bytes back off disk. What is missing on Angular is the precision tier, not the writing.
<!-- src/app/app.component.html --><section class="panel"> <h1 class="hero">We build boats</h1> <!-- text: writes. "We build boats" is literally in this file. class: writes. "hero" is literally in this file. --> <img src="/logo.svg" alt="Acme" /> <!-- attribute: writes. Both values are literals. --> <p [ngClass]="{ lede: isIntro }">Since 1994, in one shed.</p> <!-- class: REFUSED. The rendered class list is computed from a component field; the file contains an expression, not a class name, and rewriting the expression is not the edit you asked for. --> <li *ngFor="let boat of boats" class="row">{{ boat.name }}</li> <!-- class="row": writes. {{ boat.name }}: no. That text came from your data, not from this template. --> </section>
The pieces underneath
Visual editor
Click an element on your running site in your own browser and edit its text, classes and styles straight into the source file, across 21 stacks.
Explore →HTTPS + .test domains
https://name.test per project: mkcert certificates, managed local DNS and a bundled Caddy edge, with expiry and reissue in view.
Explore →Asked before downloading
How does PortBay know my project is Angular?
By @angular/core in your package.json dependencies. That is the whole signal — no config file to add, no framework field to set, and no directory scan. Everything downstream, including which write lane the project gets and where its page title lives, follows from that one detection.
Does PortBay stamp Angular templates with source coordinates?
No, and this is the honest limit of the Angular lane. PortBay adds source-location stamping only to dev servers it launches itself through Vite or Astro, and the Angular CLI's builder is neither. So an Angular element carries no data-pb-loc, and edits are resolved by finding that markup in your template files instead of by following a coordinate. PortBay tells you which mode a project is in rather than degrading quietly.
If Angular templates aren't stamped, what does PortBay's visual editor write?
Text, class and attribute edits, plus page settings — all four write lanes. That is tested rather than claimed: PortBay's cross-stack guard builds a real Angular fixture project, drives each lane against it, and reads the changed bytes back off disk from src/app/app.component.html. A lane that quietly did nothing is the exact failure that test exists to catch, so a silent no-op cannot ship.
What can't it edit in an Angular template?
Three things, all for the same reason — the value you see is not in the file. A class bound with [class] or [ngClass] is computed from a component field, so there is no class name in the template to change. Interpolated text inside {{ }} came from your data. And structural edits — moving, wrapping or converting an element — are refused rather than guessed, because without a coordinate there is no way to be sure which occurrence you meant.
Where does PortBay write the page title and meta description in Angular?
Into src/index.html. Angular is unusual among the frameworks here in having a genuinely static document shell: src/index.html really is the head every route renders through, so patching it takes effect rather than being overwritten on the next render. PortBay reports it as site scope in the panel, so you can see that a title written there applies to every route rather than to the one you happen to be looking at.
Can it edit elements from Angular Material or another component library?
Only where the markup is yours. A library's own internal template is not in your source tree, so there is nothing to match and PortBay says so rather than editing something else. Attributes and classes you put on the library's component in your own template are in your file and do resolve normally.
Is PortBay's visual editor free for Angular, and does it work on a shared URL?
PortBay's visual editor is a Pro feature, in early access behind an opt-in toggle in Settings, and it is not compiled into the open-source build. It refuses to run while the project is shared over a public tunnel — stop the share first — and the edit bar works only on local .test hosts. Running your Angular dev server on a real .test domain with trusted HTTPS is free.

Give your projects and your agents a real local home.
Download for macOSFree & open source · macOS 11+ on Apple Silicon · Pro from $10/mo