<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Turing's Oracle</title>
    <description>The latest articles on DEV Community by Turing's Oracle (turingsoracle).</description>
    <link>https://dev.to/turingsoracle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F9347%2F7a287c81-6a1d-486c-9c09-5d4d5640ad06.png</url>
      <title>DEV Community: Turing's Oracle</title>
      <link>https://dev.to/turingsoracle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/turingsoracle"/>
    <language>en</language>
    <item>
      <title>Agent-Safe Angular Components: Copy-Paste MCP + Skills Setup for Verified AI Development</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Thu, 04 Jun 2026 04:32:42 +0000</pubDate>
      <link>https://dev.to/turingsoracle/agent-safe-angular-components-copy-paste-mcp-skills-setup-for-verified-ai-development-32ai</link>
      <guid>https://dev.to/turingsoracle/agent-safe-angular-components-copy-paste-mcp-skills-setup-for-verified-ai-development-32ai</guid>
      <description>&lt;h2&gt;
  
  
  Angular v22 MCP + Skills Integration: Agentic Development Setup
&lt;/h2&gt;

&lt;p&gt;With Angular v22, the MCP (Model Context Protocol) server + Angular Skills stack transforms agent-assisted development from a risky proposition into a deterministic, verifiable workflow. This guide walks you through configuring your environment, setting up the right skills, and building agent-safe components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Environment Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js v20+ (&lt;code&gt;node --version&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Angular CLI v22+ (&lt;code&gt;npm install -g @angular/cli@latest&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A coding agent environment (Gemini CLI, Cursor, Claude Code, GitHub Copilot, JetBrains AI, or Windsurf)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Configure Angular MCP Server
&lt;/h3&gt;

&lt;p&gt;The Angular CLI ships with the MCP server built-in. Configure it in your agent's settings:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Gemini CLI / Cursor / Claude Code&lt;/strong&gt; (using &lt;code&gt;.gemini/settings.json&lt;/code&gt; or equivalent):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"angular-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"@angular/cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"chrome-devtools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"chrome-devtools-mcp@latest"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For JetBrains IDEs&lt;/strong&gt; (Settings → Tools → MCP):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add new server: name &lt;code&gt;angular-cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Command: &lt;code&gt;npx -y @angular/cli mcp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add second server: name &lt;code&gt;chrome-devtools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Command: &lt;code&gt;npx chrome-devtools-mcp@latest&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Test the connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @angular/cli mcp &lt;span class="nt"&gt;--health-check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a list of available tools. Common ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ng_lint&lt;/code&gt; — runs the linter on your project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_examples&lt;/code&gt; — fetches best-practice code examples&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_best_practices&lt;/code&gt; — retrieves the Angular Best Practices Guide&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_documentation&lt;/code&gt; — queries angular.dev&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev_server.wait_for_build&lt;/code&gt; — blocks until build succeeds/fails (critical for agents)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev_server.start&lt;/code&gt; — starts the dev server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev_server.stop&lt;/code&gt; — stops the dev server&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Install Angular Skills
&lt;/h3&gt;

&lt;p&gt;Skills are installed separately from MCP tools. They augment the agent's knowledge without adding token overhead to every request.&lt;/p&gt;

&lt;p&gt;Install the official Angular skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using npx skills package&lt;/span&gt;
npx @anthropic-ai/skills add &lt;span class="se"&gt;\&lt;/span&gt;
  https://github.com/angular/skills/blob/main/angular-developer/SKILL.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; angular-developer

npx @anthropic-ai/skills add &lt;span class="se"&gt;\&lt;/span&gt;
  https://github.com/angular/skills/blob/main/angular-new-app/SKILL.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; angular-new-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if your agent supports URL-based skills, reference directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/skills &lt;span class="nb"&gt;install &lt;/span&gt;https://github.com/angular/skills/blob/main/angular-developer/SKILL.md
/skills &lt;span class="nb"&gt;install &lt;/span&gt;https://github.com/angular/skills/blob/main/angular-new-app/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In your agent (Gemini CLI, etc.)&lt;/span&gt;
/skills list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see &lt;code&gt;angular-developer&lt;/code&gt; and &lt;code&gt;angular-new-app&lt;/code&gt; listed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Configure Chrome DevTools for Agents
&lt;/h3&gt;

&lt;p&gt;This gives agents visibility into your running application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx chrome-devtools-mcp@latest &lt;span class="nt"&gt;--install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx chrome-devtools-mcp@latest &lt;span class="nt"&gt;--health-check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 2: Writing Agent-Safe Components
&lt;/h2&gt;

&lt;p&gt;With MCP + Skills configured, your agent has access to build verification and browser visibility. Now write code that agents can safely modify.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 1: Exhaustive &lt;a class="mentioned-user" href="https://dev.to/switch"&gt;@switch&lt;/a&gt; with Type Safety
&lt;/h3&gt;

&lt;p&gt;Always use exhaustive &lt;a class="mentioned-user" href="https://dev.to/switch"&gt;@switch&lt;/a&gt; blocks. This prevents agents from introducing unhandled cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✓ Good: Type-safe, exhaustive union&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;VehicleStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;maintenance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;critical&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FleetDetailComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VehicleStatus&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;assertNever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unhandled status: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Template with exhaustive check --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"status-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  @switch (status()) {
    @case ('idle') {
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"badge badge-green"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Available&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    }
    @case ('transit') {
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"badge badge-blue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;In transit&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    }
    @case ('maintenance') {
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"badge badge-yellow"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Maintenance&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    }
    @case ('critical') {
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"badge badge-red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Critical&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    }
    @default {
      &lt;span class="c"&gt;&amp;lt;!-- If an agent adds a new status to the union without updating the template, this line will fail to compile --&amp;gt;&lt;/span&gt;
      {{ assertNever(status() as never) }}
    }
  }
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters&lt;/strong&gt;: If a backend team adds &lt;code&gt;'error'&lt;/code&gt; to the union without notifying frontend, the TypeScript build fails—agents can't ship broken code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 2: Signal Forms with Inline Validators
&lt;/h3&gt;

&lt;p&gt;Signal Forms provide type-safe, signal-driven form handling. Agents are far less likely to introduce validation errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceTicketComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Signal-based form&lt;/span&gt;
  &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOW&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HIGH&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CRITICAL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;assignedTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Signal-based access&lt;/span&gt;
  &lt;span class="nx"&gt;priority$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;priority&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueAsSignal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Compute UI state based on priority&lt;/span&gt;
  &lt;span class="nx"&gt;priorityClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CRITICAL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-red-600&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HIGH&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-orange-600&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-gray-600&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Agent can safely call this; form validation is enforced&lt;/span&gt;
  &lt;span class="nf"&gt;submitTicket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Safe to use form.value — it's typed and validated&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fleetService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTicket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;[formGroup]=&lt;/span&gt;&lt;span class="s"&gt;"form"&lt;/span&gt; &lt;span class="na"&gt;(submit)=&lt;/span&gt;&lt;span class="s"&gt;"submitTicket()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt;
    &lt;span class="na"&gt;formControlName=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;
    &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"priorityClass()"&lt;/span&gt;
    &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Describe the issue..."&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;formControlName=&lt;/span&gt;&lt;span class="s"&gt;"priority"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"LOW"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Low&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"MEDIUM"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Medium&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"HIGH"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;High&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"CRITICAL"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Critical&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;[disabled]=&lt;/span&gt;&lt;span class="s"&gt;"form.invalid()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters&lt;/strong&gt;: Agents can't generate invalid form values. TypeScript catches it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 3: @boundary for Risky Integrations
&lt;/h3&gt;

&lt;p&gt;When integrating third-party code or experimental features, wrap with &lt;code&gt;@boundary&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dashboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Core fleet list always renders --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;fleet-list&lt;/span&gt; &lt;span class="na"&gt;[units]=&lt;/span&gt;&lt;span class="s"&gt;"units()"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- AI diagnostics can fail without crashing the whole page --&amp;gt;&lt;/span&gt;
  @boundary {
    &lt;span class="nt"&gt;&amp;lt;ai-predictive-diagnostics&lt;/span&gt; &lt;span class="na"&gt;[selectedUnit]=&lt;/span&gt;&lt;span class="s"&gt;"selectedUnit()"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  } @catch (error) {
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"error-fallback"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Diagnostics unavailable&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{ error.message }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"retryDiagnostics()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Retry&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  }
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters&lt;/strong&gt;: When an agent writes complex AI integration code, a single bug won't crash the user's app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 4: Inline Template Functions for Transient Logic
&lt;/h3&gt;

&lt;p&gt;Keep component API clean; let agents write inline handlers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- ✓ Inline handler — close to its usage --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; 
  &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"vehicles.update(v =&amp;gt; v.filter(item =&amp;gt; item.id !== vehicleId))"&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn-danger"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Remove from fleet
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- ✗ Avoid exposing every handler as a method --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- &amp;lt;button (click)="removeVehicle(vehicleId)"&amp;gt;Remove&amp;lt;/button&amp;gt; --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the component API surface minimal and lets agents see the full handler intent inline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: Agent Workflows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Workflow 1: Scaffold a Component (with MCP Verification)
&lt;/h3&gt;

&lt;p&gt;Tell your agent: &lt;em&gt;"Create a ServiceTicketForm component using Angular skills. Use signal forms, include an @boundary for the AI priority analyzer, and run the build to verify."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The agent will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Call &lt;code&gt;get_best_practices&lt;/code&gt; to fetch Signal Forms patterns.&lt;/li&gt;
&lt;li&gt;Scaffold the component with &lt;code&gt;ng generate component&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Implement inline validators using the skill guidance.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;dev_server.wait_for_build&lt;/code&gt; to verify compilation.&lt;/li&gt;
&lt;li&gt;If the build fails, read the error and fix it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can monitor this entirely in your agent's chat; no surprise errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow 2: Add AI-Powered Fleet Chat (with Browser Verification)
&lt;/h3&gt;

&lt;p&gt;From the logistics-manager-app codelab, tell your agent: &lt;em&gt;"Implement a fleet chat query feature. Use the Gemini API to analyze fleet data and return filtered results. Start the dev server with Chrome DevTools, navigate to the chat component, and take a screenshot to verify the feature works."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The agent will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;FleetChatService&lt;/code&gt; that accepts a natural-language query.&lt;/li&gt;
&lt;li&gt;Send the current &lt;code&gt;units()&lt;/code&gt; signal state to the Gemini API.&lt;/li&gt;
&lt;li&gt;Parse Gemini's response and filter the fleet.&lt;/li&gt;
&lt;li&gt;Update the chat UI with results.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;dev_server.start&lt;/code&gt; to spin up the dev server.&lt;/li&gt;
&lt;li&gt;Call Chrome DevTools to navigate to the component.&lt;/li&gt;
&lt;li&gt;Snap a screenshot showing the chat results.&lt;/li&gt;
&lt;li&gt;Read the screenshot and confirm the feature works.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No hallucinations—the agent has eyes on the running application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow 3: Implement Predictive Diagnostics with @boundary
&lt;/h3&gt;

&lt;p&gt;From the codelab, tell your agent: &lt;em&gt;"Add a 'Run AI Diagnostic' button to the FleetDetailModal. The button should call a Gemini API with the unit's telemetry (speed, battery, status). Wrap the diagnostics component with @boundary so if the AI call fails, it doesn't crash the modal. Test it by triggering a vehicle detail view and clicking the button."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The agent will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;DiagnosticsComponent&lt;/code&gt; that calls the AI service.&lt;/li&gt;
&lt;li&gt;Wrap it with &lt;code&gt;@boundary&lt;/code&gt; in the modal template.&lt;/li&gt;
&lt;li&gt;Implement a fallback UI in the &lt;a class="mentioned-user" href="https://dev.to/catch"&gt;@catch&lt;/a&gt; block.&lt;/li&gt;
&lt;li&gt;Add retry logic.&lt;/li&gt;
&lt;li&gt;Start the dev server.&lt;/li&gt;
&lt;li&gt;Navigate to a vehicle detail modal.&lt;/li&gt;
&lt;li&gt;Click the diagnostic button.&lt;/li&gt;
&lt;li&gt;Verify the result (or error) in the browser.&lt;/li&gt;
&lt;li&gt;If the test fails, analyze the error and iterate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This entire workflow is deterministic. The agent can't ship broken code—the build will catch it first, and Chrome DevTools will catch runtime issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Skills Configuration Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  One Server Per Domain
&lt;/h3&gt;

&lt;p&gt;Don't load the Angular MCP server alongside your deployment server and communication server. Create separate IDE configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"profiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"angular-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"angular-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@angular/cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"chrome-devtools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"chrome-devtools-mcp@latest"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deployment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deploy-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"my-deploy-cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate only the profile you need for the task at hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version Your Skills
&lt;/h3&gt;

&lt;p&gt;Put skills in your repo and version them like code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/my-project
  /skills
    /angular-v22-dev-guidelines.md
    /our-design-system.md
    /api-integration-patterns.md
  /src
  angular.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @anthropic-ai/skills add ./skills/angular-v22-dev-guidelines.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review and update skills when you update Angular versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measure Context Budget
&lt;/h3&gt;

&lt;p&gt;Before running an agent on a real task, ask it to estimate token usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What's the total token count of all my installed MCP tools and skills?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If over 30% of your context window is on tool definitions, simplify. Agents need room to think.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write MCP Guardrails in Skills
&lt;/h3&gt;

&lt;p&gt;Instead of relying on the agent to "be careful," write it into the skill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Angular Update Guardrail Skill&lt;/span&gt;

Before running &lt;span class="sb"&gt;`ng update`&lt;/span&gt;, ALWAYS:
&lt;span class="p"&gt;1.&lt;/span&gt; Create a git branch: &lt;span class="sb"&gt;`git checkout -b ng-update-v22`&lt;/span&gt;
&lt;span class="p"&gt;2.&lt;/span&gt; Run tests: &lt;span class="sb"&gt;`npm test`&lt;/span&gt;
&lt;span class="p"&gt;3.&lt;/span&gt; Commit current state: &lt;span class="sb"&gt;`git commit -m "checkpoint before ng update"`&lt;/span&gt;
&lt;span class="p"&gt;4.&lt;/span&gt; Then and only then run: &lt;span class="sb"&gt;`ng update @angular/core @angular/cli`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent will follow the skill's instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 5: Troubleshooting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"MCP server not found"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify &lt;code&gt;npx @angular/cli mcp --health-check&lt;/code&gt; returns a list of tools&lt;/li&gt;
&lt;li&gt;Restart your agent IDE&lt;/li&gt;
&lt;li&gt;Check that Angular CLI v22+ is installed: &lt;code&gt;ng version&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;"Skills not recognized"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;npx @anthropic-ai/skills list&lt;/code&gt; to confirm they're installed&lt;/li&gt;
&lt;li&gt;Restart your agent&lt;/li&gt;
&lt;li&gt;Verify the skill URL is correct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;"Chrome DevTools not taking screenshots"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure Chrome is installed and in PATH&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npx chrome-devtools-mcp@latest --health-check&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check that you've started the dev server with &lt;code&gt;dev_server.start&lt;/code&gt; before asking the agent to navigate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;"Build verification timed out"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;dev_server.wait_for_build&lt;/code&gt; tool has a default timeout (usually 30 seconds)&lt;/li&gt;
&lt;li&gt;If your builds are slower, ask the agent to increase the timeout in the MCP call&lt;/li&gt;
&lt;li&gt;Check that the dev server is running: &lt;code&gt;ng serve&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;With Angular v22's MCP + Skills stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents write type-safe code&lt;/strong&gt; that compiles or fails, never silently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exhaustive type checking&lt;/strong&gt; prevents new states from slipping past.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@boundary&lt;/strong&gt; contains failures instead of crashing the app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline templates&lt;/strong&gt; keep components clean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signal Forms&lt;/strong&gt; enforce validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome DevTools integration&lt;/strong&gt; gives agents visibility into running code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills teach modern patterns&lt;/strong&gt; aligned to your version and conventions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hallucination loop is closed. Code generation becomes verifiable. Agentic development shifts from risky to reliable.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up Angular MCP in your IDE/agent (5 minutes)&lt;/li&gt;
&lt;li&gt;Install Angular Skills (2 minutes)&lt;/li&gt;
&lt;li&gt;Configure Chrome DevTools (2 minutes)&lt;/li&gt;
&lt;li&gt;Write a test component using the patterns above&lt;/li&gt;
&lt;li&gt;Ask your agent to scaffold a feature and verify it with MCP tools&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Angular Skills Repository: &lt;a href="https://github.com/angular/skills" rel="noopener noreferrer"&gt;https://github.com/angular/skills&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chrome DevTools for Agents: &lt;a href="https://developer.chrome.com/docs/devtools/agents" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/devtools/agents&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Logistics Manager Codelab: &lt;a href="https://github.com/angular/examples/blob/main/logistics-manager-app/codelab.md" rel="noopener noreferrer"&gt;https://github.com/angular/examples/blob/main/logistics-manager-app/codelab.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>mcp</category>
      <category>agentskills</category>
      <category>ai</category>
    </item>
    <item>
      <title>Stop AI Agents From Hallucinating: Angular v22's Type-Safe, Boundary-Protected Pipelines</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Thu, 04 Jun 2026 04:22:07 +0000</pubDate>
      <link>https://dev.to/turingsoracle/stop-ai-agents-from-hallucinating-angular-v22s-type-safe-boundary-protected-pipelines-3j1k</link>
      <guid>https://dev.to/turingsoracle/stop-ai-agents-from-hallucinating-angular-v22s-type-safe-boundary-protected-pipelines-3j1k</guid>
      <description>&lt;h1&gt;
  
  
  Angular v22: Agentic Pipelines and Resilient Template Architectures
&lt;/h1&gt;

&lt;p&gt;The frontend landscape is no longer just about rendering pixels; it's about establishing robust pipelines that integrate seamlessly with automated, AI-driven workflows. At Google I/O 2026, the Angular team unveiled a massive structural shift for the framework. Moving towards the v22 release (launching the week of June 1st, 2026), Angular is solidifying its primitive layer—pushing Signal Forms and Resource APIs to stable—while actively engineering the framework to act as a first-class citizen in agentic development environments.&lt;/p&gt;

&lt;p&gt;Here is an architectural breakdown of the most critical updates and what they mean for high-performance core engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agentic Pipeline: Angular MCP + Skills
&lt;/h2&gt;

&lt;p&gt;For those of us configuring custom agentic workflows, the standard LLM coding loop is notoriously brittle. An agent writes code, claims it works, and leaves you to discover the compilation errors at runtime.&lt;/p&gt;

&lt;p&gt;Angular is attacking this friction head-on by pairing two critical systems: the Angular CLI's Model Context Protocol (MCP) server that enables AI assistants to interact directly with the Angular CLI, providing tools for code generation, modernizing code, fetching examples, and running &lt;code&gt;builds/tests&lt;/code&gt;, and the &lt;strong&gt;Angular Skills framework&lt;/strong&gt; — a specialized knowledge layer that teaches agents to write modern, v22-aligned code.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works: The MCP Server + Skills Stack
&lt;/h3&gt;

&lt;p&gt;The Angular CLI MCP server exposes tools that launch an interactive AI-powered Angular tutor, find authoritative best-practice code examples, retrieve the Angular Best Practices Guide, and list applications and libraries in the workspace by reading angular.json, and search the official documentation at angular.dev.&lt;/p&gt;

&lt;p&gt;Configure it in your IDE or agent environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"angular-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@angular/cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The angular-developer skill generates Angular code and provides architectural guidance, triggering when creating projects, components, or services or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling, testing, or CLI tooling.&lt;/p&gt;

&lt;p&gt;When an agent scaffolds a new component, instead of reaching for outdated Angular 15 patterns, the &lt;code&gt;angular-developer&lt;/code&gt; skill injects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Signal-first reactivity&lt;/strong&gt;: &lt;code&gt;input()&lt;/code&gt; and &lt;code&gt;output()&lt;/code&gt; instead of &lt;code&gt;@Input()&lt;/code&gt; and &lt;code&gt;@Output()&lt;/code&gt; decorators&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OnPush by default&lt;/strong&gt;: Change detection set to &lt;code&gt;ChangeDetectionStrategy.OnPush&lt;/code&gt; from the start&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standalone components&lt;/strong&gt;: No &lt;code&gt;NgModule&lt;/code&gt; boilerplate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-safe forms&lt;/strong&gt;: Signal Forms for reactive, typed form handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real-world example from the Angular logistics-manager-app codelab: agents can implement AI-powered fleet chat by updating FleetService to include a queryFleet(prompt) method, using the gemini-sdk skill to send the current units() state to Gemini and filter data based on the user's input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing the Hallucination Loop: MCP + Chrome DevTools for Agents
&lt;/h3&gt;

&lt;p&gt;The real power unlocks when you chain Angular MCP with Chrome DevTools for Agents, which allows agents to navigate websites, interact with buttons, explore pages, and run instant accessibility audits through a fully managed browser instance.&lt;/p&gt;

&lt;p&gt;The workflow becomes deterministic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agent writes code&lt;/strong&gt; using the &lt;code&gt;angular-developer&lt;/code&gt; skill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP triggers &lt;code&gt;dev_server.wait_for_build&lt;/code&gt;&lt;/strong&gt; — the agent blocks until compilation succeeds or fails&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent spawns the dev server&lt;/strong&gt; using &lt;code&gt;dev_server.start&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome DevTools for Agents takes a screenshot&lt;/strong&gt; to visually verify DOM changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent reads the rendered output&lt;/strong&gt; and fixes errors if needed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This closes the hallucination loop entirely. No more "I'll assume that worked" — the agent has eyes on your running application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template Resilience with @boundary
&lt;/h2&gt;

&lt;p&gt;In complex UI engineering—especially when mixing DOM layouts with heavy WebGL or custom animation loops—a single component failure can crash the entire change detection cycle, resulting in a blank screen.&lt;/p&gt;

&lt;p&gt;To solve this, Angular is introducing &lt;strong&gt;@boundary&lt;/strong&gt; (landing in Developer Preview in Q3 2026).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@boundary&lt;/code&gt; block introduces native error boundaries directly into the template compilation. If an isolated widget or complex directive throws a fatal error, &lt;code&gt;@boundary&lt;/code&gt; traps it, preventing the crash from bubbling up and halting the rest of the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Isolation and Fallback Patterns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@boundary {
  &lt;span class="nt"&gt;&amp;lt;heavy-webgl-scene-renderer&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @catch (error) {
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"error-fallback"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Scene unavailable&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{ error.message }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"retryBoundary()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Reload scene&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike try-catch in component logic, &lt;code&gt;@boundary&lt;/code&gt; operates at the &lt;strong&gt;template compilation level&lt;/strong&gt;. The boundary knows about the component tree and can isolate errors without unwinding the entire change detection cycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retry Logic Without State Reload
&lt;/h3&gt;

&lt;p&gt;The architecture enables intentional retry logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;sceneError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;retryBoundary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Retry logic — the boundary re-renders, re-executes the component&lt;/span&gt;
    &lt;span class="c1"&gt;// but preserves the outer application state&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sceneError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In traditional Angular, a critical error in one component forces a full page reload. With &lt;code&gt;@boundary&lt;/code&gt;, you contain the failure. The fleet dashboard can crash, but the user can still see the service queue and vehicle list. Error containment becomes a first-class concern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Level Boundaries for Granular Control
&lt;/h3&gt;

&lt;p&gt;You can nest &lt;code&gt;@boundary&lt;/code&gt; blocks for layered error handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@boundary {
  &lt;span class="nt"&gt;&amp;lt;telemetry-dashboard&amp;gt;&lt;/span&gt;
    @boundary {
      &lt;span class="nt"&gt;&amp;lt;ai-predictive-diagnostics&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    } @catch {
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Diagnostics unavailable&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    }
  &lt;span class="nt"&gt;&amp;lt;/telemetry-dashboard&amp;gt;&lt;/span&gt;
} @catch {
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Dashboard offline&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inner boundary catches errors from the diagnostics component; the outer boundary catches errors from the entire dashboard. This mirrors real-world failure domains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive: Advanced Control Flow Mechanics in &lt;code&gt;@switch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The evolution of Angular's control flow syntax isn't just about cleaner aesthetics — it's about moving runtime liabilities into compile-time guarantees. The updates to the &lt;code&gt;@switch&lt;/code&gt; block address two classic pain points in template architecture: redundant boilerplate via multiple case matching and structural desynchronization via exhaustive type checking.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Multiple Case Matching (Boilerplate Reduction)
&lt;/h3&gt;

&lt;p&gt;In traditional templates, if multiple states shared identical UI representation, you were forced to duplicate template blocks or nest conditional elements. Angular now allows comma-separated matching values within a single &lt;code&gt;@case&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@switch (orderStatus()) {
  @case ('pending', 'processing') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Your order is being prepared.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
  @case ('shipped') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Your order is on the way.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
  @case ('delivered') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Order complete.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template compiler groups these branches efficiently without generating redundant view nodes. Instead of maintaining two separate case blocks with identical markup, a single case handles multiple states. This is especially powerful when dealing with isomorphic state enums where the user-facing representation is identical across several backend statuses.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Exhaustive Checking via the &lt;code&gt;never&lt;/code&gt; Type
&lt;/h3&gt;

&lt;p&gt;The most critical architectural upgrade is compile-time exhaustiveness enforcement. When dealing with strict TypeScript union types (e.g., &lt;code&gt;type Status = 'open' | 'closed' | 'archived'&lt;/code&gt;), a common source of production bugs occurs when a backend team introduces a new status — but the frontend template is never updated. The UI silently fails or shows a blank state.&lt;/p&gt;

&lt;p&gt;By combining template variable evaluation with an exhaustive default assignment using the &lt;code&gt;never&lt;/code&gt; type boundary assertion, the Angular compiler can enforce that every branch of a union type is explicitly handled. If a new member is added to the union, the build breaks immediately until that state is handled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Component TypeScript&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;OrderStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;processing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shipped&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delivered&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;orderStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OrderStatus&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// This forces exhaustive checking — TypeScript won't compile without all cases&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;assertNever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unhandled status: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Template with exhaustive guarantee --&amp;gt;&lt;/span&gt;
@switch (orderStatus()) {
  @case ('pending') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Waiting to be processed.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
  @case ('processing') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Your order is being prepared.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
  @case ('shipped') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Your order is on the way.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
  @case ('delivered') {
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Order complete.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  }
  @default {
    {{ assertNever(orderStatus() as never) }}
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a backend engineer adds a sixth status (&lt;code&gt;'returned'&lt;/code&gt;) without notifying the frontend, TypeScript compilation fails immediately. This shifts the burden of type safety from runtime testing to the development build process — exactly where it belongs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inline Template Functions: Reducing Class Boilerplate
&lt;/h2&gt;

&lt;p&gt;In v22, you can now safely inline short, quick arrow functions directly within template event bindings without bloating your TypeScript class. This is more than cosmetic—it's a statement about where logic belongs.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pattern: Event Handlers and Transforms
&lt;/h3&gt;

&lt;p&gt;Instead of exposing every handler as a class method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before: pollutes the component API&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CartComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;([...]);&lt;/span&gt;

  &lt;span class="nf"&gt;onAddItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onRemoveItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now inline these directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- v22: inline arrow functions in templates --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"items.update(items =&amp;gt; [...items, newItem()])"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Add&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"items.update(items =&amp;gt; items.filter(i =&amp;gt; i.id !== id))"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Remove&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component surface shrinks—only the true public API remains visible. Transient handlers stay in the template, where they logically belong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Template Errors and Type Inference
&lt;/h3&gt;

&lt;p&gt;The template compiler now provides rich type feedback for inline expressions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- TypeScript error: items.update expects an updater function --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"items.update('invalid')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Wrong&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- ✓ Correct: full type checking on the inline arrow function parameter --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"items.update(items =&amp;gt; items.slice(0, items.length - 1))"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Remove last
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is critical for agent-assisted development. When the &lt;code&gt;angular-developer&lt;/code&gt; skill writes template code, the compiler catches type mismatches immediately, preventing hallucinations from reaching production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Example: Form Field Transforms
&lt;/h3&gt;

&lt;p&gt;From the logistics-manager-app codelab, when a user describes an issue like "The vehicle is emitting smoke and the engine has stopped," the AI should automatically set the priority to CRITICAL by adding a listener to the issue field in the &lt;strong&gt;serviceForm&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With inline template functions, you can implement this compactly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
  &lt;span class="na"&gt;(blur)=&lt;/span&gt;&lt;span class="s"&gt;"priorityField.setValue(
    analyzePriority(issueField.value)
  )"&lt;/span&gt;
  &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Describe the issue..."&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The handler stays close to its trigger, making the intent transparent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Reactivity Refinements
&lt;/h2&gt;

&lt;p&gt;Beyond agents, error boundaries, and control flow mechanics, Angular is sharpening the broader developer experience:&lt;/p&gt;

&lt;h3&gt;
  
  
  Signal Forms: Fine-Grained Reactivity for Complex Forms
&lt;/h3&gt;

&lt;p&gt;Moving out of Developer Preview in v22, Signal Forms combines the strict typing of reactive forms with the granular reactivity of Signals. A form with 50 fields now updates only the field that changed—not the entire form tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceTicketForm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;issueDescription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOW&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;assignedTechnician&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Signal-based access with fine-grained tracking&lt;/span&gt;
  &lt;span class="nx"&gt;priority$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;priority&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueAsSignal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Only the priority display updates when priority changes&lt;/span&gt;
  &lt;span class="nx"&gt;priorityStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CRITICAL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-yellow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Angular Aria: Accessible UI Primitives
&lt;/h3&gt;

&lt;p&gt;Alongside Signal Forms, Angular Aria (the headless, fully accessible UI directive set) also hits stable, allowing you to build heavily customized, high-contrast UI components without sacrificing native accessibility standards.&lt;/p&gt;

&lt;p&gt;This is crucial for AI-assisted development. When the &lt;code&gt;angular-developer&lt;/code&gt; skill scaffolds a custom dropdown or modal, it automatically includes the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keyboard navigation (arrow keys, enter, escape)&lt;/li&gt;
&lt;li&gt;ARIA roles and live regions&lt;/li&gt;
&lt;li&gt;Focus management&lt;/li&gt;
&lt;li&gt;Screen reader announcements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No agent hallucinations about accessibility—it's baked in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vitest as Default
&lt;/h3&gt;

&lt;p&gt;The Angular CLI now scaffolds all new projects with Vitest as the default test runner, replacing Karma for dramatically faster, more modern testing cycles. Tests run in milliseconds instead of seconds, making the agent feedback loop nearly instant.&lt;/p&gt;

&lt;h3&gt;
  
  
  OnPush as Default Change Detection
&lt;/h3&gt;

&lt;p&gt;New components use &lt;code&gt;ChangeDetectionStrategy.OnPush&lt;/code&gt; by default, encouraging signal-based reactivity over Zone.js-triggered checks from project inception. This trains both developers and agents to think in terms of granular, trackable state changes rather than global change detection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Skills: Teaching Agents Modern Patterns
&lt;/h2&gt;

&lt;p&gt;Angular Skills are designed to help coding agents create applications aligned with the latest versions of Angular, best practices, and new features and manage Angular applications effectively. These skills provide architectural guidance, generate idiomatic Angular code, and help scaffold new projects using modern best practices.&lt;/p&gt;

&lt;p&gt;Two key skills ship with v22:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;angular-developer&lt;/code&gt;&lt;/strong&gt;: Generates code for components, services, state management, forms, routing, SSR, and more. Always references the correct Angular version before providing guidance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;angular-new-app&lt;/code&gt;&lt;/strong&gt;: Creates a new Angular app using the Angular CLI, providing important guidelines for effectively setting up and structuring a modern Angular application, with flags like --ai-config=[agents, claude, copilot, cursor, gemini, jetbrains, none, windsurf] to tune the generated code for the specific agent's conventions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Skills and MCP tools are complementary—don't confuse them. One MCP server per domain (don't load everything at once); version your skills like code (a skill for Angular 19 patterns will actively hurt you on Angular 21); use skills to write MCP guardrails (e.g., "Before running ng update, always create a git branch first"); and measure your context budget (if over 30% of your context window is on tool definitions, you have a configuration problem).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Consolidation Release
&lt;/h2&gt;

&lt;p&gt;Angular is no longer just catching up in the reactivity space; by natively integrating MCP and Angular Skills, hardening its template error boundaries with &lt;code&gt;@boundary&lt;/code&gt;, automating exhaustive type checking in control flow, and enabling inline template functions, it is actively defining what a modern, agent-ready frontend architecture looks like.&lt;/p&gt;

&lt;p&gt;v22 is the signal-first era made concrete. The framework's multi-year modernization effort converges into a coherent, production-ready, agentic-native development model where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents write type-safe templates&lt;/strong&gt; that compile or fail, never silently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error boundaries isolate failures&lt;/strong&gt; instead of crashing the entire app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control flow is exhaustive&lt;/strong&gt; by default, not a runtime surprise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers close the hallucination loop&lt;/strong&gt; with real browser visibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills teach agents modern patterns&lt;/strong&gt; tailored to your version and conventions.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's new in Angular - Chrome for Developers (Google I/O 2026)&lt;/li&gt;
&lt;li&gt;Angular Skills Repository: &lt;a href="https://github.com/angular/skills" rel="noopener noreferrer"&gt;https://github.com/angular/skills&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Logistics Manager App Codelab: &lt;a href="https://github.com/angular/examples/blob/main/logistics-manager-app/codelab.md" rel="noopener noreferrer"&gt;https://github.com/angular/examples/blob/main/logistics-manager-app/codelab.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MCP Skills vs MCP Tools: The Right Way to Configure Your Server (Antonio Cárdenas, yeou.dev)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>ai</category>
      <category>agents</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Antigravity is Dead. Long Live Antigravity.</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Wed, 20 May 2026 00:14:21 +0000</pubDate>
      <link>https://dev.to/turingsoracle/antigravity-is-dead-long-live-antigravity-186m</link>
      <guid>https://dev.to/turingsoracle/antigravity-is-dead-long-live-antigravity-186m</guid>
      <description>&lt;p&gt;Google just dropped &lt;strong&gt;Antigravity 2.0&lt;/strong&gt; at I/O 2026—and in the same breath, it killed Gemini CLI, stranded a lot of chat histories in a backup directory, and shipped three new surfaces sharing the same brand. If you opened the app this morning and panicked because your conversations are gone, keep reading. We'll fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What just happened at I/O 2026
&lt;/h2&gt;

&lt;p&gt;On May 18, 2026, Google rebranded Antigravity from a "cursor competitor" into a full &lt;strong&gt;agent-first development platform&lt;/strong&gt; powered by Gemini 3.5 Flash. The brand now spans four products:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity 2.0&lt;/strong&gt; — the new standalone desktop app with multi-agent orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity CLI&lt;/strong&gt; — a Go-based terminal tool replacing Gemini CLI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity SDK&lt;/strong&gt; — programmatic access to the same agent harness Google uses internally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity IDE&lt;/strong&gt; — the original VS Code-style app from November 2025, still alive
And here's the deadline you can't ignore: &lt;strong&gt;Gemini CLI sunsets on June 18, 2026&lt;/strong&gt; for AI Pro, AI Ultra, and free-tier users. Enterprise on Gemini Code Assist Standard or Enterprise keeps access — everyone else has 30 days to migrate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Four Faces of Antigravity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Antigravity 2.0 (Desktop App)
&lt;/h3&gt;

&lt;p&gt;The flagship. Runs multiple agents in parallel, ships dynamic subagents for parallelized workflows, schedules tasks in the background, and integrates natively with AI Studio, Firebase, and Android. Export a project from AI Studio on your phone and open it locally, full context intact. Voice command support is in too — you can talk to your agents instead of typing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Antigravity CLI
&lt;/h3&gt;

&lt;p&gt;Rebuilt from scratch in Go. Same agent harness as the desktop, terminal-native, and noticeably faster than its predecessor. If you live in Gemini CLI today, this is your migration target — and you have until &lt;strong&gt;June 18&lt;/strong&gt; to switch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify your install once you migrate&lt;/span&gt;
antigravity &lt;span class="nt"&gt;--version&lt;/span&gt;
antigravity agent new &lt;span class="s2"&gt;"refactor the auth module"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Antigravity SDK
&lt;/h3&gt;

&lt;p&gt;For building custom agents on top of Google's coding infrastructure, optimized for Gemini models. You define the behaviors; you host wherever it fits — Google Cloud, your own infra, your choice. Custom agent templates are available in AI Studio for enterprise use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Antigravity IDE (the original)
&lt;/h3&gt;

&lt;p&gt;Still maintained. Still the VS Code fork from November 2025. This is the one most of us got hooked on — and it's the one with the migration trap (more on that below).&lt;/p&gt;

&lt;h2&gt;
  
  
  The immediate pain: your chat history is in the wrong directory
&lt;/h2&gt;

&lt;p&gt;If you updated to 2.0 and your conversations are gone, &lt;strong&gt;your data is not lost — the migration stranded it in a backup folder.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Antigravity 2.0 uses three directories under &lt;code&gt;~/.gemini/&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directory&lt;/th&gt;
&lt;th&gt;Owner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/antigravity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Live data for the standalone 2.0 app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/antigravity-ide&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Live data for the original IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/antigravity-backup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Snapshot the migration created — often more complete than the live dir&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After the update, the standalone app's &lt;code&gt;antigravity/&lt;/code&gt; dir frequently ends up missing brain entries, scratch space, and conversation files. The &lt;code&gt;antigravity-backup/&lt;/code&gt; next to it has the full set. We just need to put the right one in front of the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix: rsync from backup into the live dir
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;macOS / Linux&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dry-run first — see exactly what would change&lt;/span&gt;
rsync &lt;span class="nt"&gt;-avhn&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'mcp_config.json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.gemini/antigravity-backup/ &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.gemini/antigravity/

&lt;span class="c"&gt;# Looks right? Run it for real (drop the -n flag)&lt;/span&gt;
rsync &lt;span class="nt"&gt;-avh&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'mcp_config.json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.gemini/antigravity-backup/ &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.gemini/antigravity/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why exclude &lt;code&gt;mcp_config.json&lt;/code&gt;? It's usually a symlink pointing at your local MCP server configuration — overwrite it and you break your active MCP connections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows (PowerShell)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.gemini\antigravity-backup"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$dest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.gemini\antigravity"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Robocopy mirror, excluding mcp_config.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;robocopy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$dest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/E&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/XF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mcp_config.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fully quit&lt;/strong&gt; Antigravity — kill the process, don't just close the window.&lt;/li&gt;
&lt;li&gt;Reopen the app.&lt;/li&gt;
&lt;li&gt;Verify the side panel now shows your threads.
If anything looks off, your &lt;code&gt;antigravity-backup/&lt;/code&gt; is untouched — you can re-run the sync or copy specific files manually. For peace of mind, snapshot &lt;code&gt;antigravity-backup/&lt;/code&gt; to an external location before you start poking at it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to install just the IDE (skip 2.0)
&lt;/h2&gt;

&lt;p&gt;The good news: &lt;strong&gt;the IDE and the standalone 2.0 app keep their data in separate directories&lt;/strong&gt; (&lt;code&gt;antigravity-ide/&lt;/code&gt; vs &lt;code&gt;antigravity/&lt;/code&gt;), so your IDE history doesn't get clobbered when 2.0 installs alongside it.&lt;/p&gt;

&lt;p&gt;The bad news: &lt;strong&gt;the installers conflict at the OS level.&lt;/strong&gt; Install both and the IDE binary refuses to launch — dependencies are coupled. Uninstalling 2.0 doesn't fully heal the IDE either; you have to reinstall the IDE cleanly, which wipes your IDE settings.&lt;/p&gt;

&lt;p&gt;If you want to stay on the IDE only:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Uninstall Antigravity 2.0 completely&lt;/strong&gt; if you already installed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Back up&lt;/strong&gt; &lt;code&gt;~/.gemini/antigravity-ide&lt;/code&gt; before touching anything else.&lt;/li&gt;
&lt;li&gt;Grab the IDE installer from the releases page: &lt;a href="https://antigravity.google/releases" rel="noopener noreferrer"&gt;antigravity.google/releases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pick a version that predates the 2.0 split — &lt;strong&gt;1.23.2&lt;/strong&gt; is the safest landing pad.&lt;/li&gt;
&lt;li&gt;In Settings, switch updates to manual so the app doesn't silently jump back to 2.0.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="c1"&gt;// settings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"update.mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"manual"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Migration checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Migrate Gemini CLI workflows to Antigravity CLI &lt;strong&gt;before June 18, 2026&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Pick one: 2.0 desktop &lt;em&gt;or&lt;/em&gt; the original IDE — never install both&lt;/li&gt;
&lt;li&gt;[ ] Back up &lt;code&gt;~/.gemini/antigravity&lt;/code&gt; and &lt;code&gt;~/.gemini/antigravity-ide&lt;/code&gt; weekly&lt;/li&gt;
&lt;li&gt;[ ] If history disappeared post-update, &lt;code&gt;rsync&lt;/code&gt; from &lt;code&gt;~/.gemini/antigravity-backup&lt;/code&gt; (exclude &lt;code&gt;mcp_config.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;[ ] Set &lt;code&gt;update.mode&lt;/code&gt; to &lt;code&gt;manual&lt;/code&gt; if you depend on the IDE&lt;/li&gt;
&lt;li&gt;[ ] Evaluate the new $100 AI Ultra tier if you run multi-agent workloads (5× the Pro limits)
## TL;DR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Antigravity 2.0 + CLI + SDK shipped at I/O 2026. Gemini CLI dies June 18, 2026. Lost your chat history? Your data is sitting in &lt;code&gt;~/.gemini/antigravity-backup&lt;/code&gt; — &lt;code&gt;rsync&lt;/code&gt; it into &lt;code&gt;~/.gemini/antigravity&lt;/code&gt; (excluding &lt;code&gt;mcp_config.json&lt;/code&gt;), restart the app. Want the old IDE only? Uninstall 2.0, install 1.23.2 from the releases page, set updates to manual. Pick one — don't run 2.0 and the IDE side by side.&lt;/p&gt;

&lt;p&gt;The king is dead. Long live the king. Migrate carefully.&lt;/p&gt;

</description>
      <category>antigravity</category>
      <category>gemini</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>MCP Skills vs MCP Tools: The Right Way to Configure Your Server</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Sun, 22 Mar 2026 08:40:00 +0000</pubDate>
      <link>https://dev.to/turingsoracle/mcp-skills-vs-mcp-tools-the-right-way-to-configure-your-server-562c</link>
      <guid>https://dev.to/turingsoracle/mcp-skills-vs-mcp-tools-the-right-way-to-configure-your-server-562c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Skills and MCP tools are not the same thing — and confusing them costs you. Learn the real difference, the real downsides, and how to combine both for a better agentic workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  MCP Skills vs MCP Tools: What's the Difference and How to Combine Them
&lt;/h1&gt;

&lt;p&gt;Everyone is talking about MCP. Everyone is talking about skills.&lt;/p&gt;

&lt;p&gt;Most people are using them interchangeably — and that's exactly the problem.&lt;/p&gt;

&lt;p&gt;They are not the same thing. They don't solve the same problem. And if you reach for the wrong one, you will feel it: hallucinations, context blowups, agents that drift off-task, and workflows that fall apart under pressure.&lt;/p&gt;

&lt;p&gt;Let's fix that.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Mental Model
&lt;/h2&gt;

&lt;p&gt;Think of it like a kitchen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP tools&lt;/strong&gt; are your appliances and ingredients — the oven, the fridge, the fresh vegetables. Raw capability. Without them, nothing gets cooked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; are your recipes — the step-by-step instructions that tell a skilled chef exactly how to turn those ingredients into something good. Without them, you have power with no direction.&lt;/p&gt;

&lt;p&gt;An agent with only MCP tools can &lt;em&gt;do&lt;/em&gt; things but doesn't necessarily know &lt;em&gt;how&lt;/em&gt; to do them well. An agent with only skills has great instructions but no way to act on them.&lt;/p&gt;

&lt;p&gt;You need both.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an MCP Tool?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Model Context Protocol&lt;/strong&gt; is an open standard — now under the Linux Foundation's Agentic AI Foundation — that gives AI agents a standardized way to connect to external systems: databases, APIs, file systems, GitHub, Slack, your Angular CLI.&lt;/p&gt;

&lt;p&gt;When you connect an MCP server to your client—whether that's Claude Code, the Gemini CLI, or a custom agent—it gets access to a set of typed, deterministic tools. Each tool has a clear input/output schema. When the agent calls it, it executes — no interpretation, no hallucination risk at the execution level. It's a structured API call, not a suggestion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"angular-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@angular/cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MCP is how the agent &lt;em&gt;reaches outside itself&lt;/em&gt;. It's the nervous system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use MCP when you need the agent to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read or write to a real system (database, filesystem, API)&lt;/li&gt;
&lt;li&gt;Execute actions with clear, auditable inputs and outputs&lt;/li&gt;
&lt;li&gt;Connect to tools you don't own or control&lt;/li&gt;
&lt;li&gt;Integrate multiple services through a consistent interface&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Is a Skill?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Skill&lt;/strong&gt; is a folder containing a Markdown file (with YAML frontmatter) plus optional scripts and resources. It's not executable by itself — it's a playbook.&lt;/p&gt;

&lt;p&gt;When a user's request matches a Skill's relevance criteria, the agent loads those instructions dynamically and follows them. Think of it as giving the agent expert-level procedural memory on demand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;angular-component-review&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Review Angular components for Signal compliance and standalone architecture&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Angular Component Review&lt;/span&gt;

When reviewing an Angular component:
&lt;span class="p"&gt;1.&lt;/span&gt; Check that all state uses &lt;span class="sb"&gt;`signal()`&lt;/span&gt; or &lt;span class="sb"&gt;`computed()`&lt;/span&gt; — never direct property mutation
&lt;span class="p"&gt;2.&lt;/span&gt; Verify the component is &lt;span class="sb"&gt;`standalone: true`&lt;/span&gt;
&lt;span class="p"&gt;3.&lt;/span&gt; Confirm no &lt;span class="sb"&gt;`NgModule`&lt;/span&gt; dependencies remain
&lt;span class="p"&gt;4.&lt;/span&gt; Validate that &lt;span class="sb"&gt;`@if`&lt;/span&gt; / &lt;span class="sb"&gt;`@for`&lt;/span&gt; is used instead of &lt;span class="sb"&gt;`*ngIf`&lt;/span&gt; / &lt;span class="sb"&gt;`*ngFor`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent loads this only when it's relevant. When it's not — it costs you nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use a skill when you need the agent to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow a consistent process or checklist&lt;/li&gt;
&lt;li&gt;Apply domain-specific expertise (your coding standards, review criteria)&lt;/li&gt;
&lt;li&gt;Encode knowledge that doesn't change often&lt;/li&gt;
&lt;li&gt;Reuse the same workflow across different conversations&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Real Downsides
&lt;/h2&gt;

&lt;p&gt;This is where most guides stop. They shouldn't.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP: The Token Tax
&lt;/h3&gt;

&lt;p&gt;Every MCP tool you connect injects its full schema into the context window &lt;em&gt;before the agent processes a single message&lt;/em&gt;. Each tool costs 550–1,400 tokens. Connect GitHub, Slack, and Sentry, and you're looking at &lt;strong&gt;55,000 tokens burned upfront&lt;/strong&gt; — over a quarter of Claude's 200k limit before any real work begins. And if you are using Gemini with its 1M+ token window, you might think you can just ignore this. Don't. Even if you have the space to spare, dumping 55,000 tokens of raw JSON schema into every single turn of a conversation drives up your latency, increases API costs, and dilutes the model's focus.&lt;/p&gt;

&lt;p&gt;One team reported connecting three MCP servers and consuming &lt;strong&gt;143,000 of 200,000 tokens&lt;/strong&gt; on tool definitions alone. The agent had 57,000 tokens left for the actual conversation.&lt;/p&gt;

&lt;p&gt;The good news: modern clients like Claude Code and the Gemini CLI have adopted progressive discovery for MCP—loading only tool names and descriptions upfront (~20–50 tokens each) and fetching full schemas only when the agent actually needs a tool. Token overhead declined by ~85%. But this feature only works if your MCP setup is configured to use it, and most setups still aren't.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skills: The Staleness Problem
&lt;/h3&gt;

&lt;p&gt;Skills are Markdown files. They don't update themselves. If your Angular patterns evolve — say you migrate from &lt;code&gt;setInput()&lt;/code&gt; to the new declarative API in Angular 20 — your Skill still teaches the old way until someone updates it manually.&lt;/p&gt;

&lt;p&gt;The more skills you create, the more maintenance burden you carry. And if a skill is subtly wrong, the agent will follow it confidently — no error, just quietly incorrect output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Both: The Selection Problem
&lt;/h3&gt;

&lt;p&gt;Give an agent too many tools or too many skills, and it starts making the wrong choices — calling the wrong tool, triggering the wrong playbook, or combining them in ways that produce contradictory instructions. Experts recommend staying under &lt;strong&gt;10–15 active MCP tools&lt;/strong&gt; at any time.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Combine Them
&lt;/h2&gt;

&lt;p&gt;The most powerful pattern is using them as layers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1 — MCP provides access.&lt;/strong&gt;&lt;br&gt;
Connect only what the agent genuinely needs for the current task. Angular CLI, a database, and a file system. Keep it lean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 — Skills provide expertise.&lt;/strong&gt;&lt;br&gt;
Create a skill that tells the agent &lt;em&gt;how&lt;/em&gt; to use those tools in your specific context. Not just "run the Angular CLI" — but "when migrating a component, run &lt;code&gt;ng generate&lt;/code&gt; with these flags, then validate against these patterns."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3 — Skills can orchestrate MCP.&lt;/strong&gt;&lt;br&gt;
A Skill can define a multi-step workflow that calls multiple MCP tools in sequence. Example: a "Deploy &amp;amp; Notify" Skill that uses GitHub MCP to push, a CI/CD MCP to trigger a build, and a Slack MCP to notify the team — all under one coherent playbook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;angular-migration-workflow&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Full workflow for migrating an Angular component to v21 patterns&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Migration Workflow&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; Use the Angular CLI MCP to check the current component version
&lt;span class="p"&gt;2.&lt;/span&gt; Run &lt;span class="sb"&gt;`ng update`&lt;/span&gt; for the affected package
&lt;span class="p"&gt;3.&lt;/span&gt; Apply the zoneless migration schematic
&lt;span class="p"&gt;4.&lt;/span&gt; Review the output against the angular-component-review Skill
&lt;span class="p"&gt;5.&lt;/span&gt; Run tests and report results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Practical Decision Guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Need to query a real database&lt;/td&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to follow a code review checklist&lt;/td&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to push to GitHub&lt;/td&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to apply your team's commit message format&lt;/td&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to read a live API&lt;/td&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to teach the agent your Angular architecture rules&lt;/td&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need both access and consistent process&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Improving Your Workflow
&lt;/h2&gt;

&lt;p&gt;A few patterns that actually work in production:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. One MCP server per domain.&lt;/strong&gt; Don't load everything at once. Create separate configs for "Angular development," "deployment," and "communication" — and activate only the one you need for a given session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Version your Skills like code.&lt;/strong&gt; Put them in your repository. Review them when you update your stack. A Skill for Angular 19 patterns will actively hurt you on Angular 21.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Use Skills to write MCP guardrails.&lt;/strong&gt; Instead of relying on the agent to figure out when to call a destructive MCP action, write a Skill that explicitly says: &lt;em&gt;"Before running any &lt;code&gt;ng update&lt;/code&gt;, always create a git branch first."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Measure your context budget.&lt;/strong&gt; Before your agent does any real work, know how many tokens your MCP setup consumes. If you're over 30% of your context window is on tool definitions, you have a configuration problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Let the agent maintain simple Skills.&lt;/strong&gt; For fast-moving areas — like keeping track of your team's current Angular version conventions — let the agent update the Skill file itself when you tell it to. It's faster than doing it manually and keeps the Skill honest.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;MCP gives agents the ability to act. Skills teach them how to act well.&lt;/p&gt;

&lt;p&gt;The debate of "MCP vs Skills" is a false one. The real question is: &lt;em&gt;do you need access, expertise, or both?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In most real Angular workflows, you need both. An agent that can run your CLI but doesn't know your architecture is just a faster way to make the same mistakes. An agent that knows your patterns but can't touch your actual project is just an expensive search engine.&lt;/p&gt;

&lt;p&gt;Used together, with clear boundaries and lean configuration, they're the foundation of agentic development that actually works.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Previously I wrote about &lt;a href="https://www.yeou.dev/articles/angular-21-mcp-migrations" rel="noopener noreferrer"&gt;Angular 21 MCP and the end of manual migrations&lt;/a&gt; — a good starting point if you're new to the MCP server setup for Angular.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Angular 20 to 21 Upgrade: The Practical Survival Guide</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Sat, 13 Dec 2025 07:48:14 +0000</pubDate>
      <link>https://dev.to/turingsoracle/angular-20-to-21-upgrade-the-practical-survival-guide-1km9</link>
      <guid>https://dev.to/turingsoracle/angular-20-to-21-upgrade-the-practical-survival-guide-1km9</guid>
      <description>&lt;p&gt;A clear and concise guide to upgrading from Angular 20 to 21. that Covers the essentials like the Karma full removal, the new default Zoneless mode, automatic HttpClient, and how to fix your breaking builds.&lt;/p&gt;

&lt;p&gt;If you thought Angular 20 was a big shift, welcome to Angular 21.&lt;/p&gt;

&lt;p&gt;While version 20 was about stabilizing Signals, version 21 is about removing most of the old patterns. The "Angular Way" has fundamentally changed: &lt;code&gt;zone.js&lt;/code&gt; is optional, Karma is dead, and RxJS is slowly retreating to the edges.&lt;/p&gt;

&lt;p&gt;This isn't just an update; it's a new ecosystem. Here is what is going to break and how to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 The "Stop Everything" Breaking Changes
&lt;/h2&gt;

&lt;p&gt;Before you run &lt;code&gt;ng update&lt;/code&gt;, be aware that your build will likely fail if you rely on these legacy patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Karma Extinction Event (Vitest is Default)
&lt;/h3&gt;

&lt;p&gt;The most immediate shock for many teams will be &lt;code&gt;ng test&lt;/code&gt;. Angular 21 has officially swapped Karma for Vitest as the default test runner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What breaks:&lt;/strong&gt; If you have a custom &lt;code&gt;karma.conf.js&lt;/code&gt; or rely on specific Karma plugins/reporters, your test suite is now legacy code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;New Projects:&lt;/strong&gt; You get Vitest out of the box. It's faster, cleaner, and uses Vite.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Existing Projects:&lt;/strong&gt; You aren't forced to switch immediately, but the writing is on the wall. The CLI will nag you.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Migration:&lt;/strong&gt; Run the schematic &lt;code&gt;ng generate @angular/core:karma-to-vitest&lt;/code&gt; to attempt an auto-migration. It's remarkably good at converting standard configs, but custom Webpack hacks in your test setup will need manual rewriting for Vite.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. HttpClient is "Just There"
&lt;/h3&gt;

&lt;p&gt;Remember adding &lt;code&gt;provideHttpClient()&lt;/code&gt; to your &lt;code&gt;app.config.ts&lt;/code&gt; or importing &lt;code&gt;HttpClientModule&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Change:&lt;/strong&gt; &lt;code&gt;HttpClient&lt;/code&gt; is now injected by default in the root injector.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What breaks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If you have tests that mock &lt;code&gt;HttpClient&lt;/code&gt; by expecting it not to be there, they might fail.&lt;/li&gt;
&lt;li&gt;  If you rely on &lt;code&gt;HttpClientModule&lt;/code&gt; for complex interceptor ordering in a mixed NgModule/Standalone app, you might see subtle behavior changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Remove explicit &lt;code&gt;provideHttpClient()&lt;/code&gt; calls unless you are passing configuration options (like &lt;code&gt;withInterceptors&lt;/code&gt; or &lt;code&gt;withFetch&lt;/code&gt;). It cleans up your config, but check your interceptor execution order.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. zone.js is Gone (For New Apps)
&lt;/h3&gt;

&lt;p&gt;New apps generated with &lt;code&gt;ng new&lt;/code&gt; will exclude &lt;code&gt;zone.js&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What breaks:&lt;/strong&gt; Nothing for existing apps (yet). Your &lt;code&gt;polyfils.ts&lt;/code&gt; will keep importing Zone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Warning:&lt;/strong&gt; If you copy-paste code from a new v21 tutorial into your existing v20 app, it might assume Zoneless behavior (using &lt;code&gt;ChangeDetectorRef&lt;/code&gt; less often, relying on Signals). If you mix the two paradigms without understanding them, you'll get "changed after checked" errors or views that don't update.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ The New Toys: Features You'll Actually Use
&lt;/h2&gt;

&lt;p&gt;Once you fix the build, v21 offers some incredible DX improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Signal Forms (Experimental but Stable)
&lt;/h3&gt;

&lt;p&gt;This is the feature we've been waiting for. No more &lt;code&gt;valueChanges.pipe(...)&lt;/code&gt;spaghetti.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/forms/signals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Define a reactive form model&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Access values directly as signals!&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why use it:&lt;/strong&gt; It's type-safe by default and doesn't require RxJS mastery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Experimental. Use it for new features, but maybe don't rewrite your checkout flow just yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Angular Aria (Developer Preview)
&lt;/h3&gt;

&lt;p&gt;A new library of headless primitives for accessibility.&lt;/p&gt;

&lt;p&gt;Instead of fighting with &lt;code&gt;aria-expanded&lt;/code&gt; and &lt;code&gt;role="button"&lt;/code&gt;, you use directives that handle the a11y logic while you handle the CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Handles keyboard nav, focus, and ARIA roles automatically --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;ariaMenu&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;ariaMenuItem&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Option 1&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;ariaMenuItem&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Option 2&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Regex in Templates
&lt;/h3&gt;

&lt;p&gt;Small but mighty. You can finally use regex literals in templates, perfect for &lt;code&gt;@if&lt;/code&gt;logic without creating a helper function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@if (email() | match: /@company\.com$/) {
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"badge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Employee&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛠️ The Upgrade Checklist
&lt;/h2&gt;

&lt;p&gt;Ready to jump? Follow this order to minimize pain.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Backup:&lt;/strong&gt; Commit everything. Seriously.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update the Global CLI:&lt;/strong&gt;&lt;br&gt;
Updating Angular generally involves two parts: the global CLI and the local project dependencies. Ensure your global CLI is up to date first (you might need sudo or Administrator privileges).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Optional: Uninstall the old global version first to avoid conflicts&lt;/span&gt;
npm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli

&lt;span class="c"&gt;# Verify the npm cache&lt;/span&gt;
npm cache verify

&lt;span class="c"&gt;# Install the latest global CLI version&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update Local Project:&lt;/strong&gt;&lt;br&gt;
Now update your local project dependencies:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng update @angular/cli@21 @angular/core@21
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the Diagnostics:&lt;/strong&gt;&lt;br&gt;
Angular 21 includes smarter diagnostics. Pay attention to warnings about &lt;code&gt;ngClass&lt;/code&gt; (soft deprecated in favor of &lt;code&gt;[class.my-class]&lt;/code&gt;) and standalone migration opportunities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check Your Tests:&lt;/strong&gt;&lt;br&gt;
Run &lt;code&gt;ng test&lt;/code&gt;. If it explodes, decide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Path A:&lt;/strong&gt; Keep Karma (add &lt;code&gt;@angular/build:karma&lt;/code&gt; manually if removed).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Path B:&lt;/strong&gt; Migrate to Vitest (Recommended).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Optional: Go Zoneless:&lt;/strong&gt;&lt;br&gt;
If you're feeling brave, run the experimental migration:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng generate @angular/core:zoneless-migration
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;This is "Agentic" territory. See our &lt;a href="https://dev.to/turingsoracle/angular-21-mcp-the-end-of-manual-migrations-4hdh"&gt;MCP Guide&lt;/a&gt; for how to let AI handle this complex refactor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Angular 21 is the "clean slate" release. It sheds the weight of the last decade (Zone, Karma, Modules) to compete with modern frameworks like Svelte and Solid.&lt;/p&gt;

&lt;p&gt;The upgrade might be bumpy due to the testing changes, but the destination—a faster, simpler, signal-driven framework—is absolutely worth it.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>upgrade</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Upgrading to Angular 20</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Sat, 28 Jun 2025 10:07:39 +0000</pubDate>
      <link>https://dev.to/turingsoracle/upgrading-to-angular-20-4h5i</link>
      <guid>https://dev.to/turingsoracle/upgrading-to-angular-20-4h5i</guid>
      <description>&lt;p&gt;This is a practical guide focused on what really matters when updating a real-world application: what breaks, what makes your work easier, and how you should adapt your development style.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Full Story Behind Karma's Removal: Beyond a Broken Build
&lt;/h2&gt;

&lt;p&gt;The immediate issue when upgrading is that &lt;code&gt;ng test&lt;/code&gt; will fail. The reason is a fundamental change in Angular's build tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did Angular drop Karma?
&lt;/h3&gt;

&lt;p&gt;With Angular 20, the default build package changes from &lt;code&gt;@angular-devkit/build-angular&lt;/code&gt; to the new &lt;code&gt;@angular/build&lt;/code&gt;. This new package no longer includes the Karma plugin used by legacy test setups.&lt;/p&gt;

&lt;p&gt;The web ecosystem has moved on to faster test runners like &lt;strong&gt;Vitest&lt;/strong&gt; and &lt;strong&gt;Jest&lt;/strong&gt; that use modern tools like Vite and esbuild. Karma had become a bottleneck.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the new world looks like (Vitest/Jest)
&lt;/h3&gt;

&lt;p&gt;Angular's experimental test runner, now powered by &lt;strong&gt;Vitest&lt;/strong&gt;, is the future. Migrating means your unit tests will run in a fast, modern Node.js-based environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "temporary fix" explained
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @angular-devkit/build-angular &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command forces the CLI to fall back to the old compiler that still supports Karma. It’s a compatibility bridge — but the message is clear: start planning your migration to Jest or Vitest soon.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting the update process, make sure you meet the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt;: Version &lt;code&gt;20.11.1&lt;/code&gt; or later
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt;: Version &lt;code&gt;5.8&lt;/code&gt; or later
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project backup&lt;/strong&gt;: Commit all current changes in Git
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. How to Update: CLI Command and Comparison
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Update Command
&lt;/h3&gt;

&lt;p&gt;Make sure you're running Node.js &lt;code&gt;v20.11.1&lt;/code&gt; or later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng update @angular/cli @angular/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use Angular Material:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng update @angular/cli @angular/core @angular/material
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manual intervention required
&lt;/h3&gt;

&lt;p&gt;To reinstall the old compiler with Karma support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @angular-devkit/build-angular &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wasn't required in earlier versions but is now &lt;strong&gt;mandatory&lt;/strong&gt; if you want to keep using Karma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compared to earlier upgrades
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Angular v19&lt;/strong&gt;: &lt;code&gt;ng update&lt;/code&gt; just worked.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular v20&lt;/strong&gt;: You must manually reinstall the old builder for Karma.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Control Flow: More Than Syntactic Sugar
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@for&lt;/code&gt; replaces &lt;code&gt;*ngFor&lt;/code&gt; and is a major improvement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Old syntax
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let item of items; trackBy: trackItemById"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {{ item.name }}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New syntax
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@for (item of items; track item.id) {
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;{{ item.name }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
} @empty {
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;No items to display.&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;track&lt;/code&gt; is &lt;strong&gt;mandatory&lt;/strong&gt; and encourages best practices.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@empty&lt;/code&gt; improves DX by removing the need for separate &lt;code&gt;@if&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Automated migration and performance
&lt;/h3&gt;

&lt;p&gt;Use the CLI to automatically refactor templates to the new control flow syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng generate @angular/core:control-flow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  General Best Practices and Further Migrations
&lt;/h3&gt;

&lt;p&gt;You can also migrate to other modern Angular features:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng generate @angular/core:standalone
ng generate @angular/core:inject
ng generate @angular/core:route-lazy-loading
ng generate @angular/core:signal-input-migration
ng generate @angular/core:signal-queries-migration
ng generate @angular/core:output-migration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands allow for a comprehensive update of an Angular app to leverage the latest patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Standalone by Default: A Fundamental Architectural Shift
&lt;/h2&gt;

&lt;p&gt;By explicitly listing dependencies using the &lt;code&gt;imports&lt;/code&gt; array at the component level, each component becomes self-contained. This:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clarifies your architecture&lt;/li&gt;
&lt;li&gt;Improves tree-shaking&lt;/li&gt;
&lt;li&gt;Results in smaller bundles&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Zoneless: Escaping the "Magic" of Change Detection
&lt;/h2&gt;

&lt;p&gt;In a zone-less world, the UI only updates when you explicitly tell it to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signals&lt;/strong&gt; are the main tool here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mySignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This directly tells Angular to update only the DOM parts that use that signal. It’s a &lt;strong&gt;surgical, predictable, and high-performance&lt;/strong&gt; approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. New Naming Convention: Why It Feels Complicated
&lt;/h2&gt;

&lt;p&gt;Angular 20 introduces a new official naming convention that &lt;strong&gt;drops traditional suffixes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Old naming
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="nx"&gt;highlight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New naming
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;       &lt;span class="c1"&gt;// UI component&lt;/span&gt;
&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;         &lt;span class="c1"&gt;// state&lt;/span&gt;
&lt;span class="nx"&gt;highlight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;          &lt;span class="c1"&gt;// directive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Focus on intent instead of type
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;         &lt;span class="c1"&gt;// HTTP requests&lt;/span&gt;
&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;       &lt;span class="c1"&gt;// reactive state&lt;/span&gt;
&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;       &lt;span class="c1"&gt;// UI component&lt;/span&gt;
&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;    &lt;span class="c1"&gt;// UI component&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Naming rules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;dashes&lt;/strong&gt;: &lt;code&gt;user-profile.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Match &lt;strong&gt;class and filename&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Keep &lt;code&gt;.spec.ts&lt;/code&gt; for tests&lt;/li&gt;
&lt;li&gt;Avoid generic names like &lt;code&gt;utils.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Co-locate&lt;/strong&gt; related files&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Feature-based folder structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── core/
│   └── auth/
│       ├── auth-store.ts
│       ├── login.ts
│       └── register.ts
├── features/
│   └── users/
│       ├── user-profile.ts
│       ├── user-api.ts
│       └── user-settings.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner Git diffs&lt;/li&gt;
&lt;li&gt;Intention-oriented code&lt;/li&gt;
&lt;li&gt;Easier onboarding&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Important Detail: &lt;code&gt;browserslist&lt;/code&gt; and Browser Support
&lt;/h2&gt;

&lt;p&gt;Angular 20 &lt;strong&gt;no longer supports Opera&lt;/strong&gt; officially.&lt;br&gt;&lt;br&gt;
If you list Opera in your &lt;code&gt;browserslist&lt;/code&gt;, you may need to remove it.&lt;/p&gt;

&lt;p&gt;Other non-mainstream browsers may also lose support, potentially triggering warnings or build issues.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>typescript</category>
      <category>unittest</category>
    </item>
    <item>
      <title>From Vibe Coding to Vibe Engineering with V0 and Firebase Studio. [Part 0].</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Tue, 08 Apr 2025 18:48:10 +0000</pubDate>
      <link>https://dev.to/turingsoracle/from-vibe-coding-to-vibe-engineering-with-v0-and-firebase-part-0-2m8m</link>
      <guid>https://dev.to/turingsoracle/from-vibe-coding-to-vibe-engineering-with-v0-and-firebase-part-0-2m8m</guid>
      <description>&lt;h1&gt;
  
  
  Yes, you heard right
&lt;/h1&gt;

&lt;p&gt;In this tutorial, we’re going to crank up impostor syndrome to the max by building a full-stack web app using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firebase Auth&lt;/strong&gt; for authentication
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firestore&lt;/strong&gt; for real-time data storage
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase Hosting&lt;/strong&gt; so you can actually show your project and avoid the “it works on my machine” excuse&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase Studio&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this time, we’re not doing another “Login + Hello World.”&lt;/p&gt;

&lt;p&gt;We’re going to build something with purpose: a &lt;strong&gt;book lending and return management platform&lt;/strong&gt; for a public library.&lt;br&gt;
And yes, we’ll generate &lt;strong&gt;QR codes&lt;/strong&gt; to streamline returns.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase One: Planning and Goals
&lt;/h2&gt;

&lt;p&gt;A popular saying goes:&lt;br&gt;
&lt;strong&gt;You don’t start a house from the roof...&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
And even though Vercel’s V0 lets us begin with the UI, we’re going to do things properly.&lt;/p&gt;

&lt;p&gt;Before sending prompts, we’ll define what we’re building:&lt;/p&gt;

&lt;h3&gt;
  
  
  The What
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;library management app&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full CRUD for books
&lt;/li&gt;
&lt;li&gt;Book lending and return system
&lt;/li&gt;
&lt;li&gt;QR code generation for scannable loan identification
&lt;/li&gt;
&lt;li&gt;QR code reading to easily mark books as returned
&lt;/li&gt;
&lt;li&gt;(Optional) Social features to create a reading club where users can exchange books and experiences&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Why
&lt;/h3&gt;

&lt;p&gt;We aim to solve a real problem: managing a &lt;strong&gt;public or community library&lt;/strong&gt; in a simple, modern, and digital way — and encourage reading habits.&lt;/p&gt;

&lt;p&gt;Also, it’s a great excuse to practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14/15&lt;/strong&gt; architecture
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;V0-generated UI components&lt;/strong&gt; (which we’ll refine manually later)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase as backend&lt;/strong&gt; (although you could swap it for something else)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRUD best practices&lt;/strong&gt; (create, read, update, delete)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Premise
&lt;/h2&gt;

&lt;p&gt;We want to manage book check-ins and check-outs from a physical location and create a small community that works like a book club.&lt;/p&gt;

&lt;p&gt;Manage the borrowing and returning of books in a public library.&lt;br&gt;
All this using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://v0.dev" rel="noopener noreferrer"&gt;v0.dev&lt;/a&gt; for quick UI creation with style
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; as the web framework, also used by V0
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase&lt;/strong&gt; for authentication, database, and hosting
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase Studio&lt;/strong&gt; (Optional alternative to v0)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR codes&lt;/strong&gt; to ease the physical return of books, using

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/yudiel/react-qr-scanner" rel="noopener noreferrer"&gt;&lt;code&gt;yudiel/react-qr-scanner&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zpao/qrcode.react" rel="noopener noreferrer"&gt;&lt;code&gt;qrcode.react&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Logic
&lt;/h2&gt;

&lt;p&gt;We assume there will be a &lt;strong&gt;librarian role&lt;/strong&gt; — someone responsible for books. &lt;br&gt;
This person’s responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registering new books
&lt;/li&gt;
&lt;li&gt;Updating stock
&lt;/li&gt;
&lt;li&gt;Correcting input errors
&lt;/li&gt;
&lt;li&gt;Removing availability of certain books
&lt;/li&gt;
&lt;li&gt;Checking return status (condition, timeliness)
&lt;/li&gt;
&lt;li&gt;Tracking book locations (e.g., Sci-Fi shelf 2)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a &lt;strong&gt;user&lt;/strong&gt;, I want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for a book and check if it’s available&lt;/li&gt;
&lt;li&gt;The homepage should display a searchable list of books by &lt;strong&gt;name, ISBN, or category&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Know where a book is physically located&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another scenario: the user finds the book and &lt;strong&gt;scans the QR code&lt;/strong&gt; to request a loan. &lt;br&gt;
To do this, they must &lt;strong&gt;sign in or register&lt;/strong&gt; — since managing libraries or book clubs requires some form of membership or ID.&lt;/p&gt;

&lt;p&gt;To simplify, all books can be borrowed, and the &lt;strong&gt;Google account&lt;/strong&gt; used to request them will serve as identification.&lt;/p&gt;




&lt;h2&gt;
  
  
  Other Considerations: “Security”
&lt;/h2&gt;

&lt;p&gt;This includes both &lt;strong&gt;physical&lt;/strong&gt; and &lt;strong&gt;digital&lt;/strong&gt; security and depends on the specific library’s operations.&lt;/p&gt;

&lt;p&gt;In public libraries, there’s usually a front desk with a librarian who grants access to the reading area. &lt;br&gt;
They assign books by &lt;strong&gt;membership number&lt;/strong&gt; or personal data.&lt;/p&gt;

&lt;p&gt;If the user wants to take a book home:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It must be &lt;strong&gt;scanned and assigned&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The system may also send return details and deadlines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Digitally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users must &lt;strong&gt;log in&lt;/strong&gt; to borrow a book&lt;/li&gt;
&lt;li&gt;Protect routes so only admins access core CRUD operations.&lt;/li&gt;
&lt;li&gt;Optionally, implement a &lt;strong&gt;reputation system&lt;/strong&gt; that limits the number of loans based on:

&lt;ul&gt;
&lt;li&gt;Account age
&lt;/li&gt;
&lt;li&gt;Verification status
&lt;/li&gt;
&lt;li&gt;Membership validity
&lt;/li&gt;
&lt;li&gt;Loan and return history
&lt;/li&gt;
&lt;li&gt;Return timeliness&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;With Firebase, it’s crucial to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure documents properly.&lt;/li&gt;
&lt;li&gt;Define security rules so only authorized roles can read, write, or delete certain documents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(This section will be expanded in future articles.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;After all this planning, we’ve essentially written a &lt;strong&gt;pseudocode-like spec&lt;/strong&gt; for our app.&lt;/p&gt;

&lt;p&gt;So in the &lt;strong&gt;next article&lt;/strong&gt;, we’ll set up everything from Firebase to V0, use alternative Firebase Studio, and build the first prompt based on pseudocode.&lt;/p&gt;

&lt;p&gt;In future posts, we’ll explore &lt;strong&gt;Copilot, Cursor,&lt;/strong&gt; and other AI tools to &lt;strong&gt;accelerate development&lt;/strong&gt; — because at the end of the day, &lt;strong&gt;AI is a tool, not a replacement.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>v0</category>
      <category>webdev</category>
      <category>firebasestudio</category>
    </item>
    <item>
      <title>The Future of FrontEnd Is Written... with Prompts</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Wed, 26 Mar 2025 09:21:33 +0000</pubDate>
      <link>https://dev.to/turingsoracle/the-future-of-frontend-is-written-with-prompts-2cle</link>
      <guid>https://dev.to/turingsoracle/the-future-of-frontend-is-written-with-prompts-2cle</guid>
      <description>&lt;p&gt;As you may know, after several iterations, v0 no longer just centers divs.&lt;br&gt;
It now raises a question that makes many feel uncomfortable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To what extent can—or should—artificial intelligence replace the work of a frontend developer?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is v0?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://v0.dev" rel="noopener noreferrer"&gt;v0.dev&lt;/a&gt; is a platform developed by Vercel that allows you to generate full frontend components from natural language descriptions. It's a sort of &lt;em&gt;visual copilot&lt;/em&gt; that combines design and implementation, returning clean code using React, Tailwind, and other modern stacks.&lt;/p&gt;

&lt;p&gt;What sets v0 apart from other generators is its semantic precision. It understands the context of the request, provides coherent structures, and offers visually well-designed solutions.&lt;/p&gt;

&lt;p&gt;It doesn't generate "random code"; it generates useful components, aligned with what the prompt suggests and how it's written.&lt;/p&gt;

&lt;p&gt;Some time ago, the prompt used by v0 from Vercel to build interfaces from plain text was leaked. You can take a look &lt;a href="https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/tree/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Despite causing a stir, the leak uncovered the true power of this tool: context.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a prompt?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;prompt&lt;/strong&gt; is the instruction given to a language model to perform a task.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A registration form with validation, dark mode, and mobile-first design."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The power of a prompt doesn't just lie in &lt;em&gt;what&lt;/em&gt; is being asked, but in &lt;em&gt;how&lt;/em&gt; it is asked.&lt;br&gt;
Clear language, explicit intentions, and well-defined context are key to obtaining useful results.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is context?
&lt;/h2&gt;

&lt;p&gt;Technically speaking, &lt;strong&gt;context&lt;/strong&gt; is the additional information that accompanies a prompt and allows the model to more precisely "understand" what is expected.&lt;/p&gt;

&lt;p&gt;It may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The desired stack (React, Next.js, Tailwind)&lt;/li&gt;
&lt;li&gt;Accessibility considerations&lt;/li&gt;
&lt;li&gt;Expected component behavior&lt;/li&gt;
&lt;li&gt;Technical or design constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;v0 uses an advanced &lt;em&gt;prompt engineering&lt;/em&gt; system with enriched context, which enables it to generate functional code relevant to the project environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Vibe Coding?
&lt;/h2&gt;

&lt;p&gt;The concept of &lt;strong&gt;vibe coding&lt;/strong&gt; refers to a new way of programming guided more by intention and creative energy than by manually writing every line of code.&lt;/p&gt;

&lt;p&gt;With tools like v0, the development experience begins to feel more like &lt;em&gt;composing music&lt;/em&gt; than coding line by line.&lt;/p&gt;

&lt;p&gt;The flow shifts: it becomes a collaboration between human and AI, where intuition and technical judgment remain essential.&lt;/p&gt;

&lt;p&gt;And v0 isn't alone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cursor&lt;/strong&gt; transforms Visual Studio Code into a conversational environment, allowing you to edit, navigate, and write code directly with AI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude&lt;/strong&gt; enables reasoning over complex structures and high-level refactoring, very useful for abstract frontend tasks like architecture design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Copilot&lt;/strong&gt; continues to act as a line-level assistant, suggesting snippets and completing code as you type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these tools are part of the new development environment—one where human ingenuity and algorithmic efficiency meet at the center of the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The End of the Front-End Dev?
&lt;/h2&gt;

&lt;p&gt;Personally, the approach I like most regarding artificial intelligence is &lt;strong&gt;augmenting capabilities&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Automating without understanding what is being done can be a dangerous trap, often generating more technical debt than real value.&lt;/p&gt;

&lt;p&gt;v0 doesn't replace the frontend developer, but it does require them to evolve.&lt;br&gt;
The role shifts from implementer to &lt;strong&gt;curator, architect, and interface strategist&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Writing a good prompt, understanding the project context and its logic, testing its security, validating accessibility, fixing errors generated by AI implementations, optimizing performance…&lt;br&gt;
All of that is still part of the job.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Artificial intelligence doesn't eliminate frontend development. It transforms it.&lt;br&gt;&lt;br&gt;
And those who understand that transformation will be the ones to lead it—rather than resist it.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>promptengineering</category>
      <category>vibecoding</category>
      <category>v0</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Seamless Reactive HTTP Requests in Angular</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Tue, 18 Mar 2025 10:49:21 +0000</pubDate>
      <link>https://dev.to/turingsoracle/seamless-reactive-http-requests-in-angular-2ihh</link>
      <guid>https://dev.to/turingsoracle/seamless-reactive-http-requests-in-angular-2ihh</guid>
      <description>&lt;p&gt;Starting from Angular v19.2, we can begin to move away from manually handling API calls thanks to Angular's new primitive: &lt;code&gt;httpResource&lt;/code&gt;. It allows us to reactively fetch data, calling our preferred API automatically each time the value changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main features:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Automatic Reactivity:&lt;br&gt;
The resource generated by httpResource observes signals and automatically makes HTTP requests each time reactive dependencies change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Default state:&lt;br&gt;
Allows defining default values through the defaultValue property, ensuring a consistent response during initial states, loading phases, or request errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data validation and transformation:&lt;br&gt;
The parse option facilitates automatic validation and transformation of HTTP responses, enhancing type safety and ensuring the integrity of received data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advantages over the traditional approach:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Significant code reduction: Eliminates the need to manually manage subscriptions, reducing errors such as memory leaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic state updates: By directly depending on Signals, data updates automatically according to changes in the application's reactive state, eliminating manual tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Increased security: Promotes robust development through automatic validation and strict state management throughout all phases of the data lifecycle.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Currently, this API is in an experimental phase, so it's recommended to monitor its evolution before implementing it in critical production environments.&lt;/p&gt;




&lt;h1&gt;
  
  
  Usage and implementation example:
&lt;/h1&gt;

&lt;p&gt;Previously, we had to rely on RxJS to subscribe and unsubscribe each time we made an API call, which sometimes contributed to the famous memory leaks when we forgot to unsubscribe.&lt;/p&gt;

&lt;p&gt;To implement it, we should start by creating an interface defining the structure of our character with data such as the ID, name, image, etc.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now we implement httpResource in our component.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;characterResource&lt;/code&gt; is an &lt;code&gt;httpResourceRef&lt;/code&gt; that returns character data from the API; &lt;code&gt;defaultValue&lt;/code&gt; ensures that &lt;code&gt;characterResource&lt;/code&gt; has a defined structure even before the data is loaded.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
characterId&lt;/code&gt; is a signal representing the ID of the character being displayed. Changing this value triggers &lt;code&gt;httpResource&lt;/code&gt; to fetch data for the selected character.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;But what if we want to use POST, PUT, DELETE?&lt;/p&gt;

&lt;p&gt;We only need to change the method and provide the corresponding body along with the params.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;usersResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RickCharacter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;per_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next article, I'll cover more advanced aspects like &lt;code&gt;headers&lt;/code&gt;, &lt;code&gt;params&lt;/code&gt;, etc., but for now you can see all the functional code in the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/stackblitz-angularhttpresource?embed=1&amp;amp;file=src%2Frickandmoty.component.ts" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Proyect Fugu</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Mon, 25 Nov 2024 14:00:00 +0000</pubDate>
      <link>https://dev.to/turingsoracle/proyect-fugu-4e2j</link>
      <guid>https://dev.to/turingsoracle/proyect-fugu-4e2j</guid>
      <description>&lt;p&gt;Aims to bridge the gap between progressive web applications (PWAs) and native applications, making PWAs more useful, appealing, and accessible to everyone. This effort is a collaboration between the Chromium community and companies such as Google, Microsoft, and other contributors from the broader web community.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are PWAs?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PWAs&lt;/strong&gt; are web applications designed to be fast, reliable, and capable of being installed on devices as if they were native applications. They use modern APIs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhance capabilities:&lt;/strong&gt; Access advanced hardware and features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensure reliability:&lt;/strong&gt; Load quickly and work seamlessly, even offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplify installation:&lt;/strong&gt; Behave like traditional apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these enhancements, PWAs combine the best of the web and native applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why "Fugu Project"?
&lt;/h2&gt;

&lt;p&gt;The name "Fugu" refers to the Japanese pufferfish, known for being delicious but dangerous if not prepared correctly. This symbolism captures the essence of the project: the new APIs can be very powerful, but if not implemented carefully, they can pose risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of advanced capabilities and risks:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Advanced capabilities:&lt;/strong&gt; File system access, video editing tools, integration with Bluetooth and USB devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potential risks:&lt;/strong&gt; These tools must ensure user security and privacy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Fugu Project focuses on enabling these capabilities while maintaining a balance between utility and security.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key APIs in the Fugu Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;File System Access API:&lt;/strong&gt; Allows applications to read and write files directly on the user's system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Share API and Web Share Target API:&lt;/strong&gt; Facilitates sharing content between web and native apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contact Picker API:&lt;/strong&gt; Provides access to device contacts with explicit permission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Bluetooth and Web USB:&lt;/strong&gt; Enables connection with physical devices to extend functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Badging API:&lt;/strong&gt; Displays notifications and counts on the installed app's icon.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Benefits of the Fugu Project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Universal compatibility:&lt;/strong&gt; PWAs work on any device with a browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hassle-free updates:&lt;/strong&gt; Always up-to-date without requiring downloads from an app store.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better user experience:&lt;/strong&gt; Access to features previously exclusive to native apps.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Security and the Future of PWAs
&lt;/h2&gt;

&lt;p&gt;The Fugu Project aims to expand PWA capabilities securely. It works to mitigate risks through explicit permissions and the development of responsible practices for developers.&lt;/p&gt;

&lt;p&gt;With Fugu, PWAs are evolving beyond being mere web versions. They are a powerful tool transforming how we interact with technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Via App the easy way to personalize macros and Keytes &lt;a href="https://usevia.app/" rel="noopener noreferrer"&gt;https://usevia.app/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Momentum website &lt;a href="https://momentum-fw.dev/" rel="noopener noreferrer"&gt;https://momentum-fw.dev/&lt;/a&gt; uses the Web USB API to install an alternative firmware to the default one on FlipperZero.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More examples and inspiration at:&lt;br&gt;
&lt;a href="https://developer.chrome.com/docs/capabilities/fugu-showcase" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/capabilities/fugu-showcase&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>fugu</category>
      <category>chromium</category>
      <category>devtools</category>
    </item>
    <item>
      <title>What's New Angular 19:</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Tue, 19 Nov 2024 15:47:47 +0000</pubDate>
      <link>https://dev.to/turingsoracle/whats-new-angular-19-3fe9</link>
      <guid>https://dev.to/turingsoracle/whats-new-angular-19-3fe9</guid>
      <description>&lt;p&gt;Angular is constantly evolving, and version 19 is no exception. With a focus on developer experience, improved performance, and new tools, Angular 19 offers features to streamline your projects and enhance efficiency. In this article, we’ll explore improvements in reactivity with &lt;strong&gt;signals&lt;/strong&gt;, rendering optimizations, and much more. This marks the eleventh iteration since version 8, one of the first articles on this blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Standalone Components as the Default Standard
&lt;/h2&gt;

&lt;p&gt;Standalone components, introduced in Angular 14, have been revolutionary, and now in Angular 19, they are the default behavior. This means you no longer need to declare &lt;code&gt;standalone: true&lt;/code&gt; for each component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before Angular 19:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CommonModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;standalone-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./standalone-component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StandaloneComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CommonModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;standalone-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./standalone-component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StandaloneComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This eliminates the need for NgModules in most cases, simplifying application structure and promoting modular development. If you still need to work with NgModules, you can explicitly declare &lt;code&gt;standalone: false&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Partial and Incremental Hydration for Faster Rendering
&lt;/h2&gt;

&lt;p&gt;Angular 19 introduces partial and incremental hydration, transforming the performance of server-rendered (SSR) applications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partial Hydration:&lt;/strong&gt; Prioritizes critical component loading, reducing initial interaction time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental Hydration:&lt;/strong&gt; Defers feature loading based on user interactions (clicks or hovers), optimizing resource usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These techniques create faster, more interactive applications right from the start, improving the user experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0r7o1f4laq0yl0vz4yhy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0r7o1f4laq0yl0vz4yhy.gif" alt="Progresive Rehydration" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Enhanced Signals: Simplifying Reactivity
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Signals&lt;/strong&gt; integration in Angular continues to improve, now with deeper support and new tools like &lt;strong&gt;LinkedSignal&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are signals?
&lt;/h3&gt;

&lt;p&gt;Signals are an API designed to manage states reactively and predictably, reducing reliance on Zone.js. This not only simplifies debugging but also improves performance and reduces bundle size.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example with Signals: Introducing LinkedSignal
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;linkedSignal&lt;/code&gt; allows the creation of dependent signals that automatically update based on a source signal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;linkedSignal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;linkedSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;double&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 20&lt;/span&gt;
&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;double&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Improvements to Component API
&lt;/h2&gt;

&lt;p&gt;Angular 19 introduces a new lifecycle hook, &lt;code&gt;ngAfterSignalUpdate&lt;/code&gt;, to react after a Signal update, simplifying interactions with complex states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AfterSignalUpdate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-lifecycle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h3&amp;gt;Signal Lifecycle &amp;lt;/h3&amp;gt;
    &amp;lt;button (click)="updateSignal()"&amp;gt;Update&amp;lt;/button&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SignalLifecycleComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AfterSignalUpdate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mySignal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;updateSignal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mySignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mySignal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngAfterSignalUpdate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Signal updated to:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mySignal&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This hook helps developers manage UI changes and complex state interactions effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Faster Build Times
&lt;/h2&gt;

&lt;p&gt;Thanks to optimizations in Angular CLI, builds are faster in both development and production environments. The addition of caching accelerates iterative processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Build with Cache&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng build &lt;span class="nt"&gt;--optimization&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--build-cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Dependency Injection Enhancements
&lt;/h2&gt;

&lt;p&gt;Angular now automatically infers types in Dependency Injection (DI), reducing repetitive code and increasing type safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Type Inference in DI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// Now in Angular 19&lt;/span&gt;
&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Resource and rxResource APIs: Simplifying Async Data
&lt;/h2&gt;

&lt;p&gt;The new experimental &lt;strong&gt;resource&lt;/strong&gt; and &lt;strong&gt;rxResource&lt;/strong&gt; APIs are designed for promises and observables, simplifying asynchronous data handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Properties of &lt;code&gt;resource&lt;/code&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Status:&lt;/strong&gt; Tracks resource state (loading, success, or error).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value:&lt;/strong&gt; Contains data after loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error:&lt;/strong&gt; Handles errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example with &lt;code&gt;rxResource&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rxResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rxResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tools unify asynchronous data management, making workflows more intuitive.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Improved Routing
&lt;/h2&gt;

&lt;p&gt;Angular 19 integrates signals more deeply with the router, enabling more reactive and streamlined navigation flows. This simplifies handling route and query parameters reactively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Using Signals with Router&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-signal-route&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h2&amp;gt;Signal Route&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;Route ID: {{ routeSignal() }}&amp;lt;/p&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RouteDemoComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;routeSignal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paramMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;routeSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus: Angular Material Enhancements
&lt;/h2&gt;

&lt;p&gt;Angular Material introduces new style improvements, accessibility features, and enhanced component interactions. For example, components like &lt;code&gt;mat-menu&lt;/code&gt; and &lt;code&gt;mat-select&lt;/code&gt; are now more intuitive and user-friendly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Improved &lt;code&gt;mat-menu&lt;/code&gt; Usage&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;mat-button&lt;/span&gt; &lt;span class="na"&gt;[matMenuTriggerFor]=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Menu&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;mat-menu&lt;/span&gt; &lt;span class="na"&gt;#menu&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;&lt;span class="na"&gt;matMenu&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;mat-menu-item&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;mat-menu-item&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;mat-menu-item&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/mat-menu&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Angular 19 marks a significant step in the evolution of the framework. From default standalone components to improved reactivity with signals and SSR optimizations, this version provides tools to build faster, more reactive, and maintainable applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready to upgrade?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng update @angular/core @angular/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;more info about update here:&lt;a href="https://angular.dev/update-guide/?v=18.0-19.0&amp;amp;l=1" rel="noopener noreferrer"&gt;https://angular.dev/update-guide/?v=18.0-19.0&amp;amp;l=1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Share your experience&lt;/strong&gt; with these new features and keep exploring the future of Angular development! 🚀, Stay tuned for upcoming articles deep down about Material, Signals and of course Hydration&lt;/p&gt;

&lt;p&gt;¡Thanks to &lt;a class="mentioned-user" href="https://dev.to/damiansire"&gt;@damiansire&lt;/a&gt; for being the editor and approving this post!&lt;/p&gt;

</description>
      <category>news</category>
      <category>angular</category>
      <category>angular19</category>
      <category>webdev</category>
    </item>
    <item>
      <title>12 HTML Tricks You Probably Don't Know About</title>
      <dc:creator>Antonio Cardenas </dc:creator>
      <pubDate>Mon, 09 Sep 2024 22:48:22 +0000</pubDate>
      <link>https://dev.to/turingsoracle/12-html-tricks-you-probably-dont-know-about-584i</link>
      <guid>https://dev.to/turingsoracle/12-html-tricks-you-probably-dont-know-about-584i</guid>
      <description>&lt;p&gt;HTML is the backbone of the web, but it's far more than just a set of basic tags and attributes. There are tons of hidden features in HTML that can make your websites more interactive, accessible, and efficient. Ready to level up your HTML skills? Let's dive into these cool tricks!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;contenteditable&lt;/code&gt; - Make Elements Editable
&lt;/h3&gt;

&lt;p&gt;Did you know you can make any HTML element directly editable by the user? The &lt;code&gt;contenteditable&lt;/code&gt; attribute allows you to do just that. Whether you're building a CMS, an interactive blog, or a live text editor, this attribute can save you loads of time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;contenteditable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;You can edit this text. Give it a try!
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Enhance user engagement by allowing them to edit content directly on the page. No need for complex JavaScript!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Custom Data Attributes - Store Extra Info on Elements
&lt;/h3&gt;

&lt;p&gt;If you've ever needed a way to store custom data within an HTML element, custom data attributes are for you. These attributes, prefixed with &lt;code&gt;data-&lt;/code&gt;, let you add extra information that you can access via JavaScript, without cluttering your DOM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"user-profile"&lt;/span&gt; &lt;span class="na"&gt;data-user-id=&lt;/span&gt;&lt;span class="s"&gt;"42"&lt;/span&gt; &lt;span class="na"&gt;data-role=&lt;/span&gt;&lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;! &lt;/span&gt;&lt;span class="na"&gt;-&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="na"&gt;User&lt;/span&gt; &lt;span class="na"&gt;details&lt;/span&gt; &lt;span class="na"&gt;go&lt;/span&gt; &lt;span class="na"&gt;here&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="na"&gt;div&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Perfect for dynamic applications that rely on metadata. Plus, it keeps your code clean!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The &lt;code&gt;hidden&lt;/code&gt; Attribute - Hide Elements Without CSS
&lt;/h3&gt;

&lt;p&gt;Forget using &lt;code&gt;display: none;&lt;/code&gt; in your stylesheets. The &lt;code&gt;hidden&lt;/code&gt; attribute is a more semantic way to hide elements. It's easy to use and helps keep your HTML tidy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This paragraph is visible.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This paragraph is hidden.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Use it with JavaScript to show or hide elements dynamically without worrying about styles.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; - Better Form Accessibility
&lt;/h3&gt;

&lt;p&gt;Forms can get messy, especially if they have many inputs. Enter &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt;. These tags help you group related controls together, providing a clear, accessible structure for all users, including those using screen readers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;fieldset&amp;gt;&lt;/span&gt;
&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;legend&amp;gt;&lt;/span&gt;Personal Information&lt;span class="nt"&gt;&amp;lt;/legend&amp;gt;&lt;/span&gt;
&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;First Name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; It's all about improving user experience. Structured forms are easier to navigate and understand!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;code&gt;download&lt;/code&gt; Attribute - Simplify File Downloads
&lt;/h3&gt;

&lt;p&gt;Want to offer a file download on your site? The &lt;code&gt;download&lt;/code&gt; attribute on an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag lets you do this seamlessly. You can even specify the filename that the file should be saved as.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"path/to/file.pdf"&lt;/span&gt; &lt;span class="na"&gt;download=&lt;/span&gt;&lt;span class="s"&gt;"myfile.pdf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Download the PDF&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Makes downloading files straightforward for your users. No need for extra server-side configurations!&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;code&gt;spellcheck&lt;/code&gt; - Enable Spell Checking in Text Inputs
&lt;/h3&gt;

&lt;p&gt;Ever wanted to add spell-checking to your text inputs or textareas? The &lt;code&gt;spellcheck&lt;/code&gt; attribute lets you turn on the browser's built-in spell checker. This can be super useful for enhancing user experience by reducing typos and mistakes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;spellcheck=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This textarea will be spell-checked!&lt;span class="nt"&gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Make sure users always have a great experience by helping them avoid embarrassing typos.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. &lt;code&gt;inputmode&lt;/code&gt; - Improve Mobile Input
&lt;/h3&gt;

&lt;p&gt;Tailor the virtual keyboard for users on mobile devices using the &lt;code&gt;inputmode&lt;/code&gt; attribute. This attribute specifies what kind of input is expected, triggering a keyboard that's optimized for the type of data to be entered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;inputmode=&lt;/span&gt;&lt;span class="s"&gt;"numeric"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Enter your phone number"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Providing the right keyboard helps users enter data quickly and correctly. Great for mobile-friendly sites!&lt;/p&gt;

&lt;h3&gt;
  
  
  8. &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; - Create Native Expandable Content
&lt;/h3&gt;

&lt;p&gt;Need to create expandable content without relying on JavaScript? The &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; elements offer a simple, built-in solution for collapsible sections. Perfect for FAQs, menus, or any other content that benefits from being hidden until needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;details&amp;gt;&lt;/span&gt;
&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;What is HTML?&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;HTML stands for HyperText Markup Language. It's the foundation of the web!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; This is a lightweight, accessible way to toggle content visibility without using JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. &lt;code&gt;draggable&lt;/code&gt; -Add Drag-and-Drop Functionality
&lt;/h3&gt;

&lt;p&gt;Want to add drag-and-drop functionality to your site? The user is able to drag elements with the "draggable" attribute. It's an easy way to introduce interactivity without needing external libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Draggable Image"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Combine &lt;code&gt;draggable&lt;/code&gt; with JavaScript events to create custom drag-and-drop experiences!&lt;/p&gt;

&lt;h3&gt;
  
  
  10. &lt;code&gt;type="date"&lt;/code&gt; - Simplify Date Input
&lt;/h3&gt;

&lt;p&gt;Instead of using text fields and JavaScript to manage dates, try using &lt;code&gt;&amp;lt;input type="date"&amp;gt;&lt;/code&gt;. This will bring up a native date picker in most modern browsers, making it easier for users to enter dates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"date"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"birthday"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Provides a consistent, easy-to-use interface for date input, no additional JavaScript required.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; - Optimize Images for Different Devices
&lt;/h3&gt;

&lt;p&gt;If you want to make your website faster and more responsive, use the &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; attributes on &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags. These attributes allow the browser to choose the most appropriate image based on the device's screen size and resolution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image-small.jpg"&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image-medium.jpg 768w, image-large.jpg 1200w"&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 768px) 100vw, (min-width: 769px) 50vw"&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Responsive Image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; Serve the right image for the right screen, reducing load times and improving the user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. &lt;code&gt;placeholder&lt;/code&gt; - Enhance Form Inputs with Hints
&lt;/h3&gt;

&lt;p&gt;Need to provide a hint or example for your form inputs? Use the &lt;code&gt;placeholder&lt;/code&gt; attribute to display a short hint inside an input field before the user enters a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"you@example.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; It helps users understand what input is expected without cluttering your form with extra text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Takeaway
&lt;/h3&gt;

&lt;p&gt;These HTML tricks show that there’s a lot more to HTML than meets the eye. Don’t just settle for the basics—explore and experiment with these features to build more dynamic, accessible, and user-friendly web pages. Dive in and start experimenting to discover all the cool things HTML can do!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>html</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
