<?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: Martin Machava</title>
    <description>The latest articles on DEV Community by Martin Machava (@vergil333).</description>
    <link>https://dev.to/vergil333</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%2F829929%2Fdcb8c892-1ef6-40d1-8d01-aea9c568051f.jpeg</url>
      <title>DEV Community: Martin Machava</title>
      <link>https://dev.to/vergil333</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vergil333"/>
    <language>en</language>
    <item>
      <title>SnapNews (build in public)</title>
      <dc:creator>Martin Machava</dc:creator>
      <pubDate>Mon, 26 Aug 2024 18:06:43 +0000</pubDate>
      <link>https://dev.to/vergil333/snapnews-build-in-public-5cd9</link>
      <guid>https://dev.to/vergil333/snapnews-build-in-public-5cd9</guid>
      <description>&lt;p&gt;It's been a while, but I've finally taken the plunge to create and launch a new product! 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82js1ltp9v06h2no952f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82js1ltp9v06h2no952f.png" alt="https://snapnews.me" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Concept: AI-Driven Personalized Newsletters 📰🤖
&lt;/h2&gt;

&lt;p&gt;Ever wondered how to stay updated on your favorite topics without endlessly scrolling through Twitter or Google? 🤔&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagine receiving tailored news summaries on your interests, delivered right to your inbox!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you prefer daily, weekly, or monthly updates, this service has got you covered. After scouring the web for similar offerings and coming up empty-handed, I decided to build it myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting the Prototype ⚙️
&lt;/h2&gt;

&lt;p&gt;The journey began with a simple question: How challenging would it be to bring this idea to life?&lt;/p&gt;

&lt;p&gt;Recently, I made the switch from ChatGPT to Perplexity, attracted by its multiple LLM models and integrated search engine. The PPLX API, though limited to a single endpoint, seemed perfect for my needs.&lt;/p&gt;

&lt;p&gt;One Friday evening, post-9-to-5 grind, I rolled up my sleeves and whipped up a prototype using ExpressJS. It could take a user's topic of interest and summarize search results into a newsletter. A promising start!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My mantra this time: Ship fast, focus on one core feature, and attract those first users!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Initially, I considered using Discord as the primary interaction channel to bypass the need for a frontend. But as we know, plans often evolve...&lt;/p&gt;

&lt;h2&gt;
  
  
  Diving into Discord Integration 🎮
&lt;/h2&gt;

&lt;p&gt;While Discord integration was new territory for me, it wasn't insurmountable. However, I soon realized that Discord's character limits for posts would hinder my ability to showcase full newsletter previews.&lt;/p&gt;

&lt;p&gt;This realization led me to develop a frontend for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time newsletter previews&lt;/li&gt;
&lt;li&gt;Stripe pricing integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The backend needed to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discord user authentication and registration&lt;/li&gt;
&lt;li&gt;Slash command processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/preview&lt;/strong&gt; 👉 Instant newsletter previews&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/create-newsletter&lt;/strong&gt; 👉 Set up recurring newsletters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/manage-newsletters&lt;/strong&gt; 👉 Review or cancel existing subscriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also added a nifty feature allowing users to copy newsletters they admire from others, embracing the community aspect of Discord.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting the Perfect Landing Page 🛬
&lt;/h2&gt;

&lt;p&gt;With a functional frontend in place, it seemed only natural to create an enticing landing page to showcase the product and potentially boost conversion rates.&lt;/p&gt;

&lt;p&gt;Challenge accepted! 🍺&lt;/p&gt;

&lt;p&gt;Having recently dabbled with Angular and finding it more to my liking than React, I decided to stick with it. For styling, I opted for Tailwind CSS, using it first time ever and I love it!, resulting in a sleek and professional look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Smarter AI Search Engine 🔍🤖
&lt;/h2&gt;

&lt;p&gt;While Perplexity API was functional, it lacked options for controlling result dates and providing source references. Determined to offer fresh, verifiable news, I spent a weekend crafting a custom AI search engine.&lt;/p&gt;

&lt;p&gt;The process involves several steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GPT-4o mini&lt;/strong&gt; 👉 Interprets the topic and generates 3 Google search queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Search API&lt;/strong&gt; 👉 Fetches 10 results per query within the specified timeframe&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Search API&lt;/strong&gt; 👉 Queries for "negative" results outside the timeframe to filter out dated news&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPT4o mini&lt;/strong&gt; 👉 Reviews and filters results for relevance and freshness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perplexity API&lt;/strong&gt; 👉 Processes filtered links to create the final newsletter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And of course, the newsletter is then delivered straight to the user's inbox!&lt;/p&gt;

&lt;p&gt;If you've made it this far and want to experience AI-powered personalized news for yourself, check out &lt;a href="https://snapnews.me" rel="noopener noreferrer"&gt;SnapNews&lt;/a&gt; 👈&lt;/p&gt;

&lt;p&gt;You can also find more details about my journey on &lt;a href="https://www.indiehackers.com/product/snapnews" rel="noopener noreferrer"&gt;Indie Hackers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(SEO &lt;a href="https://medium.com/@admin_79457/the-ai-newsletter-revolution-how-personalized-news-is-reshaping-information-consumption-4dbd2881c8a9" rel="noopener noreferrer"&gt;backlink&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>sass</category>
      <category>ai</category>
      <category>newsletter</category>
    </item>
    <item>
      <title>Salesforce objects in Kotlin under 5 minutes</title>
      <dc:creator>Martin Machava</dc:creator>
      <pubDate>Tue, 07 Jun 2022 08:01:38 +0000</pubDate>
      <link>https://dev.to/vergil333/salesforce-objects-in-kotlin-under-5-minutes-3jg6</link>
      <guid>https://dev.to/vergil333/salesforce-objects-in-kotlin-under-5-minutes-3jg6</guid>
      <description>&lt;p&gt;&lt;a href="https://salesforce.codegen.link/"&gt;salesforce.codegen.link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHAT IT DOES?&lt;/strong&gt;&lt;br&gt;
Generates Salesforce object classes in Kotlin code so you don't have to write them all manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HOW?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you &lt;strong&gt;grant permissions&lt;/strong&gt; to the site to your salesforce objects&lt;/li&gt;
&lt;li&gt;then site can &lt;strong&gt;load salesforce objects&lt;/strong&gt; in a list&lt;/li&gt;
&lt;li&gt;you &lt;strong&gt;select&lt;/strong&gt; those &lt;strong&gt;objects&lt;/strong&gt; that you need for your use-case&lt;/li&gt;
&lt;li&gt;when you are done, you proceed to the &lt;strong&gt;next button&lt;/strong&gt; which &lt;strong&gt;loads fields&lt;/strong&gt; of selected objects&lt;/li&gt;
&lt;li&gt;all this is done in the context of the website, from your browser, it works similar as Postman. You can even inspect all api calls. By clicking &lt;strong&gt;generate button&lt;/strong&gt;, your selected objects and fields are passed to the backend which &lt;strong&gt;generates the code&lt;/strong&gt; and in few milliseconds it's printed on your site&lt;/li&gt;
&lt;li&gt;as a bonus, I'm also providing simple rest api client so you can load data of your objects but so far it's not the main objective of this site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Easy, huh?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FUTURE?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add cookies so you stay logged-in after you refresh the page&lt;/li&gt;
&lt;li&gt;option to pass gist token so the generated code is stored under your GitHub account&lt;/li&gt;
&lt;li&gt;login so your preferred settings are stored between sessions&lt;/li&gt;
&lt;li&gt;Gradle/Maven integration so you can run it from command/pipeline and generate/update objects code whenever needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DOUBTS?&lt;/strong&gt;&lt;br&gt;
When you are not logged-in, I added mocked data so you can first load those and try the functionality before granting the access.&lt;br&gt;
Or you can create &lt;a href="https://developer.salesforce.com/signup"&gt;free developer account&lt;/a&gt; and try that one.&lt;br&gt;
Bellow I recorded video on how to use CodeGen and how to implement generated code into your project.&lt;/p&gt;

&lt;p&gt;DEMO&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/9Dw-mntksoM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Let me know in the comments what you think.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>backend</category>
      <category>kotlin</category>
      <category>java</category>
    </item>
    <item>
      <title>Kotlin delegated properties</title>
      <dc:creator>Martin Machava</dc:creator>
      <pubDate>Sun, 13 Mar 2022 09:44:25 +0000</pubDate>
      <link>https://dev.to/vergil333/kotlin-delegated-properties-2ck3</link>
      <guid>https://dev.to/vergil333/kotlin-delegated-properties-2ck3</guid>
      <description>&lt;p&gt;Let’s say you have an &lt;a href="https://github.com/Vergil333/delegated-dto-demo/blob/master/src/main/kotlin/com/martinmachava/delegationtutorial/entities.kt#L11"&gt;Entity&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IHsh0CoX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157916373-820ada10-6cd5-4d67-bc12-397427e84e8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IHsh0CoX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157916373-820ada10-6cd5-4d67-bc12-397427e84e8c.png" alt="1_WCpNS2pYdSMvro9eOW9xhg" width="700" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to create a DTO for some reason. You probably do it &lt;a href="https://github.com/Vergil333/delegated-dto-demo/blob/master/src/main/kotlin/com/martinmachava/delegationtutorial/dtos.kt#L4"&gt;like this&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yRuVYwZY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157916448-63fb1655-dd56-42fb-a7b5-2021ec090292.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yRuVYwZY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157916448-63fb1655-dd56-42fb-a7b5-2021ec090292.png" alt="1_nDGVxuBf6LsAFAaCUOrkXQ" width="700" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constructor here serves as a mapper&lt;/strong&gt;. It maps Entity properties to DTO properties.&lt;br&gt;
&lt;strong&gt;Types of&lt;/strong&gt; DTO &lt;strong&gt;properties are resolved from its Entity&lt;/strong&gt;. That’s good, we do not want to duplicate those types in DTO.&lt;br&gt;
But you can also write &lt;a href="https://github.com/Vergil333/delegated-dto-demo/blob/master/src/main/kotlin/com/martinmachava/delegationtutorial/dtos.kt#L13"&gt;&lt;strong&gt;DTO with delegated properties&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hbl0Sqcm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157918973-719035ce-57d0-4164-a5df-da44321ba29c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hbl0Sqcm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157918973-719035ce-57d0-4164-a5df-da44321ba29c.png" alt="1_N__7AJ253xNeeDNxsYXG9A" width="700" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This looks almost the same as the first DTO. So &lt;strong&gt;what’s the difference&lt;/strong&gt;?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;delegated property is not ”real”&lt;/strong&gt; property of it’s class&lt;/li&gt;
&lt;li&gt;instead its &lt;strong&gt;getter and setter is delegated to Entity&lt;/strong&gt; class&lt;/li&gt;
&lt;li&gt;when &lt;strong&gt;Entity property is changed, that change is reflected in DTO&lt;/strong&gt; delegated property, even when DTO was instantiated before the change&lt;/li&gt;
&lt;li&gt;when DTO delegated property is changed, the change is reflected in Entity&lt;/li&gt;
&lt;li&gt;when we &lt;strong&gt;do not want to modify&lt;/strong&gt; delegated property, we &lt;strong&gt;set it to val&lt;/strong&gt; instead of var.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see it in &lt;a href="https://github.com/Vergil333/delegated-dto-demo/blob/master/src/test/kotlin/com/martinmachava/delegationtutorial/unit/MediumDemoTest.kt#L11"&gt;test example&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v5re1109--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157918719-4b593bca-a864-4b31-9958-75571bf72cc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v5re1109--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/569066/157918719-4b593bca-a864-4b31-9958-75571bf72cc2.png" alt="1_Kw1Ig7yTktT4OmGFZTGuDw" width="700" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you know a good example where to use delegated properties in practice, please, do let me know in the comment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For more examples, &lt;strong&gt;unit tests&lt;/strong&gt; and &lt;strong&gt;integration tests with Hibernate&lt;/strong&gt; functionality where delegation “extends” the arms of Hibernate’s Entity, &lt;a href="https://github.com/Vergil333/delegated-dto-demo/tree/master/src/test/kotlin/com/martinmachava/delegationtutorial"&gt;see my tests&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>java</category>
      <category>jvm</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
