<?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: Mani Movassagh</title>
    <description>The latest articles on DEV Community by Mani Movassagh (@manimovassagh).</description>
    <link>https://dev.to/manimovassagh</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F718496%2F3ed9bdb8-cf07-4de3-adb8-1cdadcfaffba.jpg</url>
      <title>DEV Community: Mani Movassagh</title>
      <link>https://dev.to/manimovassagh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manimovassagh"/>
    <language>en</language>
    <item>
      <title>MCP Explained: How AI Plus MCP Controls a Real Browser</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Thu, 26 Mar 2026 08:35:51 +0000</pubDate>
      <link>https://dev.to/manimovassagh/mcp-explained-how-claude-controls-a-real-browser-1m4j</link>
      <guid>https://dev.to/manimovassagh/mcp-explained-how-claude-controls-a-real-browser-1m4j</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;AI models like Claude are powerful — but they live inside a text box.&lt;/p&gt;

&lt;p&gt;By default, I can read your message, think, and reply. That's it. I cannot open a browser, click a button, fill a form, or take a screenshot. My "hands" stop at the conversation window.&lt;/p&gt;

&lt;p&gt;Developers worked around this by building custom integrations — glue code that connected AI to specific tools. Every team reinvented the wheel. There was no standard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without MCP:
  Claude ── custom glue ──► Playwright
  Claude ── custom glue ──► Supabase
  Claude ── custom glue ──► Gmail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every integration was one-off, fragile, and hard to maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  What MCP Is
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MCP stands for Model Context Protocol.&lt;/strong&gt; It is an open standard created by Anthropic that defines one consistent way for any AI to communicate with any external tool or service.&lt;/p&gt;

&lt;p&gt;Think of it like &lt;strong&gt;USB&lt;/strong&gt;. Before USB, every device had its own connector. After USB, one standard plug worked with everything. MCP does the same for AI tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;With MCP:
  Claude ── MCP ──► Playwright MCP Server ──► Browser
  Claude ── MCP ──► Supabase MCP Server   ──► Database
  Claude ── MCP ──► Gmail MCP Server      ──► Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same protocol. Different servers. Infinite tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Language: JSON
&lt;/h2&gt;

&lt;p&gt;MCP communicates using &lt;strong&gt;JSON messages&lt;/strong&gt; — structured text passed back and forth between Claude and an MCP server.&lt;/p&gt;

&lt;p&gt;When I want to navigate to a URL, I send this:&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;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_navigate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://google.com"&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 server executes the action and sends back a result:&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"navigated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://google.com"&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;That's it. No magic. Just JSON flying between two programs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The MCP Server: The Translator
&lt;/h2&gt;

&lt;p&gt;Raw Playwright has no idea what to do with my JSON. It doesn't speak MCP natively.&lt;/p&gt;

&lt;p&gt;That's where the &lt;strong&gt;Playwright MCP Server&lt;/strong&gt; comes in. It is a small program that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Listens for JSON messages from Claude&lt;/li&gt;
&lt;li&gt;Translates them into real Playwright API calls&lt;/li&gt;
&lt;li&gt;Controls the browser&lt;/li&gt;
&lt;li&gt;Sends results back to Claude
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude ──JSON──► Playwright MCP Server ──► Playwright ──► Browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP Server is the middleman. It bridges the gap between my structured messages and the actual browser automation library.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where It Runs: Your Machine, Not the Cloud
&lt;/h2&gt;

&lt;p&gt;This is a common misconception. The Playwright MCP Server does &lt;strong&gt;not&lt;/strong&gt; run on AWS, Anthropic's servers, or anywhere on the internet.&lt;/p&gt;

&lt;p&gt;It runs as a &lt;strong&gt;local process on your machine&lt;/strong&gt;, right alongside Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Machine
├── Claude Code
├── Playwright MCP Server  ← a Node.js process, running locally
└── Chrome / Firefox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code connects to it through a local socket or pipe. Your browser never leaves your machine unless you navigate to an external URL.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Claude Discovers Tools: The Handshake
&lt;/h2&gt;

&lt;p&gt;When Claude Code starts, it reads a config file (&lt;code&gt;.mcp.json&lt;/code&gt; or &lt;code&gt;settings.json&lt;/code&gt;) that lists available MCP servers:&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;"playwright"&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;"@playwright/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;Claude Code starts the process, then immediately asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What tools do you offer?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Playwright MCP Server replies with a full list of available tools and their parameters:&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;"tools"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_navigate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Navigate to a URL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&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;"url"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_click"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Click an element on the page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&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;"selector"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_take_screenshot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Take a screenshot of the current page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&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;Claude reads this list and now knows &lt;strong&gt;exactly&lt;/strong&gt; what it can ask Playwright to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Full Real Example: End to End
&lt;/h2&gt;

&lt;p&gt;Let's trace one complete action. You ask Claude:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Take a screenshot of google.com"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is every step that happens:&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="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;─────────────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Claude&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"screenshot google.com"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;──────────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Playwright&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&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;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_navigate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://google.com"&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="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;──────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Browser&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;playwright.goto(&lt;/span&gt;&lt;span class="s2"&gt;"https://google.com"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;──────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Claude&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"navigated"&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="mi"&gt;5&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;──────────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Playwright&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&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;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_take_screenshot"&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="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;──────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Claude&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;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;base64 encoded image data&amp;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="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;──────────────────►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;You&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;displays&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;screenshot&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;Two JSON calls. One visible result. Claude is orchestrating each step, deciding what to call next based on the previous response.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Claude Finds Elements: Visual Reasoning
&lt;/h2&gt;

&lt;p&gt;Simple selectors work fine when the HTML is clean:&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;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_click"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"selector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#submit-btn"&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;But real pages are rarely that clean:&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;"x7k2p"&lt;/span&gt; &lt;span class="na"&gt;data-v=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&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;No useful selector. So Claude takes a different approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calls &lt;code&gt;browser_take_screenshot&lt;/code&gt; — receives a &lt;strong&gt;base64 image&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visually inspects the image&lt;/strong&gt; — Claude is multimodal, it can see&lt;/li&gt;
&lt;li&gt;Locates the button by its appearance and position&lt;/li&gt;
&lt;li&gt;Clicks using pixel coordinates
&lt;/li&gt;
&lt;/ol&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;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser_click"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"coordinate"&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="mi"&gt;842&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;560&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;No CSS selector needed. Claude reasons the same way a human would — it sees a blue "Submit" button in the bottom right and clicks there.&lt;/p&gt;

&lt;p&gt;This is the loop that makes MCP powerful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude ──► screenshot ──► [sees, thinks] ──► click ──► [sees, thinks] ──► next step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Snapshot vs Screenshot: Choosing the Right Tool
&lt;/h2&gt;

&lt;p&gt;Taking a screenshot on every step is expensive — images are large and slow to process.&lt;/p&gt;

&lt;p&gt;Playwright MCP offers a smarter alternative: &lt;code&gt;browser_snapshot&lt;/code&gt;. Instead of an image, it returns the &lt;strong&gt;accessibility tree&lt;/strong&gt; of the page as text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button "Submit" [id=submit-btn] at (842, 560)
input "Email" [id=email] at (400, 300)
link "Forgot password?" at (400, 400)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives Claude exact element references, names, and positions — without processing a full image.&lt;/p&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 see visual layout or styling&lt;/td&gt;
&lt;td&gt;&lt;code&gt;browser_take_screenshot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to find and interact with elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;browser_snapshot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging a visual bug&lt;/td&gt;
&lt;td&gt;&lt;code&gt;browser_take_screenshot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fast, efficient automation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;browser_snapshot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  MCP vs Writing Your Own Playwright Script
&lt;/h2&gt;

&lt;p&gt;Both can automate a browser. So when do you use each?&lt;/p&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;One-off task: "grab this data for me"&lt;/td&gt;
&lt;td&gt;MCP — no code needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repeatable test in CI/CD&lt;/td&gt;
&lt;td&gt;Playwright script — version controlled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging a flaky test interactively&lt;/td&gt;
&lt;td&gt;MCP — Claude reasons step by step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production test suite&lt;/td&gt;
&lt;td&gt;Playwright script — no AI dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The core difference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MCP              = Claude drives the browser live, reasoning at each step
Playwright script = code drives the browser, no AI at runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here is the most powerful pattern — &lt;strong&gt;use both together&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use MCP to explore the page, figure out the right selectors and flow, then ask Claude to write the Playwright script based on what it just learned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You get the best of both worlds: AI-assisted discovery, production-grade output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting It Up Yourself
&lt;/h2&gt;

&lt;p&gt;Getting Playwright MCP running takes three steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install the MCP server&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;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @playwright/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Add it to your Claude Code config&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create or edit &lt;code&gt;.mcp.json&lt;/code&gt; in your project root:&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;"playwright"&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;"@playwright/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;&lt;strong&gt;3. Restart Claude Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude Code will automatically start the server, perform the handshake, and add all Playwright tools to its capabilities.&lt;/p&gt;

&lt;p&gt;Now try it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Go to github.com and take a screenshot"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude will navigate, capture, and show you the result — no code written, no script run.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Now Know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MCP is a standard protocol — the USB of AI tools&lt;/li&gt;
&lt;li&gt;It uses simple JSON messages over a local connection&lt;/li&gt;
&lt;li&gt;The MCP Server is a translator between Claude and the real tool&lt;/li&gt;
&lt;li&gt;Everything runs locally on your machine&lt;/li&gt;
&lt;li&gt;Claude discovers tools automatically via a handshake at startup&lt;/li&gt;
&lt;li&gt;Claude reasons visually between steps — it sees, thinks, then acts&lt;/li&gt;
&lt;li&gt;MCP is for interactive exploration; scripts are for production automation&lt;/li&gt;
&lt;li&gt;The killer combo: use MCP to discover, then generate a script&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>playwright</category>
    </item>
    <item>
      <title>🧰 Springman – A Fast Go CLI to Boost Your Spring Boot Development 🚀</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Mon, 09 Jun 2025 18:14:56 +0000</pubDate>
      <link>https://dev.to/manimovassagh/springman-a-fast-go-cli-to-boost-your-spring-boot-development-9gi</link>
      <guid>https://dev.to/manimovassagh/springman-a-fast-go-cli-to-boost-your-spring-boot-development-9gi</guid>
      <description>&lt;p&gt;If you're a Java developer who builds Spring Boot applications regularly, chances are you're tired of clicking through start.spring.io or managing repetitive tasks manually.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Springman&lt;/strong&gt; comes in — a lightweight CLI tool written in Go that lets you:&lt;/p&gt;

&lt;p&gt;✅ Generate Spring Boot projects&lt;br&gt;&lt;br&gt;
✅ Run them instantly with Maven or Gradle&lt;br&gt;&lt;br&gt;
✅ Add or remove dependencies from &lt;code&gt;pom.xml&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ Build once and use from anywhere  &lt;/p&gt;




&lt;h2&gt;
  
  
  🌱 Why Springman?
&lt;/h2&gt;

&lt;p&gt;As a full-stack developer, I often found myself switching between front-end and backend work, and I wanted something &lt;strong&gt;blazing fast&lt;/strong&gt;, &lt;strong&gt;offline-capable&lt;/strong&gt;, and super clean for bootstrapping Java projects.&lt;/p&gt;

&lt;p&gt;So I built &lt;code&gt;springman&lt;/code&gt;, and I open-sourced it here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/manimovassagh/Springman" rel="noopener noreferrer"&gt;GitHub – manimovassagh/Springman&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;springman new myapp --build maven&lt;/code&gt; → create a Spring Boot project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;springman run myapp&lt;/code&gt; → run it with Maven or Gradle (auto-detected)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;springman add myapp group:artifact[:version]&lt;/code&gt; → add dependency to &lt;code&gt;pom.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;springman remove myapp group:artifact&lt;/code&gt; → remove it from &lt;code&gt;pom.xml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All XML operations are safely parsed and formatted. You’ll never break your &lt;code&gt;pom.xml&lt;/code&gt; again 😎&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Quick Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/manimovassagh/Springman.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Springman
go build &lt;span class="nt"&gt;-o&lt;/span&gt; springman
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;springman /usr/local/bin/
springman &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💚 Built With&lt;br&gt;
    • Go 1.21+&lt;br&gt;
    • Cobra CLI&lt;br&gt;
    • Standard XML library&lt;br&gt;
    • Lots of ☕ and love&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🙌 Contribute or Fork It&lt;/p&gt;

&lt;p&gt;Feel free to:&lt;br&gt;
    • Fork the project&lt;br&gt;
    • Suggest features (Gradle DSL support? Native Image runner?)&lt;br&gt;
    • Drop a ⭐ if you like it&lt;/p&gt;

&lt;p&gt;⸻&lt;br&gt;
If you like please give an start to support project ⭐⭐⭐&lt;br&gt;
Made with ❤️ by &lt;a href="https://github.com/manimovassagh" rel="noopener noreferrer"&gt;Mani Movassagh&lt;/a&gt;&lt;br&gt;
🔗 GitHub&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/manimovassagh/Springman" rel="noopener noreferrer"&gt;https://github.com/manimovassagh/Springman&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>springboot</category>
      <category>java</category>
      <category>cli</category>
    </item>
    <item>
      <title>From Java to .NET: A Journey of Curiosity, Confusion, and Compilation</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Sun, 08 Jun 2025 16:39:58 +0000</pubDate>
      <link>https://dev.to/manimovassagh/from-java-to-net-a-journey-of-curiosity-confusion-and-compilation-p72</link>
      <guid>https://dev.to/manimovassagh/from-java-to-net-a-journey-of-curiosity-confusion-and-compilation-p72</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;💬 &lt;em&gt;"Java is to C# what Kaffee is to Kaffe... one is just smoother in .NET."&lt;/em&gt;&lt;br&gt;&lt;br&gt;
– Every confused Java dev ever&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ☕ Why I (a Java Dev) Looked at .NET and Thought: "Wait... You Too?"
&lt;/h2&gt;

&lt;p&gt;If you're a seasoned Java developer like me, you’ve probably been living in the world of Spring Boot, JVM tuning, and curly braces for breakfast. Life was good… until one day, a .NET developer casually said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We have dependency injection, too."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hold up. You what?&lt;br&gt;&lt;br&gt;
So began my quest to discover what lies in the realm of Microsoft’s ecosystem. Spoiler alert: It's not just Windows Forms anymore.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎒 Packing the Java Backpack
&lt;/h2&gt;

&lt;p&gt;Before entering the land of C# and &lt;code&gt;Program.cs&lt;/code&gt;, here’s what I brought with me from Java:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ OOP experience
&lt;/li&gt;
&lt;li&gt;✅ Familiarity with Spring Boot (which helps a LOT)
&lt;/li&gt;
&lt;li&gt;✅ Love for annotations (a.k.a. attributes in .NET)
&lt;/li&gt;
&lt;li&gt;✅ And that deep, unexplainable bond with IntelliJ IDEA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I also brought along:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ A few biases (thinking C# is just “Java with a Microsoft logo”)
&lt;/li&gt;
&lt;li&gt;❌ The trauma of &lt;code&gt;NullPointerException&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;❌ And a tendency to Ctrl+Shift+R like it works in Visual Studio&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🚀 Starting with .NET 8 (Yes, Jump to the Latest!)
&lt;/h2&gt;

&lt;p&gt;.NET has matured—like wine or that annoying cousin who’s now a billionaire. .NET 8 is cross-platform, fast, and comes with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧱 Minimal APIs (hello, Lambda-lovers)
&lt;/li&gt;
&lt;li&gt;🔥 Native AOT (yes, your app can be fast and tiny)
&lt;/li&gt;
&lt;li&gt;🐳 First-class Docker support
&lt;/li&gt;
&lt;li&gt;🧪 Great testing tools out of the box
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're used to Maven and Gradle, fear not. &lt;code&gt;dotnet CLI&lt;/code&gt; is your new best friend. Think &lt;code&gt;dotnet new&lt;/code&gt;, &lt;code&gt;dotnet build&lt;/code&gt;, &lt;code&gt;dotnet run&lt;/code&gt;, and you're off to the races.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 C# vs Java: Same But Different
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Java&lt;/th&gt;
&lt;th&gt;C#&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Interfaces&lt;/td&gt;
&lt;td&gt;Yep&lt;/td&gt;
&lt;td&gt;Yep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambdas&lt;/td&gt;
&lt;td&gt;Since Java 8&lt;/td&gt;
&lt;td&gt;Since forever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Records&lt;/td&gt;
&lt;td&gt;Since Java 16&lt;/td&gt;
&lt;td&gt;Since C# 9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;var&lt;/code&gt; keyword&lt;/td&gt;
&lt;td&gt;Java 10+&lt;/td&gt;
&lt;td&gt;C# 3+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Null safety&lt;/td&gt;
&lt;td&gt;Optional + pain&lt;/td&gt;
&lt;td&gt;Nullable reference types (👍)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checked Exceptions&lt;/td&gt;
&lt;td&gt;Yes (😬)&lt;/td&gt;
&lt;td&gt;Nope (😎)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bonus: C# gives you &lt;code&gt;async/await&lt;/code&gt; that actually makes sense.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏗️ Building a Web API: Spring Boot vs ASP.NET Core
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Spring Boot&lt;/th&gt;
&lt;th&gt;ASP.NET Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Annotation/Attribute&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@RestController&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ApiController]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Route mapping&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@GetMapping("/path")&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[HttpGet("/path")]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@Autowired&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Constructor injection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build tool&lt;/td&gt;
&lt;td&gt;Maven/Gradle&lt;/td&gt;
&lt;td&gt;dotnet CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swagger/OpenAPI&lt;/td&gt;
&lt;td&gt;SpringDoc&lt;/td&gt;
&lt;td&gt;Built-in with 1 line 🧙‍♂️&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here’s how you define an endpoint in .NET 8 Minimal API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Hello, Java friend 👋"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, that’s it. It’s not a trap.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;😱 What Surprised Me&lt;br&gt;
    • Visual Studio is powerful… but Rider is still bae&lt;br&gt;
    • Entity Framework Core feels like JPA’s cool cousin who skipped XML hell&lt;br&gt;
    • C# syntax is cleaner than I expected. Like… really clean&lt;br&gt;
    • Native AOT makes .NET blazingly fast&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;📚 Best Resources for Java Devs Learning .NET&lt;br&gt;
    • 📖 Microsoft Learn: .NET for Java Developers&lt;br&gt;
    • 🎥 YouTube series: “Java to .NET in 30 days”&lt;br&gt;
    • 🧪 Build a CRUD app with ASP.NET Core + EF Core&lt;br&gt;
    • 🛠 Try running a .NET app in Docker just to flex&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🥲 What I Missed from Java&lt;br&gt;
    • The ecosystem around Spring (Spring Boot starters are 🤌)&lt;br&gt;
    • Maven’s lifecycle (dotnet CLI is simpler but takes getting used to)&lt;br&gt;
    • The JVM’s maturity (but .NET has caught up BIG TIME)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🎉 Conclusion: Should You Switch?&lt;/p&gt;

&lt;p&gt;Not necessarily switch — but learn it? Definitely yes.&lt;br&gt;
.NET isn’t just a Microsoft dinosaur anymore. It’s modern, snappy, and very Java-dev-friendly. You’ll feel at home quicker than you think.&lt;/p&gt;

&lt;p&gt;And hey, if you can survive Hibernate, you can survive anything 💪&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Made with ❤️ by a coffee-powered dev who crossed over and didn’t look back… much.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Let me know in the comments if you’re also jumping ships — or just curious how far the C# rabbit hole goes. 🚢🐇&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>java</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>🎬 Building a .NET 8 Web API + GitHub Actions CI/CD — Vibe Coding Ep.1</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Sat, 07 Jun 2025 19:13:40 +0000</pubDate>
      <link>https://dev.to/manimovassagh/building-a-net-8-web-api-github-actions-cicd-vibe-coding-ep1-85b</link>
      <guid>https://dev.to/manimovassagh/building-a-net-8-web-api-github-actions-cicd-vibe-coding-ep1-85b</guid>
      <description>&lt;p&gt;🔥 &lt;strong&gt;Welcome to the first episode of Vibe Coding with Mani!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this real-world coding session, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a modern &lt;strong&gt;.NET 8 Web API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Entity Framework Core&lt;/strong&gt; to connect to a SQL Server (running in Docker)&lt;/li&gt;
&lt;li&gt;Set up a &lt;strong&gt;GitHub Actions&lt;/strong&gt; workflow to automate build &amp;amp; deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No boring walkthroughs. No scripts. Just pure development vibes — experimenting, debugging, and building like a real dev.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎥 Watch the Video
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://youtu.be/6-kSHubRpEE?si=n05JnjxRVjyNVnPx" rel="noopener noreferrer"&gt;Watch on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;.NET 8 (Web API)&lt;/li&gt;
&lt;li&gt;SQL Server + Docker&lt;/li&gt;
&lt;li&gt;GitHub Actions (CI/CD)&lt;/li&gt;
&lt;li&gt;Entity Framework Core&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧠 Ideal For
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Developers learning backend with .NET&lt;/li&gt;
&lt;li&gt;Anyone curious about CI/CD with GitHub Actions&lt;/li&gt;
&lt;li&gt;Coders who enjoy watching &lt;strong&gt;real development flow&lt;/strong&gt; and decision-making&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📦 Source Code
&lt;/h2&gt;

&lt;p&gt;🔗 GitHub Repo: &lt;a href="https://github.com/manimovassagh/Dotnet-Vibe" rel="noopener noreferrer"&gt;Dotnet-Vibe&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you're tired of perfect tutorials and want to see how real devs think, break, and build — you're in the right place.&lt;/p&gt;

&lt;p&gt;🛎️ Follow me for more &lt;strong&gt;Vibe Coding&lt;/strong&gt; sessions using TypeScript, Java, AI tools, and fullstack tech.&lt;/p&gt;

&lt;p&gt;— Mani 💻🎧&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>githubactions</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>📚 10 Timeless Programming Books Every Developer Should Read (Especially If You’ve Been Coding for Years)</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Sun, 01 Jun 2025 14:15:36 +0000</pubDate>
      <link>https://dev.to/manimovassagh/10-timeless-programming-books-every-developer-should-read-especially-if-youve-been-coding-for-40hj</link>
      <guid>https://dev.to/manimovassagh/10-timeless-programming-books-every-developer-should-read-especially-if-youve-been-coding-for-40hj</guid>
      <description>&lt;h1&gt;
  
  
  📚 10 Timeless Programming Books Every Developer Should Read
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;(Especially If You’ve Been Coding for Years)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After years of working in software development—across Java, TypeScript, Go, Spring Boot, testing, automation, and even dabbling with Rust and C—I’ve finally decided to dive into &lt;strong&gt;programming books&lt;/strong&gt; seriously.&lt;/p&gt;

&lt;p&gt;Not tutorials. Not blogs. &lt;strong&gt;Books&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Books that shape how you &lt;strong&gt;think&lt;/strong&gt;, not just what you code.&lt;/p&gt;

&lt;p&gt;Here’s my personal list of the top 10 programming books that every developer—especially mid to senior level—should consider reading:&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Top 10 Programming Books for Thoughtful Developers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Pragmatic Programmer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Dave Thomas &amp;amp; Andy Hunt&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ Timeless tips and philosophies for becoming a better engineer. You’ll relate to every chapter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Designing Data-Intensive Applications&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Martin Kleppmann&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ If you’re building modern backends, this book will fundamentally upgrade your thinking on databases, events, and scale.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Computer Systems: A Programmer’s Perspective (CS:APP)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Randal Bryant &amp;amp; David O’Hallaron&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ From C to assembly, memory, binary, stack, CPU—it’s the behind-the-scenes story of your code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean Architecture&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Robert C. Martin&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ Structure, decouple, and scale your applications the right way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactoring&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Martin Fowler&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ A practical, pattern-driven guide to transforming messy code into clean, testable architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operating Systems: Three Easy Pieces&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Remzi Arpaci-Dusseau&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ One of the most readable ways to understand how operating systems actually work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effective Java&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Joshua Bloch&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ If you write Java, this is gold. If you don’t, still worth reading for sharp language design lessons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Software Engineering at Google&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Google Engineers&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ How large teams manage code quality, testing, scalability, and developer culture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structure and Interpretation of Computer Programs (SICP)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Harold Abelson &amp;amp; Gerald Jay Sussman&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ A deep, abstract, brain-expanding book. Not practical, but unforgettable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Art of Unix Programming&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;by Eric S. Raymond&lt;/em&gt;&lt;br&gt;&lt;br&gt;
→ Principles, philosophy, and the Unix mindset behind tools we all use daily.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🤔 Why Books?
&lt;/h2&gt;

&lt;p&gt;I've realized that books—unlike articles—give you space to think deeply, connect ideas, and reflect.&lt;br&gt;&lt;br&gt;
They don’t just teach you &lt;em&gt;how&lt;/em&gt;, they make you ask &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Your Turn
&lt;/h2&gt;

&lt;p&gt;Have you read any of these?&lt;br&gt;&lt;br&gt;
Got any others that made you think differently as a dev?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop them in the comments 👇 I’d love to expand this list together.&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Vibe Coding with Cursor AI</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Fri, 30 May 2025 18:46:44 +0000</pubDate>
      <link>https://dev.to/manimovassagh/vibe-coding-with-cursor-ai-25gb</link>
      <guid>https://dev.to/manimovassagh/vibe-coding-with-cursor-ai-25gb</guid>
      <description>&lt;p&gt;Vibe Coding with Cursor AI: Building an Express + TypeScript REST API&lt;/p&gt;

&lt;p&gt;I just released a new episode on my YouTube channel Tech Talk with Mani that I think you’ll enjoy:&lt;br&gt;
&lt;a href="https://www.youtube.com/live/pQeLSwKbp-A?si=sFCbxdRHJ8US_dS6" rel="noopener noreferrer"&gt;👉 Watch it here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This is part of my Vibe Coding Series, where I explore real-world development tools and AI assistants — all in a relaxed, practical format.&lt;/p&gt;

&lt;p&gt;🎯 In this episode, I team up with Cursor AI to build a backend REST API using Express.js + TypeScript.&lt;br&gt;
We cover:&lt;br&gt;
    • Project setup with ts-node-dev&lt;br&gt;
    • Routing and folder structure&lt;br&gt;
    • Creating DTOs and entity layers&lt;br&gt;
    • Health checks and testing with Jest&lt;br&gt;
    • Letting AI assist in code generation and flow&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧠 Why you should watch:&lt;br&gt;
    • See how AI coding tools like Cursor can speed up real-world backend dev&lt;br&gt;
    • Learn clean code patterns using Express and TypeScript&lt;br&gt;
    • Follow along in a chill, step-by-step vibe — perfect for fullstack devs&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;If you’re into AI, TypeScript, or want to see how devs are building faster with intelligent tools, this one’s for you.&lt;/p&gt;

&lt;p&gt;Let me know what you think, or drop your feedback — I’d love to hear it!&lt;br&gt;
Also open to collaborations or coding hangouts 🧑‍💻🎥&lt;/p&gt;

&lt;p&gt;Thanks,&lt;br&gt;
Mani&lt;br&gt;
Tech Talk with Mani&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Welcome back to Part 3 of the Immo Finder App project! 👷‍♂️</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Sun, 18 May 2025 21:05:21 +0000</pubDate>
      <link>https://dev.to/manimovassagh/welcome-back-to-part-3-of-the-immo-finder-app-project-3j3b</link>
      <guid>https://dev.to/manimovassagh/welcome-back-to-part-3-of-the-immo-finder-app-project-3j3b</guid>
      <description>&lt;p&gt;In this part, I focused on setting up the backend controller for managing apartment listings using:&lt;br&gt;
    • 📦 Spring Boot&lt;br&gt;
    • 🛠 PostgreSQL&lt;br&gt;
    • 🧪 Clean architecture and Flyway migrations&lt;br&gt;
    • 📸 Planned photo upload structure (coming next)&lt;/p&gt;

&lt;p&gt;We walk through:&lt;br&gt;
    • Creating the ApartmentController&lt;br&gt;
    • Mapping the database models&lt;br&gt;
    • Preparing for property photos and metadata&lt;/p&gt;

&lt;p&gt;🎥 Watch the episode here:&lt;br&gt;
&lt;a href="https://youtu.be/_4ZbZXC-nrA" rel="noopener noreferrer"&gt;https://youtu.be/_4ZbZXC-nrA&lt;/a&gt;&lt;br&gt;
Star the repo if you like it &lt;br&gt;
&lt;a href="https://github.com/manimovassagh/immo-finder" rel="noopener noreferrer"&gt;https://github.com/manimovassagh/immo-finder&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>postgres</category>
      <category>database</category>
      <category>backend</category>
    </item>
    <item>
      <title>Building the Immo Finder App (Part 2) – Fullstack with Cursor AI &amp; Vite + Spring Boot</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Sun, 18 May 2025 21:02:37 +0000</pubDate>
      <link>https://dev.to/manimovassagh/building-the-immo-finder-app-part-2-fullstack-with-cursor-ai-vite-spring-boot-cn7</link>
      <guid>https://dev.to/manimovassagh/building-the-immo-finder-app-part-2-fullstack-with-cursor-ai-vite-spring-boot-cn7</guid>
      <description>&lt;p&gt;Hey developers! 👋&lt;br&gt;
In this second part of my Immo Finder App series, we continue building a fullstack real estate platform using:&lt;br&gt;
    • 🧠 Cursor AI – to help us write smart code faster&lt;br&gt;
    • ⚡️ Vite + React (TypeScript) for the frontend&lt;br&gt;
    • ☕️ Spring Boot as the backend&lt;br&gt;
    • 🎯 Modern architecture with clean code&lt;/p&gt;

&lt;p&gt;👉 In this episode, I set up the frontend and backend structure and connect the pieces using devcontainers + Vite + Tailwind.&lt;br&gt;
📺 Watch it here:&lt;br&gt;
&lt;a href="https://youtu.be/JMRj59Hc_BQ" rel="noopener noreferrer"&gt;https://youtu.be/JMRj59Hc_BQ&lt;/a&gt;&lt;br&gt;
Star if you like the repo or feel free to colaborate&lt;br&gt;
&lt;a href="https://github.com/manimovassagh/immo-finder" rel="noopener noreferrer"&gt;https://github.com/manimovassagh/immo-finder&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  springboot #postgresql #backend #realestate
&lt;/h1&gt;

</description>
      <category>programming</category>
      <category>fullstack</category>
      <category>cursorai</category>
      <category>springboot</category>
    </item>
    <item>
      <title>From Microservices to Monetization: Building a Real Estate Platform the Right Way</title>
      <dc:creator>Mani Movassagh</dc:creator>
      <pubDate>Sat, 17 May 2025 12:22:54 +0000</pubDate>
      <link>https://dev.to/manimovassagh/from-microservices-to-monetization-building-a-real-estate-platform-the-right-way-271e</link>
      <guid>https://dev.to/manimovassagh/from-microservices-to-monetization-building-a-real-estate-platform-the-right-way-271e</guid>
      <description>&lt;p&gt;Intro Section:&lt;/p&gt;

&lt;p&gt;After 15 years in software development and test automation, I decided to build something of my own — a real estate (Immobilien) platform tailored for the German market.&lt;/p&gt;

&lt;p&gt;The idea was to combine what I know best: robust backend architecture, modern TypeScript frontends, and secure authentication — all designed from the ground up for monetization.&lt;/p&gt;

&lt;p&gt;This article walks through the architectural decisions, technical challenges, and hard-earned lessons that shaped the platform.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧱 Why Microservices?&lt;/p&gt;

&lt;p&gt;I started with one clear goal: keep things clean and scalable. The platform includes:&lt;br&gt;
    • 🏘️ Multiple property types (house, apartment, garden…)&lt;br&gt;
    • 📦 Listings for rent and purchase&lt;br&gt;
    • 📸 File uploads for property photos&lt;br&gt;
    • 🧭 Address-to-Geo translation (lat/lng)&lt;br&gt;
    • 🔐 Secure login with role-based access&lt;/p&gt;

&lt;p&gt;So I split it into microservices:&lt;br&gt;
    • property-service: manages property-related data&lt;br&gt;
    • auth-service: authentication via Keycloak&lt;br&gt;
    • geo-service: converts addresses into coordinates&lt;br&gt;
    • upload-service: handles image/file storage in PostgreSQL&lt;br&gt;
    • gateway-service: central API routing via Spring Cloud Gateway&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;⚙️ Key Technical Choices&lt;/p&gt;

&lt;p&gt;UUIDs for IDs:&lt;br&gt;
Avoided collisions and made frontend caching simpler.&lt;/p&gt;

&lt;p&gt;Database Design:&lt;br&gt;
Separate tables for property types (Apartment, House, etc.) and for listing types (Rent, Buy) for performance.&lt;/p&gt;

&lt;p&gt;File Uploads in PostgreSQL:&lt;br&gt;
No S3 — I stored images using bytea in PostgreSQL. It’s fast and GDPR-friendly for MVP stage.&lt;/p&gt;

&lt;p&gt;Keycloak Auth:&lt;br&gt;
It powers:&lt;br&gt;
    • Login/Signup&lt;br&gt;
    • RBAC (Admin, Agent, User)&lt;br&gt;
    • JWT-secured APIs&lt;/p&gt;

&lt;p&gt;DevOps with ECS + Terraform:&lt;br&gt;
Everything runs in Docker containers on ECS.&lt;br&gt;
Infrastructure is built using Terraform (VPCs, services, secrets).&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🖼️ Frontend Stack&lt;br&gt;
    • Next.js + TypeScript&lt;br&gt;
    • Tailwind CSS&lt;br&gt;
    • Geoapify for address autocomplete&lt;br&gt;
    • Access tokens from Keycloak for secure API use&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;💡 Lessons Learned&lt;br&gt;
    • Don’t overgeneralize — real estate data is domain-specific&lt;br&gt;
    • Start with a Gateway service — saves major refactoring later&lt;br&gt;
    • Separate out audit/analytics early&lt;br&gt;
    • Keycloak is great but painful to customize&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🚀 What’s Next?&lt;br&gt;
    • 💳 Integrate Stripe for paid listings&lt;br&gt;
    • 🔔 Notify users of search matches&lt;br&gt;
    • 📊 Add analytics microservice&lt;br&gt;
    • 🗺️ Improve map-based UX&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;✌ Final Thoughts&lt;/p&gt;

&lt;p&gt;If you’re considering building your own SaaS — go for it.&lt;br&gt;
Start small, think in services, and build around real use cases.&lt;/p&gt;

&lt;p&gt;I’m not just building a side project. I’m building a real app.&lt;br&gt;
You can too.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Need Help?&lt;/p&gt;

&lt;p&gt;Want to chat tech, design, or growth?&lt;br&gt;
Drop a comment — let’s connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
