<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Diogo Notes]]></title><description><![CDATA[Diogo Notes]]></description><link>https://blog.diogomachado.com</link><generator>RSS for Node</generator><lastBuildDate>Sat, 25 Apr 2026 08:40:11 GMT</lastBuildDate><atom:link href="https://blog.diogomachado.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[My AI development flow as a developer in 2026]]></title><description><![CDATA[Looks like 2026 is the year of AI tools for developers. About 6 months ago, we were seeing lots of changes coming. I would like to share my current workflow, which I consider is the new normal on my code challenges, in both cases: as a developer and ...]]></description><link>https://blog.diogomachado.com/my-ai-development-flow-as-a-developer-in-2026</link><guid isPermaLink="true">https://blog.diogomachado.com/my-ai-development-flow-as-a-developer-in-2026</guid><category><![CDATA[AI]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Diogo Machado]]></dc:creator><pubDate>Tue, 17 Feb 2026 13:13:20 GMT</pubDate><content:encoded><![CDATA[<p>Looks like 2026 is the year of AI tools for developers. About 6 months ago, we were seeing lots of changes coming. I would like to share my current workflow, which I consider is the new normal on my code challenges, in both cases: as a developer and an entrepreneur.</p>
<p>During more than 10 years, this was my development workflow:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771333301802/ff441eaa-9495-4c72-9449-caa82be501c9.png" alt class="image--center mx-auto" /></p>
<p>With AI, I realized this is my current development workflow:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771332513724/a0db6d7e-25d5-4735-aa8e-5061f1829203.png" alt class="image--center mx-auto" /></p>
<p>The <em>new normal</em> in all places and companies that I worked in, or in the indie communities that I follow, is that everyone is talking about AI. I embraced this new world. Without AI, my SaaS would spend so much time being launched, but I have two highlights about working with AI:</p>
<ol>
<li><p>The developer should have even more experience to provide accurately prompt context.</p>
</li>
<li><p>Sometimes is a good exercise to try to do some tasks without AI, only to force exercise your muscle memory (a couple of weeks ago I thought I was a junior when I needed to code without AI).</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA["Start small, Stay small": book review]]></title><description><![CDATA[Recently, I finished reading the book "Start Small, Stay Small," and even though this book is a little old, published in 2010, the content continues to be valuable for developers who want to start developing, marketing, and making money as solo entre...]]></description><link>https://blog.diogomachado.com/start-small-stay-small-book-review</link><guid isPermaLink="true">https://blog.diogomachado.com/start-small-stay-small-book-review</guid><category><![CDATA[indiedev]]></category><category><![CDATA[books]]></category><dc:creator><![CDATA[Diogo Machado]]></dc:creator><pubDate>Sun, 14 Sep 2025 14:56:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757860199929/67b166ea-69cd-4ae0-96fd-9a69d9bcc8aa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently, I finished reading the book "Start Small, Stay Small," and even though this book is a little old, published in 2010, the content continues to be valuable for developers who want to start developing, marketing, and making money as solo entrepreneurs.</p>
<p>I got my digital version on Amazon using the money received from my microsass 🥳</p>
<ul>
<li><p><a target="_blank" href="https://www.amazon.com.br/Start-Small-Stay-Developers-Launching-ebook/dp/B003YH9MMI/ref=sr_1_1?crid=2F312V1TU1RRG&amp;dib=eyJ2IjoiMSJ9.Shrrx1GGUA86kDW8Pee4LuV2GX4ppQjJWDOd8Pqr-GhnKlza0nrNN4lmkEEcRFcqxEkjiVI7tas1tGs4CUUtqcIHJPT83mdHgUjRP4gGoR8XrV4Hdt2Ir3NRiy2mP_JSyo0ItK0zRRf5iTKFPAsisJUQpoJAlcxofEIC46H7duBgTjVmmDcla70V7lHYmU5sk1uBUtYr9SogWumLFHeUDd3NelA_41M93egWOYLPnhbbjOp8EIWAJ1Ik5s222zn-cwlYAALVgLi6t4IKMsejx6b9Sz6P4EPuWFiJHjo8k9Y.O3Ar-yQ6rjb2B7A6PuMo6WEdQycJ0bv_gaHs6JjEyQY&amp;dib_tag=se&amp;keywords=start+small%2C+stay+small&amp;qid=1757858862&amp;sprefix=start+small+s%2Caps%2C220&amp;sr=8-1">Book link</a></p>
</li>
<li><p><a target="_blank" href="https://convide.online/en/">My microsaas</a></p>
</li>
</ul>
<h2 id="heading-my-highlights">My highlights</h2>
<p>The book is old, and some links and ideas, like marketing all in email, are really outdated nowadays. However, I generally liked all the content and learned a lot. The author is experienced, and the content came at a perfect time for me as I'm exploring this path to entrepreneurship as a solo developer building my platform <a target="_blank" href="https://convide.online/en/">convide.online</a>. Here are some comments and notes that I would like to highlight:</p>
<h2 id="heading-marketing-gt-product">Marketing &gt; Product</h2>
<blockquote>
<p>The key factor in an entrepreneur’s success is their ability to market their product.</p>
<p>Marketing is more important than your product.</p>
</blockquote>
<p>One thing that I'm really learning is that marketing can't be ignored from day one.</p>
<h2 id="heading-niche-and-seo-competition">Niche and SEO competition</h2>
<p>This highlight is really important. A more specific niche can be cheaper to market on Google Ads, for example, and is sometimes really good for your business as a solo entrepreneur.</p>
<blockquote>
<p>Having a $2000/month niche to yourself is much better than having a 20% market share of a $10,000/month niche. No competition means lower ad rates, less SEO competition, and as the market grows your income will automatically increase since you own the entire market.</p>
</blockquote>
<h2 id="heading-freedom-to-choose-your-path">Freedom to Choose Your Path</h2>
<p>I liked this idea: don't waste a lot of time on one idea if you are an Indie Hacker and solo entrepreneur.</p>
<blockquote>
<p>If an idea doesn’t work out, scrap it and start another one.</p>
</blockquote>
<h2 id="heading-ads">Ads</h2>
<p>I learned this year that if you put energy into tweaking your campaign on Google Ads (or other platforms) and it is giving results, the best news is you can keep running it for years without too much effort.</p>
<blockquote>
<p>I have campaigns that have been running with minor tweaks for more than two years. The time investment was in the first 2-3 months testing ads and finding the keywords that converted.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How to Build a Simple UTM System to Track Your Ad Campaigns]]></title><description><![CDATA[Motivation
I'm building my microsaas, and since I'm not a marketing specialist, it is difficult for me to validate if the money invested brings a return or not. For example, I tried TikTok Ads, YouTube, and Google Ads, but the reports from these serv...]]></description><link>https://blog.diogomachado.com/how-to-build-a-simple-utm-system-to-track-your-ad-campaigns</link><guid isPermaLink="true">https://blog.diogomachado.com/how-to-build-a-simple-utm-system-to-track-your-ad-campaigns</guid><category><![CDATA[Angular]]></category><category><![CDATA[marketing]]></category><category><![CDATA[ads]]></category><category><![CDATA[SaaS]]></category><dc:creator><![CDATA[Diogo Machado]]></dc:creator><pubDate>Mon, 26 May 2025 15:52:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/8qEB0fTe9Vw/upload/74f8c4ed572e887d969f26241bc01c52.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-motivation">Motivation</h2>
<p>I'm building my microsaas, and since I'm not a marketing specialist, it is difficult for me to validate if the money invested brings a return or not. For example, I tried TikTok Ads, YouTube, and Google Ads, but the reports from these services are complex and difficult. So, as I'm using a local <a target="_blank" href="https://www.metabase.com/">Metabase</a> to manage my data, I had a simple idea, which I explain below in an image.</p>
<h2 id="heading-the-idea">The idea</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748273441889/432ea050-1412-4097-b42e-b0c18fdfc2c7.png" alt class="image--center mx-auto" /></p>
<p>With this idea, you can implement it in any front-end stack. In my case, I'm using Angular, so I'll show you how I did it:</p>
<ol>
<li><p>Create a service</p>
</li>
<li><p>Listen the URL changes</p>
</li>
<li><p>Save the UTM params in the localStorage</p>
</li>
<li><p>Get the UTM params and send to the API</p>
</li>
</ol>
<h2 id="heading-the-service">The service</h2>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UtmService {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> utmKeys = [
    <span class="hljs-string">'utm_id'</span>,
    <span class="hljs-string">'utm_source'</span>,
    <span class="hljs-string">'utm_medium'</span>,
    <span class="hljs-string">'utm_campaign'</span>,
    <span class="hljs-string">'utm_term'</span>,
    <span class="hljs-string">'utm_content'</span>,
  ];
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> sessionKey = <span class="hljs-string">'NAME-YOUR-SESSION'</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {}

  saveUtmsFromQuery(params: <span class="hljs-built_in">any</span>): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> utms: <span class="hljs-built_in">any</span> = {};

    <span class="hljs-built_in">this</span>.utmKeys.forEach(<span class="hljs-function">(<span class="hljs-params">key</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (params[key]) {
        utms[key] = params[key];
      }
    });

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.keys(utms).length) {
      <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-built_in">this</span>.sessionKey, <span class="hljs-built_in">JSON</span>.stringify(utms));
    }
  }

  getUtms(): <span class="hljs-built_in">any</span> {
    <span class="hljs-keyword">const</span> data = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-built_in">this</span>.sessionKey);
    <span class="hljs-keyword">return</span> data ? <span class="hljs-built_in">JSON</span>.parse(data) : <span class="hljs-literal">null</span>;
  }

  clearUtms(): <span class="hljs-built_in">void</span> {
    <span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-built_in">this</span>.sessionKey);
  }
}
</code></pre>
<p>Inject the service in the <code>AppComponent</code>:</p>
<pre><code class="lang-typescript">utmService = inject(UtmService);
</code></pre>
<p>In the <code>ngOnInit()</code>, I created a method:</p>
<pre><code class="lang-typescript">ngOnInit(): <span class="hljs-built_in">void</span> {
    <span class="hljs-built_in">this</span>.listenQueryParams();
}
</code></pre>
<pre><code class="lang-typescript">listenQueryParams() {
    <span class="hljs-built_in">this</span>.route.queryParams.subscribe(<span class="hljs-function">(<span class="hljs-params">params</span>) =&gt;</span> {
      <span class="hljs-built_in">this</span>.utmService.saveUtmsFromQuery(params);
    });
  }
</code></pre>
<h2 id="heading-sending-the-data-to-your-api">Sending the data to your API</h2>
<p>This part depends on your backend API. In my case, I made changes to send the data when the user creates a new event. Collecting the UTM is simple:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-keyword">private</span> fb: FormBuilder,
  </span>) {
    <span class="hljs-built_in">this</span>.myForm = <span class="hljs-built_in">this</span>.fb.group({
      email: [<span class="hljs-string">''</span>, [Validators.required, Validators.email]],
      password: [<span class="hljs-string">''</span>, [Validators.required, Validators.minLength(<span class="hljs-number">6</span>)]],
      utm_source: [<span class="hljs-literal">null</span>],
      utm_medium: [<span class="hljs-literal">null</span>],
      utm_campaign: [<span class="hljs-literal">null</span>],
      utm_term: [<span class="hljs-literal">null</span>],
      utm_content: [<span class="hljs-literal">null</span>],
    });

    <span class="hljs-built_in">this</span>.myForm.patchValue(<span class="hljs-built_in">this</span>.utmService.getUtms());
  }
</code></pre>
<p>Now, when I send the form data, the UTM goes along automatically.</p>
<h2 id="heading-remember-to-set-your-utm-params-in-your-campaign-or-links">Remember to set your UTM params in your campaign or links.</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748274600933/0a072790-ec06-4562-9c4b-75284fdafdfb.png" alt class="image--center mx-auto" /></p>
<p>That's it 🎉</p>
]]></content:encoded></item><item><title><![CDATA[How to Create a Custom Select Dropdown with Angular]]></title><description><![CDATA[At some point in your career as a front-end developer, you will likely need to build a custom component. In this article, I will share my experience and provide examples to help you tackle this challenge and achieve your goal.
Why custom?
The reasons...]]></description><link>https://blog.diogomachado.com/how-to-create-a-custom-select-dropdown-with-angular</link><guid isPermaLink="true">https://blog.diogomachado.com/how-to-create-a-custom-select-dropdown-with-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Diogo Machado]]></dc:creator><pubDate>Fri, 18 Apr 2025 16:15:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744992824821/30b90057-f223-4196-8885-fca64b21ac35.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>At some point in your career as a front-end developer, you will likely need to build a custom component. In this article, I will share my experience and provide examples to help you tackle this challenge and achieve your goal.</p>
<h2 id="heading-why-custom">Why custom?</h2>
<p>The reasons can vary, but the main one is that the design system doesn't match the native <code>&lt;select&gt;</code>. In practice, the <code>&lt;select&gt;</code> is often difficult to customize, so we need to create our own. Alright, let's go, but how many variations can a simple component have? In my case, the answer is shown in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744937297493/d7749fec-db28-47bb-b3b1-aef715c513b9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-architecture-and-organization">Architecture and organization</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744938053455/ee81919e-c85f-4cc1-8ecd-a6df535b8c6d.png" alt class="image--center mx-auto" /></p>
<p>One good decision was to create a central component and extends all derivations from that component, since Angular is a Typescript framework based, I can easily extends a class.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744988450949/4855a8e4-372b-4c30-a4b1-8b7bc3808b02.png" alt class="image--center mx-auto" /></p>
<p>The <code>select.component.html</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744988167585/78660c56-e316-491d-9f01-d88d0bb7d1a5.png" alt class="image--center mx-auto" /></p>
<p>Example of the <code>select.component.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SelectComponent <span class="hljs-keyword">implements</span> OnChanges, OnDestroy {
    <span class="hljs-meta">@Input</span>() invalid = <span class="hljs-literal">false</span>;
    <span class="hljs-meta">@Input</span>() multiple = <span class="hljs-literal">false</span>;
    <span class="hljs-meta">@Input</span>() loading = <span class="hljs-literal">false</span>;
    ...
}
</code></pre>
<p>The variation only extends the parent:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SelectSimpleComponent <span class="hljs-keyword">extends</span> SelectComponent {
    <span class="hljs-comment">// Exclusive logic of this variation</span>
}
</code></pre>
<p>The beauty of this architecture is that you have all the common inputs and methods, and you can extend them in variations if you need to add new logic. It's a perfect example of object-oriented programming in Angular with TypeScript and JavaScript.</p>
<h2 id="heading-automatically-display-content-with-overlay-from-angular-cdk">Automatically display content with Overlay from Angular CDK</h2>
<p>To display the content inside the select when the user clicks, we could build it using only HTML, CSS, and JavaScript. However, there's a challenge when dealing with dialogs. You might encounter a problem like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744988708741/f500acc3-eca5-45df-9a0b-ac8247b1cc6d.png" alt class="image--center mx-auto" /></p>
<p>To solve this problem, we can use a reliable solution: the Overlay API from Angular Material CDK. Overlay is great because it solves almost all your issues by isolating the component outside of the HTML block.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744991582492/a09ea781-17da-4ab9-87ba-9674584c5c7c.png" alt class="image--center mx-auto" /></p>
<p>Problem solved! When the user clicks to open, we create an Overlay and attach it to a TemplatePortal. The <code>dropdownContent</code> is the ID used in the template in <code>select.component.html</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@ViewChild</span>(<span class="hljs-string">'dropdownContent'</span>) dropdownTpl!: TemplateRef&lt;<span class="hljs-built_in">any</span>&gt;;
</code></pre>
<p>Here is the code to create the Overlay into a TemplatePortal:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">private</span> createOverlay() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.overlayRef) {
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> positionStrategy = <span class="hljs-built_in">this</span>.overlay
      .position()
      .flexibleConnectedTo(<span class="hljs-built_in">this</span>.elementRef)
      .withFlexibleDimensions(<span class="hljs-literal">false</span>)
      .withPush(<span class="hljs-literal">false</span>)
      .withPositions([
        {
          originX: <span class="hljs-string">'start'</span>,
          originY: <span class="hljs-string">'bottom'</span>,
          overlayX: <span class="hljs-string">'start'</span>,
          overlayY: <span class="hljs-string">'top'</span>,
          offsetY: <span class="hljs-number">4</span>,
        },
        {
          originX: <span class="hljs-string">'start'</span>,
          originY: <span class="hljs-string">'top'</span>,
          overlayX: <span class="hljs-string">'start'</span>,
          overlayY: <span class="hljs-string">'bottom'</span>,
          offsetY: <span class="hljs-number">-4</span>,
        },
      ]);

    <span class="hljs-keyword">const</span> overlayConfig = <span class="hljs-keyword">new</span> OverlayConfig({
      positionStrategy,
      scrollStrategy: <span class="hljs-built_in">this</span>.overlay.scrollStrategies.block(),
      hasBackdrop: <span class="hljs-literal">true</span>,
      width: <span class="hljs-built_in">this</span>.elementRef.nativeElement.offsetWidth,
      panelClass: [<span class="hljs-string">'select-overlay'</span>],
    });

    <span class="hljs-built_in">this</span>.overlayRef = <span class="hljs-built_in">this</span>.overlay.create(overlayConfig);

    <span class="hljs-keyword">const</span> portal = <span class="hljs-keyword">new</span> TemplatePortal(<span class="hljs-built_in">this</span>.dropdownTpl, <span class="hljs-built_in">this</span>.viewContainerRef);
    <span class="hljs-built_in">this</span>.overlayRef.attach(portal);
  }
</code></pre>
<p>To close the content:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">private</span> closeOverlay() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.overlayRef) {
      <span class="hljs-built_in">this</span>.overlayRef.detach();
      <span class="hljs-built_in">this</span>.overlayRef = <span class="hljs-literal">null</span>;
    }
  }
</code></pre>
<p>With this setup, you can create as many variations as you want. In my case, these were the components created by extending from <code>select</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744991943918/2e846933-012f-4f87-85dd-e351a26cb43e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusions">Conclusions</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744992466617/fd9aef10-a19c-4587-8100-736956b8479c.png" alt class="image--center mx-auto" /></p>
<p>In times when we can use AI to assist developers, having a good architecture is important. If you don't organize from the start, your project can fail, making components hard to reuse and extend. The <code>&lt;select&gt;</code> component is a classic example of how challenging front-end development can be, whether using frameworks or pure JavaScript.</p>
]]></content:encoded></item></channel></rss>