<?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: pul</title>
    <description>The latest articles on DEV Community by pul (@pul).</description>
    <link>https://dev.to/pul</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%2F313709%2F5e58402c-56b2-4131-aa2a-699c8f81f415.png</url>
      <title>DEV Community: pul</title>
      <link>https://dev.to/pul</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pul"/>
    <language>en</language>
    <item>
      <title>How I added analytics and confetti to my loyalty app?</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Thu, 05 Jun 2025 10:21:20 +0000</pubDate>
      <link>https://dev.to/pul/how-i-added-analytics-and-confetti-to-my-loyalty-app-495i</link>
      <guid>https://dev.to/pul/how-i-added-analytics-and-confetti-to-my-loyalty-app-495i</guid>
      <description>&lt;p&gt;Fidely Update #4 – Analytics, Operator Flow &amp;amp; a touch of Confetti 🎉&lt;/p&gt;

&lt;p&gt;Back again with another update on &lt;strong&gt;Fidely&lt;/strong&gt;, the loyalty app I’ve been building in my spare time as part of &lt;em&gt;The 10-Minute Company&lt;/em&gt; series. I’ve been making steady progress, and I’m super excited to share what’s new—because this time, there’s more &lt;em&gt;polish&lt;/em&gt;, more &lt;em&gt;insight&lt;/em&gt;, and a better &lt;em&gt;experience&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If this is your first time hearing about Fidely, check out the &lt;a href="https://pul.hashnode.dev/1-fidely-loyalty-app-side-project" rel="noopener noreferrer"&gt;first post in the series&lt;/a&gt; to catch up on what it’s all about.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Home Dashboard Gets Analytics
&lt;/h2&gt;

&lt;p&gt;One of the key selling points of Fidely is helping small business owners &lt;strong&gt;understand their customers&lt;/strong&gt; better. To make this real, I’ve added a basic &lt;strong&gt;analytics section&lt;/strong&gt; on the home dashboard.&lt;/p&gt;

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

&lt;p&gt;This gives the shop owner some quick insights about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many cards are active
&lt;/li&gt;
&lt;li&gt;Which campaigns are running
&lt;/li&gt;
&lt;li&gt;Key stats from recent activity
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current dashboard acts as a preview—eventually, these metrics will be expanded into a dedicated &lt;strong&gt;analytics section&lt;/strong&gt; with proper filters, charts, and detailed views. But it’s a good first step!&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ A Faster Operator Dashboard
&lt;/h2&gt;

&lt;p&gt;Let’s talk about &lt;strong&gt;speed&lt;/strong&gt;. The Operator Dashboard now feels snappier, smarter, and more helpful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbl234s8wcmdrgfrjb2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbl234s8wcmdrgfrjb2x.png" alt="Fidely fast card research" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new flow is designed for real-world usage:&lt;br&gt;&lt;br&gt;
Operators are often juggling customers, so every click matters.&lt;/p&gt;

&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for a card quickly
&lt;/li&gt;
&lt;li&gt;Get instant results under the search bar
&lt;/li&gt;
&lt;li&gt;If there’s a single match, the app auto-selects the card and shows this view:&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;From here the operator can:&lt;/p&gt;

&lt;p&gt;✅ View card details&lt;br&gt;&lt;br&gt;
✅ Join a campaign if the card hasn’t yet&lt;br&gt;&lt;br&gt;
✅ Assign points/stamps immediately&lt;br&gt;&lt;br&gt;
✅ See campaign progress  &lt;/p&gt;

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

&lt;p&gt;Once points are added, the app brings the operator back to the search view—so they can help the next customer quickly.&lt;/p&gt;

&lt;p&gt;But wait—there’s more!&lt;/p&gt;

&lt;p&gt;If the customer &lt;strong&gt;unlocks a reward&lt;/strong&gt;, the app throws a &lt;strong&gt;confetti animation&lt;/strong&gt; (yes, for real 😄), and the workflow pauses, giving the operator time to ask if the customer wants to redeem it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8hdx4o3lc2hy9spchdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8hdx4o3lc2hy9spchdy.png" alt="Fidely reward reached alert" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s small stuff, but it matters for &lt;strong&gt;UX and flow&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐛 Bug Fixing Time
&lt;/h2&gt;

&lt;p&gt;I also spent time cleaning up annoying bugs that were dragging the user experience down.&lt;/p&gt;

&lt;p&gt;From navigation glitches to weird reloads—many small fixes that, together, make the app feel smoother and more consistent.&lt;/p&gt;




&lt;h2&gt;
  
  
  💳 A New Card Layout
&lt;/h2&gt;

&lt;p&gt;Inspired by credit cards, I gave the &lt;strong&gt;customer card UI&lt;/strong&gt; a little makeover.&lt;/p&gt;

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

&lt;p&gt;Not sure if this will be the final look, but it’s a fun experiment—and it makes cards feel more "real".&lt;/p&gt;




&lt;h2&gt;
  
  
  🔔 Global Notification System
&lt;/h2&gt;

&lt;p&gt;Last but not least: I’ve added a &lt;strong&gt;toast notification system&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Whenever a user takes an action—like assigning points, joining a campaign, or redeeming a reward—they’ll now get &lt;strong&gt;instant visual feedback&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s a small feature, but it adds a lot of clarity.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;More detailed analytics
&lt;/li&gt;
&lt;li&gt;Campaign creation wizard
&lt;/li&gt;
&lt;li&gt;Customer view and reward redemption flow
&lt;/li&gt;
&lt;li&gt;Localization (yes, Fidely is still mostly in Italian 😅)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;That’s it for now. As always, I’m building Fidely a few evenings at a time—progress is slow but steady.&lt;br&gt;&lt;br&gt;
If you're working on a microSaaS or playing around with loyalty mechanics, I’d love to hear from you!&lt;/p&gt;

&lt;p&gt;Let’s keep building!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>#3 Fidely Project Update: a better UI 💪</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Mon, 05 May 2025 10:09:10 +0000</pubDate>
      <link>https://dev.to/pul/3-fidely-project-update-a-better-ui-15j8</link>
      <guid>https://dev.to/pul/3-fidely-project-update-a-better-ui-15j8</guid>
      <description>&lt;p&gt;Time for a long-overdue update on the &lt;strong&gt;Fidely Project&lt;/strong&gt;!&lt;br&gt;&lt;br&gt;
Yeah, this post took a while to come out—writing consistently is still a challenge for me. But hey, I'm trying to stay on track and keep this blog alive for the months ahead.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through what I’ve been building lately. Lots of progress, especially on the &lt;strong&gt;frontend&lt;/strong&gt;, but also a good amount of refactoring under the hood.&lt;/p&gt;

&lt;p&gt;If this is your first time hearing about Fidely, I recommend &lt;a href="https://pulbasso.dev/series/the-10-minute-company" rel="noopener noreferrer"&gt;checking out the series&lt;/a&gt; to understand the context and the problem I'm trying to solve.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's New?
&lt;/h2&gt;

&lt;p&gt;Right now, I’m mostly focused on the &lt;strong&gt;shop owner&lt;/strong&gt;’s point of view.&lt;/p&gt;

&lt;p&gt;Here’s what a shop owner can now do:&lt;/p&gt;

&lt;p&gt;✅ Register/Login&lt;br&gt;&lt;br&gt;
✅ Create and manage one or more companies&lt;br&gt;&lt;br&gt;
✅ Set up loyalty campaigns (both points collection and stamps)&lt;br&gt;&lt;br&gt;
✅ Create customer cards&lt;br&gt;&lt;br&gt;
✅ Assign points or stamps to customer cards from the &lt;strong&gt;Operator View&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ View and manage their user profile&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All features are working in the app already — still mostly in Italian, but internationalization is on my radar for the next releases!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🔐 Login &amp;amp; Register
&lt;/h3&gt;

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

&lt;p&gt;Straightforward login and signup flow. Nothing fancy, but it works!&lt;/p&gt;




&lt;h3&gt;
  
  
  🏠 Home Dashboard
&lt;/h3&gt;

&lt;p&gt;The app now includes a sidebar with different sections (some are still under construction).&lt;/p&gt;

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

&lt;p&gt;Let’s break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Company Switcher&lt;/strong&gt; at the top: if the user manages multiple companies, this dropdown lets them switch between them or create a new one.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Operatività&lt;/strong&gt;: this section is all about speed. It’s designed for quick actions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Viewing recent transactions&lt;/li&gt;
&lt;li&gt;Creating a new customer card&lt;/li&gt;
&lt;li&gt;Launching the operator interface for assigning points/stamps&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyb2o1m2yr7ubpdoxmbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyb2o1m2yr7ubpdoxmbm.png" alt="Fidely sidebar quick links" width="408" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Attività / Campagne / Carte&lt;/strong&gt;: classic CRUD sections where shop owners can edit their business info, loyalty campaigns, and customer cards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c9h3v5yz0wane58ot2z.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c9h3v5yz0wane58ot2z.webp" alt="Fidely sidebar sections" width="490" height="616"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Wizard Engine
&lt;/h2&gt;

&lt;p&gt;One of the coolest things I’ve added recently is a &lt;strong&gt;custom wizard engine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I noticed that multiple flows in the app follow a “step-by-step” pattern—like onboarding, campaign setup, card creation, and more.&lt;/p&gt;

&lt;p&gt;So instead of repeating the same logic all over, I built a tiny &lt;strong&gt;abstract wizard engine&lt;/strong&gt;. It handles step navigation and state management, so I can reuse it for any future wizard.&lt;/p&gt;

&lt;p&gt;First implementation? The card creation flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnk9r451c32j23strafud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnk9r451c32j23strafud.png" alt="Fidely card creation wizard" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s basic but working! And adding new wizards should now take a fraction of the time.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;In the upcoming evenings and weekends (aka my dev time), I’ll be working on:&lt;/p&gt;

&lt;p&gt;🔧 Completing more wizards (e.g., for campaign creation)&lt;br&gt;&lt;br&gt;
🪲 Fixing annoying bugs&lt;br&gt;&lt;br&gt;
🛠 Starting to polish the operator flow and customer-side logic&lt;br&gt;&lt;br&gt;
🌍 Adding support for multiple languages&lt;/p&gt;




&lt;p&gt;That’s all for now! If you're building something similar or have questions about my tech stack or structure, let’s chat!&lt;/p&gt;

&lt;p&gt;I'll keep you posted.&lt;br&gt;&lt;br&gt;
Until next time—stay loyal 😄&lt;/p&gt;

</description>
      <category>development</category>
      <category>buildinpublic</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>#2 Refactoring Fidely &amp; Tackling Side Projects</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Mon, 24 Mar 2025 21:33:31 +0000</pubDate>
      <link>https://dev.to/pul/2-refactoring-fidely-tackling-side-projects-29ki</link>
      <guid>https://dev.to/pul/2-refactoring-fidely-tackling-side-projects-29ki</guid>
      <description>&lt;p&gt;Hello everyone,&lt;/p&gt;

&lt;p&gt;It’s been a while since my last update in &lt;em&gt;The 10-Minute Company&lt;/em&gt; series. I originally thought I’d be able to share progress sooner, but the holiday season (and a few unexpected projects) absorbed much of my free time. Nevertheless, I made some good progress—both on Fidely and on a smaller side project that popped up in early January.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Detour: Building a Landing Page with Next.js
&lt;/h2&gt;

&lt;p&gt;During the first two weeks of January, I helped a friend who offers online consultations by building a simple landing page for her services. The project was straightforward but fun, and it gave me a chance to work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Next.js&lt;/strong&gt; for the frontend,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Brevo&lt;/strong&gt; (formerly Sendinblue) for handling newsletter subscriptions and automated emails,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Brevo Meeting&lt;/strong&gt; for scheduling online consultations,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clerk.com&lt;/strong&gt; for authentication and an admin dashboard,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stripe&lt;/strong&gt; for handling payments and checkout.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the most interesting parts of the project was setting up an automated workflow: when someone subscribes to the newsletter and completes the &lt;strong&gt;double opt-in&lt;/strong&gt;, they receive a &lt;strong&gt;welcome coupon code&lt;/strong&gt; via email. This ensures only verified users get access to the special offer, adding an extra layer of engagement and trust.&lt;/p&gt;

&lt;p&gt;Now, back to Fidely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning to Fidely: Cleaning Up the Backend
&lt;/h2&gt;

&lt;p&gt;With the side project wrapped up, I finally got back to working on Fidely. The focus of the last few days has been restructuring the backend to improve maintainability and scalability. Here’s what I worked on:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Refactoring API Routes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I split API endpoints more logically, ensuring that different resources and functionalities were correctly separated. This cleanup makes the backend easier to navigate and will help with future expansions.&lt;/p&gt;

&lt;p&gt;Here’s a quick look at the updated routing system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"../../middlewares/authenticate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;authRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./auth"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;companiesRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./companies"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;campaignsRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./campaigns"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cardCampaignsRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./card-campaigns"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cardsRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./cards"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;transactionsRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./transactions"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;campaignBuildersRoutes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"./campaign-builders"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;v1Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Public routes (no auth required)&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Protected routes&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/companies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;companiesRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/campaigns"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaignsRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/card-campaigns"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cardCampaignsRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/cards"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cardsRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/transactions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transactionsRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="nf"&gt;.use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/campaign-builders"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaignBuildersRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="n"&gt;v1Routes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Creating a Simple Seeding System&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Manually setting up test data was becoming a hassle, so I implemented an automated seeding script that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Clears the database,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inserts fake data for testing and demo purposes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the updated seed system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;SeedContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="err"&gt;'.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;seedUsers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="err"&gt;'.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;seedCompanies&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="err"&gt;'.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;seedCampaigns&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="err"&gt;'.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;campaigns&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;seedCards&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="err"&gt;'.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cards&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SeedContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="n"&gt;campaigns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="n"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="n"&gt;catalogs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'🌱&lt;/span&gt; &lt;span class="n"&gt;Starting&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Seed users&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'Seeding&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;seedUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Seed companies&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'Seeding&lt;/span&gt; &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;seedCompanies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Seed campaigns&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'Seeding&lt;/span&gt; &lt;span class="n"&gt;campaigns&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;seedCampaigns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Seed cards&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'Seeding&lt;/span&gt; &lt;span class="n"&gt;cards&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;seedCards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'✅&lt;/span&gt; &lt;span class="n"&gt;Seed&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="nd"&gt;successfully!&lt;/span&gt;'&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nf"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;'❌ &lt;span class="n"&gt;Seed&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;'&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="nf"&gt;.exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the key advantages of using SQLite for both seeding and testing is the ability to spin up different databases for development and testing. This also allows for testing database migrations with Drizzle in a controlled environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Introducing Automated Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Fidely now has its first batch of automated tests! I’ve added both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unit tests&lt;/strong&gt; for core logic,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;End-to-end (E2E) tests&lt;/strong&gt; using Mocha and SuperAgent.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is just the beginning, but having a testing framework in place will make future development smoother and more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Struggles with Monorepos
&lt;/h2&gt;

&lt;p&gt;One of the biggest challenges I’ve encountered (and still haven’t solved) is setting up a monorepo for both frontend and backend. Since the whole project is in TypeScript, a monorepo could help share code between them.&lt;/p&gt;

&lt;p&gt;Yesterday, I spent several hours trying to migrate to &lt;strong&gt;pnpm workspaces&lt;/strong&gt;, but I ran into issues with &lt;strong&gt;better-sqlite3&lt;/strong&gt; during compilation. The new setup fails to find the compiled drivers—even after trying a &lt;strong&gt;postinstall recompilation&lt;/strong&gt;, nothing changed. 😫&lt;/p&gt;

&lt;p&gt;I haven’t figured out a solution yet, and for now, I don’t want to get stuck on this problem. If anyone has dealt with similar issues, I’d love to hear your thoughts! 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;I’m really happy with the backend refactor, and my next focus will be the frontend. The plan for the upcoming weeks includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enhancing the UI/UX,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continuing to add automated tests,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Abstracting the transaction management system to allow for different transaction sources (currently, only operators can generate transactions).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The overall goal remains the same: keeping the codebase clean and flexible so that Fidely can evolve naturally.&lt;/p&gt;

&lt;p&gt;That’s it for this update! If you’ve worked on similar refactors, monorepos, or pnpm workspace issues, I’d love to hear your experiences. Let’s chat in the comments or via email!&lt;/p&gt;

&lt;p&gt;Until next time! 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>#1 Fidely: Loyalty App Side Project</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Sun, 02 Feb 2025 10:30:17 +0000</pubDate>
      <link>https://dev.to/pul/1-fidely-loyalty-app-side-project-3a0c</link>
      <guid>https://dev.to/pul/1-fidely-loyalty-app-side-project-3a0c</guid>
      <description>&lt;p&gt;Hello everyone,&lt;/p&gt;

&lt;p&gt;Welcome to the first blog article of &lt;em&gt;The 10-Minute Company&lt;/em&gt; series! Today, I’m excited to introduce &lt;strong&gt;Fidely&lt;/strong&gt;, a simple digital loyalty app born from a conversation with a friend who owns a shop near my hometown.&lt;/p&gt;

&lt;p&gt;He showed me his printed stamp cards—those small cards that reward customers after they make a certain number of purchases. You’ve probably seen these before; they’re a straightforward way to build customer loyalty.&lt;/p&gt;

&lt;p&gt;Fidely (a “spaghetti-English” twist on the word “Fidelity”) is essentially a digital version of these loyalty campaigns. It aims to make the process more modern and efficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does Fidely Do?
&lt;/h3&gt;

&lt;p&gt;Fidely supports two types of loyalty campaigns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Points Collection&lt;/strong&gt;: Shop owners can create a catalog where each reward requires a specific number of points to redeem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stamp Campaigns&lt;/strong&gt;: Similar to traditional stamp cards, where customers receive a reward after a set number of purchases.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system generates a unique virtual card for each customer, which they can use to collect points or stamps. What’s even better? The same card works in any shop using Fidely, creating a seamless loyalty experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Did I Build This?
&lt;/h3&gt;

&lt;p&gt;I started this project about a month ago, but with limited free time—just a few evenings and weekends. My goal is to provide an easy and affordable tool for shop owners to create customized loyalty campaigns. Beyond that, I hope Fidely fosters a local network of offers, connecting shops and their loyal customers.&lt;/p&gt;

&lt;p&gt;With Fidely, shop owners can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Easily create virtual loyalty cards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Engage customers through marketing emails or app notifications (future feature).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build a community of interconnected businesses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s take a closer look at where I’m at with the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Web App: Current Features
&lt;/h3&gt;

&lt;p&gt;At this super early stage, Fidely is not even yet a proof of concept (PoC). Here’s what it can do so far:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Shop Owner Features:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Sign in with a pre-registered account.

- View a basic dashboard with insights and quick links.

- Create virtual cards for customers.

- Launch two types of campaigns: points collection and stamp-based rewards.

- Subscribe customer cards to campaigns.

- Assign points to cards, track progress, and display rewards.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Customer Features:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Collect points or stamps on their virtual card.

- Redeem rewards when reaching campaign goals.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s a glimpse of the app in action:&lt;/p&gt;

&lt;h4&gt;
  
  
  Login Page
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Home Dashboard
&lt;/h4&gt;

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

&lt;p&gt;As you can see, the app is pretty unstyled and basic at this point. Localization is also missing, so enjoy some Italian text sprinkled in. :D&lt;/p&gt;

&lt;h4&gt;
  
  
  Operator Dashboard
&lt;/h4&gt;

&lt;p&gt;One feature I’m working on is the operator view. This allows shop employees to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Retrieve customer cards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign points based on the current campaign.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notify customers when they’ve earned a reward.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a quick look at the operator’s workflow:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_VzBYx7hecU"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;h4&gt;
  
  
  Campaign Builder
&lt;/h4&gt;

&lt;p&gt;Shop owners can currently create stamp campaigns using this interface:&lt;/p&gt;

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

&lt;p&gt;Here, they can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Name the campaign.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the number of stamps required for a reward.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign values to stamps for easy tracking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define specific rewards for reaching milestones.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My Development Approach
&lt;/h3&gt;

&lt;p&gt;At this early stage, the app feels rough around the edges: bugs, inconsistent layouts, and no styling. But that’s intentional. Here’s how I approach side projects like Fidely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Build a Dirty Prototype:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Focus on selecting the tech stack and setting it up.

- Implement basic features to validate the idea.


This phase helps me:

- See results quickly, keeping motivation high.

- Identify design challenges early.

- Understand which code modules are essential.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Refactor the Backend:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Review and clean up the codebase.

- Organize routes and logic.

- Write tests for stability.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Polish the Frontend:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Improve UX and layout consistency.

- Refactor the frontend codebase for maintainability.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This incremental approach allows me to shift focus as needed, ensuring progress without getting overwhelmed. The key is identifying the minimal viable features to validate the idea while keeping the project flexible for future iterations.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;p&gt;Now that the basic functionality is in place, I’ll focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Refactoring and structuring the backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding test coverage for reliability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Organizing and improving the user interface.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll share updates as I go, though my free time varies, so posts may be sporadic.&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts! Have you tackled similar side projects? What development methodologies do you use? Let’s chat in the comments or via email!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>saas</category>
      <category>microsaas</category>
    </item>
    <item>
      <title>DevFest Milano 2024</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Mon, 06 Jan 2025 10:31:24 +0000</pubDate>
      <link>https://dev.to/pul/devfest-milano-2024-3pa9</link>
      <guid>https://dev.to/pul/devfest-milano-2024-3pa9</guid>
      <description>&lt;p&gt;At the end of last year I had the pleasure of attending &lt;strong&gt;DevFest Milan 2024&lt;/strong&gt; , an event organized by GDG (Google Developer Groups) communities worldwide.&lt;/p&gt;

&lt;p&gt;Living in a small town on the Ligurian west coast has its perksbetter quality of life, stunning views, and a slower pacebut networking opportunities for developers are rare. Most of the time, I rely on online communities to stay connected. Thats why, when I stumbled across this conference on Eventbrite, I didnt think twice before grabbing a ticket (which, by the way, was free!).&lt;/p&gt;

&lt;p&gt;The event was held in Milan, attracting a mix of local developers, students, and even attendees from abroad. It was wonderful to experience such an inclusive and welcoming atmosphere.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Spotlight on AI
&lt;/h3&gt;

&lt;p&gt;The conference heavily focused on &lt;strong&gt;artificial intelligence&lt;/strong&gt; , which makes perfect sense given its prominence in tech over the past few years. Here are the talks I attended:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dealing with GenAI agents and rapid-fire messaging&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Da Documenti Statici a Risposte Immediate: La Rivoluzione AI nel Settore Industriale&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dagli atomi ai template: Come sviluppare un design system senza perderci la testa!&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gemini Functions Calls in Flutter&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLSA on GCP: Let's Mitigate Supply Chain Threats&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pretotyping in the Real World - Quickly Iterating Between Good and Bad Startup Ideas&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generative AI Unveiled: From Fundamentals to Real-World Applications&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bringing Fictional Characters to Life with Open Source LLMs&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The conference was well-organized, and every talk I attended was engaging and informative. Let me share some highlights from my favorite sessions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Highlights from the Talks
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Dealing with GenAI Agents and Rapid-Fire Messaging&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This talk by &lt;a href="https://linkedin.com/in/danilotrombino/en" rel="noopener noreferrer"&gt;&lt;strong&gt;Danilo Trombino&lt;/strong&gt;&lt;/a&gt; explored a fascinating aspect of AI chatbots that I hadn't considered before: managing user interactions in real-time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrpsoalb8amju6stjuw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrpsoalb8amju6stjuw6.png" alt="DevFestMilano 2024 Danilo Trombino Talk about AI Chatbots" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Different users communicate differentlysome send fully detailed messages in one go, while others prefer a chatty style, breaking their thoughts into multiple short messages. Adding to the complexity, the time users take to type their messages can also vary significantly.&lt;/p&gt;

&lt;p&gt;Danilo introduced a clever solution to handle these challenges using &lt;strong&gt;Redis&lt;/strong&gt;. By assigning an expiring key to each users message, Redis tracks activity in real-time. If no new messages are sent within a specific time frame, the expiration triggers a request to the AI. This approach not only minimizes unnecessary calls to the AI service but also supports scalability by using Redis as a centralized system across multiple application instances.&lt;/p&gt;

&lt;p&gt;The insights were practical, and Danilos clear explanations made it one of the standout talks for me.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Da Documenti Statici a Risposte Immediate: La Rivoluzione AI nel Settore Industriale&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This was easily my favorite talk of the conference. While the topicbuilding a &lt;strong&gt;retrieval-augmented generation (RAG)&lt;/strong&gt; system for internal documentationmight not sound glamorous, &lt;a href="https://www.linkedin.com/in/desimonechristian/" rel="noopener noreferrer"&gt;&lt;strong&gt;Christian&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a href="https://www.linkedin.com/in/andrea-caglio/" rel="noopener noreferrer"&gt;&lt;strong&gt;Andrea&lt;/strong&gt;&lt;/a&gt; brought it to life by sharing real-world challenges they faced while implementing the system for a large client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kmra1xfd66sk2fe4n3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kmra1xfd66sk2fe4n3l.png" alt="DveFest Milano 2024 RAG systems" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Their use of &lt;strong&gt;Haystack&lt;/strong&gt; pipelines to process and integrate data with ChatGPT-based assistants was inspiring. It was a reminder of what I love most about my work: solving real problems. A system like this can genuinely improve a companys efficiency, and the way they tackled these challenges was nothing short of impressive.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Gemini Functions Calls in Flutter&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Though Ive never worked with Flutter, &lt;a href="https://www.linkedin.com/in/clucera/" rel="noopener noreferrer"&gt;&lt;strong&gt;Carlo Lucera&lt;/strong&gt;&lt;/a&gt; made this talk highly accessible. He walked us through a practical example of using &lt;strong&gt;Gemini function calls&lt;/strong&gt; in a Flutter app to retrieve real-time information about DevFests worldwide.&lt;/p&gt;

&lt;p&gt;It was a well-structured session, and Carlos clarity in explaining the integration made me curious to try Flutter in the future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsu4inpptdlt3jf76an44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsu4inpptdlt3jf76an44.png" alt="Dev Fest Milano 2024 gemini functions Carlo Lucera" width="528" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Generative AI Unveiled: From Fundamentals to Real-World Applications&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://linkedin.com/in/levinyonatan" rel="noopener noreferrer"&gt;&lt;strong&gt;Yonatan Levin&lt;/strong&gt;&lt;/a&gt; delivered a thought-provoking talk on optimizing search results in RAG systems using &lt;strong&gt;graph databases&lt;/strong&gt; for embeddings. The ideas were advanced yet presented in a way that was easy to follow.&lt;/p&gt;

&lt;p&gt;Unfortunately, the session ended before there was time for Q&amp;amp;A. Id love to see a sequel to this talk in a future conferenceit definitely left me wanting more!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6r7n240sy3v8z6f3eq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6r7n240sy3v8z6f3eq4.png" alt="DevFest Milano 2024 Yonatan Levin Monday.com RAG graph database for optimization" width="527" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Attending DevFest Milan 2024 was a refreshing experience. While the topics werent overly advanced, they struck the right balance for a community-driven event that aims to engage developers of all levels.&lt;/p&gt;

&lt;p&gt;If youre a developer looking for inspiration, networking, or just a reason to step away from your screen, Id highly recommend keeping an eye out for the next DevFest near you. And if youre lucky enough to live close to Milan, dont miss it!&lt;/p&gt;

</description>
      <category>devfest2024</category>
      <category>conference</category>
      <category>milano</category>
    </item>
    <item>
      <title>#4 Daily Rabbit Holes: Cracking the Azure B2C Puzzle</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Tue, 17 Dec 2024 07:04:30 +0000</pubDate>
      <link>https://dev.to/pul/4-daily-rabbit-holes-cracking-the-azure-b2c-puzzle-mp9</link>
      <guid>https://dev.to/pul/4-daily-rabbit-holes-cracking-the-azure-b2c-puzzle-mp9</guid>
      <description>&lt;p&gt;Today was one of &lt;em&gt;those&lt;/em&gt; days—a deep dive into the mysterious world of Azure B2C. Or, as I like to call it, a journey through the hidden labyrinth of Azure Identity.&lt;/p&gt;

&lt;p&gt;For some reason, working with Azure Identity is never straightforward for me. Don’t get me wrong—Microsoft Azure’s documentation can be excellent for many services. For example, setting up a basic Vision API project was a breeze, and I’d even say the .NET Core documentation is top-notch.&lt;/p&gt;

&lt;p&gt;But Azure Identity? That’s a different story.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge
&lt;/h3&gt;

&lt;p&gt;I’ve worked with Microsoft Entra (the new branding for Azure Identity services) numerous times, and setting up an &lt;strong&gt;App Registration&lt;/strong&gt; is something I’ve come to expect in my day-to-day tasks. Today, however, the goal was to explore &lt;strong&gt;Azure B2C&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  What Is Azure B2C?
&lt;/h4&gt;

&lt;p&gt;In simple terms, Azure B2C is a Microsoft service that allows you to create a &lt;strong&gt;white-labeled user management platform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of it as an offshoot of Entra ID (formerly Azure Active Directory), tailored specifically for managing users who are external to your organization. While Entra ID is designed to handle internal users—employees, contractors, etc.—Azure B2C is aimed at customers or other external users.&lt;/p&gt;

&lt;p&gt;With Azure B2C, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create sign-up and sign-in flows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Customize the UI to match your brand&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle password reset flows automatically&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate third-party identity providers like Google, Facebook, or Apple&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re familiar with &lt;strong&gt;Auth0&lt;/strong&gt; or &lt;strong&gt;Clerk&lt;/strong&gt;, the concept is similar.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Goal
&lt;/h3&gt;

&lt;p&gt;Here were the requirements for my project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; A React-based SPA (preferably with Vite).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication:&lt;/strong&gt; Trusted user management using Azure B2C.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backend:&lt;/strong&gt; Node.js or .NET Core API with bearer token authentication.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It sounded simple enough. But the moment I started looking at the documentation, I found myself buried under outdated repositories, scattered information, and broken links.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Struggle
&lt;/h3&gt;

&lt;p&gt;It’s a common scenario: a React SPA talking to a Node.js backend, secured with Azure B2C. Yet, the docs felt like a treasure hunt. I kept opening new tabs—at one point, I had over 20 Chrome tabs trying to piece everything together.&lt;/p&gt;

&lt;p&gt;After hours of tinkering, I managed to get a basic example working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A React app (using &lt;strong&gt;Create React App&lt;/strong&gt;, not Vite, unfortunately).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Node.js backend (Express-based).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources That Finally Worked
&lt;/h3&gt;

&lt;p&gt;If you’re attempting the same setup, here are the key resources that worked for me:&lt;/p&gt;

&lt;h4&gt;
  
  
  Frontend:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/samples/msal-react-samples/b2c-sample" rel="noopener noreferrer"&gt;MSAL React B2C Sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Backend:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Azure-Samples/active-directory-b2c-javascript-nodejs-webapi" rel="noopener noreferrer"&gt;Node.js Web API with Azure B2C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Azure B2C Configuration:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-user-flow" rel="noopener noreferrer"&gt;Create User Flows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking at these three links now, it feels so obvious. But finding and connecting them wasn’t easy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;Azure B2C and Microsoft Identity Platform are incredibly powerful, but navigating the documentation is challenging. Part of the issue seems to be the sheer breadth of features—combined with the need to support legacy systems like Active Directory.&lt;/p&gt;

&lt;p&gt;In fairness, maintaining updated documentation while evolving services like Entra ID is no small feat.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;p&gt;To streamline future projects, I’m building a small boilerplate using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React + Vite + Tailwind + Shadcn&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Azure B2C&lt;/strong&gt; (or… maybe something else?)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node.js (Express + Passport)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once it’s ready, I’ll update this article with the boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Plot Twist
&lt;/h3&gt;

&lt;p&gt;Every good rabbit hole has a twist, and this one’s no different.&lt;/p&gt;

&lt;p&gt;Just as I wrapped my head around Azure B2C, I stumbled upon &lt;strong&gt;Microsoft Entra External ID&lt;/strong&gt;—which, they claim, is even better.&lt;/p&gt;

&lt;p&gt;Apparently, Azure B2C will eventually be replaced by Entra External ID. So, if you’re starting fresh, it might be worth exploring this newer option.&lt;/p&gt;

&lt;p&gt;The rabbit hole continues…&lt;/p&gt;

</description>
      <category>azure</category>
      <category>development</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>The 10-Minute Company: zero to PoC 10 minutes per day</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Fri, 13 Dec 2024 06:54:38 +0000</pubDate>
      <link>https://dev.to/pul/the-10-minute-company-zero-to-poc-10-minutes-per-day-52a7</link>
      <guid>https://dev.to/pul/the-10-minute-company-zero-to-poc-10-minutes-per-day-52a7</guid>
      <description>&lt;p&gt;Hello everyone,&lt;/p&gt;

&lt;p&gt;As I mentioned in a &lt;a href="https://pul.hashnode.dev/3-daily-rabbit-holes-rust-useful-resources-deno-side-projects" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;, I’ve embarked on a new series called &lt;em&gt;The 10-Minute Company&lt;/em&gt;. This idea has been on my to-do list for years. Now that it’s finally happening, I can’t decide whether to feel thrilled or terrified—probably a mix of both! Over the next few months, I’ll be dedicating significant effort to this project.&lt;/p&gt;

&lt;p&gt;In short, the concept behind this series is simple: pick an idea (ideally a small one), develop it, and journal the process publicly. It aligns closely with the “build in public” philosophy but on a smaller, more approachable scale.&lt;/p&gt;

&lt;p&gt;I’m fully aware this won’t be an easy journey. Creating software is already challenging, and doing it in public adds a whole new layer of difficulty—at least for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Series?
&lt;/h2&gt;

&lt;p&gt;This is a challenge, no doubt about it, especially because it requires consistency. However, I believe the potential benefits make it worthwhile.&lt;/p&gt;

&lt;p&gt;Before diving into my goals and expectations, let me share some context about my life and why I think this series could be beneficial, both for me and for others in my field.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Few Facts About Me
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I love learning about tech-related topics, often after my daily work hours.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I rarely create tangible examples or demos for the challenges I explore.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My interests span various domains beyond software, which often spark ideas for my projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I enjoy designing software to solve specific problems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My free time is limited.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I need a structured way to stay focused on my side projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since I began working in the field in 2011, I noticed that many job opportunities in the Italian tech scene came from consultancy firms that typically handle diverse projects and tech stacks. This led me to focus on broadening my knowledge across multiple topics, as it provided a more straightforward path to staying relevant and valuable in such a dynamic environment.&lt;/p&gt;

&lt;p&gt;As a result, I adopted the habit of learning outside work, focusing on topics unrelated to my current job. This strategy has shaped my professional journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pros and Cons of My Approach
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Expanding knowledge while staying updated on trends and concepts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Participating in developer meetups to learn from peers working on diverse projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practicing coding and mastering new technologies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reducing job-related risks by broadening my skill set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connecting dots between technologies, architectures, and methodologies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discovering better solutions by knowing more options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identifying recurring patterns and requirements across different projects and tech stacks, which helps prioritize learning.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Time constraints&lt;/strong&gt;: The day is still only 24 hours, and this approach has forced me to sacrifice other passions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Surface-level engagement&lt;/strong&gt;: While I value adaptability, I sometimes feel that “use the right tool for the job” oversimplifies reality. Learning a new framework or language should be a necessity that arises after maximizing the tools already at your disposal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Misaligned perceptions&lt;/strong&gt;: Some employers—especially those outside the tech core business—fail to recognize the value of this knowledge. This can lead to undervaluing professional expertise and bypassing important processes like documentation, skill development, and fostering innovation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Shift in Perspective
&lt;/h2&gt;

&lt;p&gt;While my focus on continuous learning has served me well, it’s time to shift gears. I want to channel the skills I’ve built over the years into concrete projects. Instead of just expanding my knowledge, I’ll now prioritize applying it to bring my ideas to life.&lt;/p&gt;

&lt;p&gt;This blog and the &lt;em&gt;10-Minute Company&lt;/em&gt; series are tools to keep me focused and accountable. Turning an idea into a working example requires a mix of skills—not just coding—which will push me to explore new perspectives.&lt;/p&gt;

&lt;p&gt;I’m excited about the opportunity to grow, not only technically but also in terms of communication and networking.&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts! Any constructive feedback or support you can offer would make a huge difference in keeping this series alive and thriving.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>#3 Daily Rabbit Holes: Rust Useful Resources + Deno + Side Projects</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Thu, 05 Dec 2024 06:22:54 +0000</pubDate>
      <link>https://dev.to/pul/3-daily-rabbit-holes-rust-useful-resources-deno-side-projects-4fli</link>
      <guid>https://dev.to/pul/3-daily-rabbit-holes-rust-useful-resources-deno-side-projects-4fli</guid>
      <description>&lt;p&gt;Today, like the past few days, I’ve spent nearly all my free time diving into the &lt;strong&gt;Rust&lt;/strong&gt; + &lt;strong&gt;Deno&lt;/strong&gt; ecosystem. It’s a rabbit hole I can’t seem to escape—but I’m loving every second of it!&lt;/p&gt;

&lt;p&gt;Here’s a list of links and resources I’ve come across that seem particularly valuable. Some are comprehensive collections, so it’ll take a bit of time to figure out which ones to follow deeply.&lt;/p&gt;

&lt;p&gt;As a general rule, I don’t want to learn &lt;strong&gt;Rust&lt;/strong&gt; by watching endless tutorials. Instead, I prefer a hands-on approach: reading interesting codebases and experimenting directly.&lt;/p&gt;

&lt;p&gt;As a &lt;strong&gt;Node.js&lt;/strong&gt; developer, I find &lt;strong&gt;Deno&lt;/strong&gt; fascinating. It’s a project that offers so much to learn, from low-level programming concepts to building finished products.&lt;/p&gt;

&lt;p&gt;Here’s a list of the best resources I discovered today:&lt;/p&gt;

&lt;h4&gt;
  
  
  Recommended Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/google/comprehensive-rust" rel="noopener noreferrer"&gt;&lt;strong&gt;Comprehensive Rust&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
A very well-written “book” by the Android Team at Google.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gist.github.com/cedrickchee/f729e848b52eab8fbc88a3910072198c" rel="noopener noreferrer"&gt;&lt;strong&gt;Rust Resources List&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
An “awesome” list with tons of useful links, especially the blog section.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.ralfj.de/projects/rust-101/main.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Rust 101&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Covers topics from basics to advanced. It’s concise—maybe too concise—but that could be a plus if you don’t want to spend too much time on tutorials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ImplFerris/LearnRust" rel="noopener noreferrer"&gt;&lt;strong&gt;LearnRust&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
A highly curated list for all expertise levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://choubey.gitbook.io/internals-of-deno/architecture/core" rel="noopener noreferrer"&gt;&lt;strong&gt;Internals of Deno&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
At the moment, this is the most interesting one for me. It dives into Deno’s architecture and internals.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve decided to start with the last one since I’m really curious about how Deno works behind the scenes (at least at a high level). Over the past few days, I’ve particularly enjoyed learning about V8 isolates.&lt;/p&gt;

&lt;p&gt;I’ll keep you updated if I discover more interesting resources!&lt;/p&gt;




&lt;h3&gt;
  
  
  When Rust and Deno Take Over Your Side Projects
&lt;/h3&gt;

&lt;p&gt;Okay, the title might be a bit long and clunky, but it perfectly sums up my current situation. I’m enjoying learning about &lt;strong&gt;V8&lt;/strong&gt;, &lt;strong&gt;Rust&lt;/strong&gt;, and &lt;strong&gt;Deno&lt;/strong&gt;, but it’s eating up way too much of my free time.&lt;/p&gt;

&lt;p&gt;I’m sure I’m not alone in struggling to find the right balance between work, life, side projects, and study.&lt;/p&gt;

&lt;p&gt;Last month, I started a new side project—simple enough for a solo developer (at least in its early stages) but interesting enough to eventually grow into a real product.&lt;/p&gt;

&lt;p&gt;For me, one of the best parts of my job is creating software or products that can improve people’s daily lives.&lt;/p&gt;

&lt;p&gt;I don’t think you need a groundbreaking idea to create a good product. Often, just listening to people or friends is enough to uncover small niches where you can build something useful.&lt;/p&gt;

&lt;p&gt;This process is a great way to improve all the skills related to product development—and I’m not just talking about coding. It’s also about system design, writing good requirements, documentation, choosing the right tools, testing the market, gathering feedback, finding early adopters, and so much more.&lt;/p&gt;

&lt;p&gt;In the next few days, I’ll write a blog post to introduce my new side project. My goal is to keep it alive, at least until I have a working proof of concept.&lt;/p&gt;




&lt;h3&gt;
  
  
  Introducing &lt;em&gt;The 10-Minute Company&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;To stay focused on developing my project, I’ve decided to share my journey in a new series called &lt;strong&gt;“The 10-Minute Company”&lt;/strong&gt;. I’ll document my side projects, starting from scratch and working toward a functional PoC.&lt;/p&gt;

&lt;p&gt;Stay tuned for all the details! 🚀&lt;/p&gt;

</description>
      <category>rust</category>
      <category>deno</category>
      <category>sideprojects</category>
      <category>javascript</category>
    </item>
    <item>
      <title>#2 Daily Rabbit Holes: Diving Deeper into Rust, V8, and the JavaScript™️ Saga</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Mon, 02 Dec 2024 20:10:45 +0000</pubDate>
      <link>https://dev.to/pul/2-daily-rabbit-holes-diving-deeper-into-rust-v8-and-the-javascript-saga-5ajc</link>
      <guid>https://dev.to/pul/2-daily-rabbit-holes-diving-deeper-into-rust-v8-and-the-javascript-saga-5ajc</guid>
      <description>&lt;p&gt;Unfortunately, today I had very little time to dive into interesting topics. I spent some time on a side project (which I’ll probably write about in the coming days), worked on my day job, and did some sports. Still, my focus remains on &lt;strong&gt;Deno&lt;/strong&gt;, &lt;strong&gt;Rust&lt;/strong&gt;, and the &lt;strong&gt;V8 engine&lt;/strong&gt;, just like in my &lt;a href="https://pul.hashnode.dev/1-daily-rabbit-holes-rusty-v8-nodejs-and-deno" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I managed to review the &lt;a href="https://dzx.cz/2023-03-08/how_do_cloudflare_workers_work/" rel="noopener noreferrer"&gt;fantastic article&lt;/a&gt; by &lt;a href="https://dzx.cz/about/" rel="noopener noreferrer"&gt;Matouš Dzivjak&lt;/a&gt;, where he explains how to build a runtime using &lt;strong&gt;Rust V8&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code from the article is a bit outdated and doesn’t run with the current version of Rust. I managed to get it working somehow, even though I don’t actually know Rust yet (so it’s either an easy task or I just got really lucky).&lt;/p&gt;

&lt;p&gt;Below is the updated code with minor tweaks and some comments to help with understanding. All credits, of course, go to Matouš.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Breakdown
&lt;/h3&gt;

&lt;p&gt;This code demonstrates how to build a &lt;strong&gt;minimal JavaScript runtime using Rust&lt;/strong&gt; and the &lt;strong&gt;V8 engine&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Platform and V8 Initialization:&lt;/strong&gt; The &lt;a href="http://main.rs" rel="noopener noreferrer"&gt;main.rs&lt;/a&gt; file initializes the V8 engine and platform, preparing it to execute JavaScript code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime Setup:&lt;/strong&gt; A global object (&lt;em&gt;globalThis.workerHandler&lt;/em&gt;) is exposed in the runtime using JavaScript, enabling a Rust function to be callable from JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Script Compilation:&lt;/strong&gt; The build_worker function compiles and evaluates the JavaScript code, combining the &lt;em&gt;runtime script&lt;/em&gt; and a &lt;em&gt;worker_script&lt;/em&gt; that defines a handler function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Context Binding:&lt;/strong&gt; Rust functions, such as &lt;em&gt;sayHello&lt;/em&gt;, are exposed to the V8 runtime by binding them to global object properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Function Execution:&lt;/strong&gt; The run_worker function calls the JavaScript handler function from Rust, passing parameters and printing the result (Hello World) to the console.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// runtime.js&lt;/span&gt;
&lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workerHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Platform and V8 initialization&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.make_shared&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;V8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;initialize_platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;V8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// `include_str!` is a Rust macro that loads a file and converts it into a Rust string&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;include_str!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"runtime.js"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;worker_script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r#"
    export function handler(y) {
        return sayHello(y);
    };
    "#&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// The runtime.js file exposes the `handler` function as a global object&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;r#"
        {runtime}
        {worker_script}
        "#&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Create a V8 isolate with default parameters&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;isolate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Isolate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;CreateParams&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup_runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;worker_scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HandleScope&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="nf"&gt;.as_mut&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;run_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;V8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;V8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispose_platform&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Set up the global runtime context&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;setup_runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OwnedIsolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a handle scope for all isolate handles    &lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;isolate_scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HandleScope&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// ObjectTemplate is used to create objects inside the isolate&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;globals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ObjectTemplate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate_scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// The function name to bind to the Rust implementation&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;resource_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sayHello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Expose the function to the global object&lt;/span&gt;
    &lt;span class="n"&gt;globals&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;resource_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;say_hello_binding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a context for isolate execution&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ContextOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;global_template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nn"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;global_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context_options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Create and return the global context&lt;/span&gt;
    &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Global&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;global_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Define the Rust binding for the sayHello function&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;say_hello_binding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandleScope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionCallbackArguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ReturnValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_rust_string_lossy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;format!&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="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Build the worker by compiling and instantiating the script&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;build_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandleScope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;resource_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"script.js"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// The source map is optional and used for debugging purposes&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;source_map_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"placeholder"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;script_compiler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ScriptOrigin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;resource_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;source_map_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;None&lt;/span&gt;
        &lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Compile and evaluate the module&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;script_compiler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;compile_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="nf"&gt;.instantiate_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="nf"&gt;.evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// open a global scope associated to the worker_scope&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// create and assign the handler to the global context&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.global&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handler_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"workerHandler"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;js_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handler_key&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;local_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Local&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;js_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Global&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;local_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Run the worker and execute the `handler` function&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;run_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandleScope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="nf"&gt;.open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.global&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// call the handler and get the result&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="nf"&gt;.call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Local&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Handler did not return a string"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.to_rust_string_lossy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;todo!&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I strongly encourage you to read Matouš Dzivjak’s excellent article for a deeper dive into the code and its concepts. This was just a summary—his detailed explanations are essential for understanding the technical nuances!&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Petition!
&lt;/h2&gt;

&lt;p&gt;By the way, I had completely forgotten that Oracle owns the &lt;strong&gt;JavaScript&lt;/strong&gt; trademark—something I already knew but slipped my mind. This week, Deno’s petition to cancel the trademark served as a reminder of this curious fact.&lt;/p&gt;

&lt;p&gt;If you're interested in learning more, check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://javascript.tm/" rel="noopener noreferrer"&gt;https://javascript.tm/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://deno.com/blog/deno-v-oracle" rel="noopener noreferrer"&gt;https://deno.com/blog/deno-v-oracle&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>dailyrabbitholes</category>
      <category>rust</category>
      <category>deno</category>
    </item>
    <item>
      <title>#1 Daily Rabbit Holes: Rusty V8, Node.js and Deno</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Sat, 30 Nov 2024 08:26:57 +0000</pubDate>
      <link>https://dev.to/pul/1-daily-rabbit-holes-rusty-v8-nodejs-and-deno-4b8j</link>
      <guid>https://dev.to/pul/1-daily-rabbit-holes-rusty-v8-nodejs-and-deno-4b8j</guid>
      <description>&lt;p&gt;This series is essentially a notebook where I document the things I learn online during my limited free time—usually early in the morning or late at night.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today’s rabbit hole&lt;/strong&gt; started with &lt;a href="https://deno.com/deploy" rel="noopener noreferrer"&gt;Deno Deploy&lt;/a&gt;, which powers serverless functions for services like &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; and &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unlike traditional serverless environments such as AWS Lambda, which rely on micro-VMs (via &lt;a href="https://firecracker-microvm.github.io/" rel="noopener noreferrer"&gt;Firecracker&lt;/a&gt;) or containers, Deno Deploy uses &lt;strong&gt;V8 Isolates&lt;/strong&gt;. Intrigued, I decided to dive deeper into &lt;strong&gt;Rusty V8&lt;/strong&gt;—the Rust bindings for V8—and learn more about how isolates work.&lt;/p&gt;

&lt;p&gt;Here’s the repo: &lt;a href="https://github.com/denoland/rusty_v8" rel="noopener noreferrer"&gt;github.com/denoland/rusty_v8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m learning Rust alongside many other interests, and I’ve found that &lt;strong&gt;reading codebases I’m genuinely curious about is one of the best ways to pick up a new language&lt;/strong&gt;, explore concepts, and understand technologies.&lt;/p&gt;

&lt;p&gt;That said, this is a rough overview of my findings so far. There might be errors, but consider this post a starting point for your own rabbit hole! 😄&lt;/p&gt;




&lt;h2&gt;
  
  
  Exploring the Codebase
&lt;/h2&gt;

&lt;p&gt;I started exploring the &lt;code&gt;rusty_v8&lt;/code&gt; codebase and was impressed by how closely it mirrors the original V8 implementation. This alignment makes it easier to find relevant documentation and examples online.&lt;/p&gt;

&lt;p&gt;The code is well-organized, and I focused on how the bindings reference the underlying V8 code.&lt;/p&gt;

&lt;h3&gt;
  
  
  BackingStore: Memory Behind the Scenes
&lt;/h3&gt;

&lt;p&gt;One interesting discovery was the &lt;strong&gt;ArrayBuffer&lt;/strong&gt;, a contiguous block of memory used to store binary data. What caught my attention was the &lt;strong&gt;BackingStore&lt;/strong&gt;—an abstraction that manages the raw memory backing the ArrayBuffer.&lt;/p&gt;

&lt;p&gt;In simpler terms, the BackingStore represents the memory area (allocated by the operating system) where the data of an ArrayBuffer is stored. V8 handles this memory, including garbage collection, ensuring efficient memory management.&lt;/p&gt;




&lt;h2&gt;
  
  
  Inside the V8 Engine
&lt;/h2&gt;

&lt;p&gt;Curious about how V8 works at a deeper level, I turned to its &lt;a href="https://v8.dev/docs" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. Given the complexity of the project, I decided to approach it as a "black box" and started by reading how to embed V8 into an application.&lt;/p&gt;

&lt;p&gt;A great resource was the &lt;a href="https://v8.dev/docs/embed" rel="noopener noreferrer"&gt;hello world example&lt;/a&gt;, which demonstrates embedding V8 in a C++ application. Rusty V8 provides a similar example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;rustCopia&lt;/span&gt; &lt;span class="n"&gt;codicelet&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_default_platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.make_shared&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;V8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;initialize_platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;V8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;isolate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Isolate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HandleScope&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ContextScope&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"'Hello' + ' World!'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"JavaScript code: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="nf"&gt;.to_rust_string_lossy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;v8&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Script&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Result: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.to_rust_string_lossy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example introduces four key concepts in V8:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Platform&lt;/strong&gt;: The environment where V8 runs. For example, a browser has a different platform implementation than Node.js.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolate&lt;/strong&gt;: A memory-isolated instance of the V8 engine, designed to run untrusted JavaScript code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handles&lt;/strong&gt;: References to JavaScript objects. A &lt;strong&gt;HandleScope&lt;/strong&gt; acts as a container for these handles, allowing the garbage collector to efficiently free memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;: The execution context, including global objects and variables, for JavaScript code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After initializing these components, the code is compiled and executed within the isolate.&lt;/p&gt;

&lt;p&gt;One fascinating aspect of this process is the ability to expose custom runtime functionalities to the code running inside the isolate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Expanding the Rabbit Hole
&lt;/h2&gt;

&lt;p&gt;I also explored two articles that delve into building custom runtimes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://deno.com/blog/roll-your-own-javascript-runtime" rel="noopener noreferrer"&gt;“Roll Your Own JavaScript Runtime”&lt;/a&gt; explains how to use &lt;code&gt;deno_core&lt;/code&gt; to create a custom runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dzx.cz/2023-03-08/how_do_cloudflare_workers_work/" rel="noopener noreferrer"&gt;“How Do Cloudflare Workers Work?”&lt;/a&gt; walks through creating a basic runtime with a single JavaScript function exposed to the isolate. Although the code is slightly outdated, it’s easy to adapt.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These resources sparked new questions about the relationship between &lt;strong&gt;libuv&lt;/strong&gt; (which powers Node.js’s async functionality) and V8, and how this differs from Deno's architecture—definitely something for another rabbit hole!&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;I know this series might not be polished or easy to read, and I’m still learning as I go. But sharing my notes helps me stay organized and serves as a reference for my future self.&lt;/p&gt;

&lt;p&gt;If you’re curious about these topics or have insights to share, let me know! Until the next rabbit hole, happy exploring! 🐇&lt;/p&gt;

</description>
      <category>rust</category>
      <category>deno</category>
      <category>node</category>
      <category>v8</category>
    </item>
    <item>
      <title>Jamstack: Modern Web Development Made Easy</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Sat, 07 Jan 2023 21:44:33 +0000</pubDate>
      <link>https://dev.to/pul/jamstack-modern-web-development-made-easy-52dg</link>
      <guid>https://dev.to/pul/jamstack-modern-web-development-made-easy-52dg</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Jamstack&lt;/strong&gt; is a web development architecture that has gained popularity in recent years due to its speed, security, and scalability. It refers to Javascript, APIs, and Markup as the three main components of the stack. While the techniques used in the Jamstack are not necessarily new, they have been combined in innovative ways to create a modern and efficient web development architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it all started
&lt;/h2&gt;

&lt;p&gt;The Jamstack is a relatively new web development architecture that emerged in the early 2010s to address the increasing complexity of modern web applications and the need for speed, security, and scalability. One of the key features of the Jamstack is the use of static content. In web development, static files are resources that are generated once at build time and served to each client without change. These files can include assets like images, HTML, and Javascript, but in the JAM Stack, the term 'static' also refers to content generated by the server and consumed by the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic vs client side vs static approach
&lt;/h3&gt;

&lt;p&gt;Traditionally, web pages have been served using two main approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server side&lt;/strong&gt; where the server generates a web page and sends it back to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client side&lt;/strong&gt; (Single Page Applications):  where the server basically sends an empty page with Javascript assets to the client, which then queries a remote API and generates the page directly in the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Server-side rendering is the more common approach and has been used for many years, but it can have limitations in terms of performance, as the server has to generate a new page for each request. Client-side rendering, on the other hand, can be more performant in terms of user experience after the first page load, as the browser only has to download and render the Javascript assets once. However, it can have slower initial load times and can be less effective for SEO, as the content is not served from the server.&lt;/p&gt;

&lt;p&gt;The static approach, used in the Jamstack, allows a server or CDN to serve a pre-built page that can be immediately shown to the user, improving performance. The Jamstack aims to maximize the use of static assets and content, while also allowing for the use of other techniques in specific sections of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefit of using the Jamstack
&lt;/h2&gt;

&lt;p&gt;Here are some benefit of using this architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;As said before, one of the key features of the Jamstack is that it relies on &lt;strong&gt;static markup&lt;/strong&gt;, which can be served from a CDN (Content Delivery Network). This means that the server does not have to dynamically generate HTML, making the website or web application faster to load and more performant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interoperability
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;APIs&lt;/strong&gt; (Application Programming Interfaces) are used to connect the frontend of a Jamstack applications to any necessary back-end services or databases. This decoupling of the frontend and the backend makes it easier to evolve and maintain the web applications.&lt;/p&gt;

&lt;p&gt;You can also rely on a single content API for a mobile app and a web app using a centralized source of content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoupling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Javascript is used to create dynamic and interactive features on the frontend&lt;/strong&gt;. This can include anything from simple form validation to more complex features like real-time updates or offline support.&lt;/p&gt;

&lt;p&gt;Some framework allows developers to create static content at build time that will be re-hydrated client side by Javascript. This allow to have fast load time and all the features that a SPA can have.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Faster deployment and easier scaling&lt;/strong&gt; are another benefit of using this architecture. Because the HTML is pre-built and served from a CDN, there is no need for a server to handle requests, making it easy to deploy and scale the application especially with specialized services that we will see in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;Not having a server and a database to maintain means also reduce the risk of attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Costs
&lt;/h3&gt;

&lt;p&gt;Serving mainly static content decrease the computational cost of your service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is a matter of tooling
&lt;/h2&gt;

&lt;p&gt;The techniques used in Jamstack have been around for many years but they have been revised with the development of toolchain that helps developers to create their applications.&lt;/p&gt;

&lt;p&gt;Static site generators, headless CMS, serverless functions and one click deployment services (such as &lt;a href="https://netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;) are pieces of this new pattern in web development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static site generators
&lt;/h3&gt;

&lt;p&gt;Static site generators allows developers to generate a static website from templates and content stored in flat files or APIs.&lt;/p&gt;

&lt;p&gt;Key benefit of these tools are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performance and speed: Static sites are typically faster and more performant than dynamic sites, as they do not require server-side rendering and can be served from CDN closer to the user location.&lt;/li&gt;
&lt;li&gt;Security: Static sites are also more secure than dynamic sites, as they do not have the vulnerabilities that are associated with server-side rendering. This makes them attractive to developers who are building secure websites and web applications.&lt;/li&gt;
&lt;li&gt;Ease of development: if you can store your content in flat files than you don’t need to maintain a complex backend.&lt;/li&gt;
&lt;li&gt;Scalability: Static sites are also easier to scale than dynamic sites, as they do not require the same level of server infrastructure and can be easily deployed on CDNs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tools and Frameworks such as &lt;a href="https://www.gatsbyjs.com" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;, &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Nextjs&lt;/a&gt;, Hugo are great choices for creating static sites.&lt;/p&gt;

&lt;p&gt;They have a great developer experience and can be used to build hybrid application with section that are completely static and parts that can be feature rich like single page applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Headless CMS
&lt;/h3&gt;

&lt;p&gt;A headless CMS is a backend-only content management system that exposes its content via APIs. This allows developers to use the content stored in the CMS to power their Jamstack web application.&lt;/p&gt;

&lt;p&gt;You can host your CMS using solution like &lt;a href="https://strapi.io/" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt; or use hosted CMS like &lt;a href="https://www.contentful.com/" rel="noopener noreferrer"&gt;Contentful&lt;/a&gt;, &lt;a href="https://www.datocms.com/" rel="noopener noreferrer"&gt;DatoCMS&lt;/a&gt; or others.&lt;/p&gt;

&lt;p&gt;The decoupled nature of the Jamstack allow you to chose the right tool for the job and evolve your infrastructure without changing the all stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless architecture
&lt;/h3&gt;

&lt;p&gt;Sometimes you don’t even need a full backend, you just need to run some backend logic and serverless functions are great choice in this particular case.&lt;/p&gt;

&lt;p&gt;You can reduce the complexity of your infrastructure and scale it in response to the traffic of your website without maintain any server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;In the last few years many organizations are creating SaaS products that helps developers to deploy and manage their applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; and &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; are two of them.&lt;/p&gt;

&lt;p&gt;You can link your github repo and configure those services to build and deploy your website every time you commit on a particular branch or you can procedurally trigger a build by calling a webhook, maybe from your headless CMS.&lt;/p&gt;

&lt;p&gt;I’ll cover some of this tools in future posts, make sure to follow my profile to stay updated 🚀🚀🚀&lt;/p&gt;

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

&lt;p&gt;In conclusion, the Jamstack is a modern and efficient web development architecture that offers a number of benefits, including performance, security, and ease of development. If you're looking to build fast, secure, and scalable websites or web applications, the Jamstack is definitely worth considering.&lt;/p&gt;

&lt;p&gt;To learn more about the Jamstack, check out the website &lt;a href="https://jamstack.org/" rel="noopener noreferrer"&gt;https://jamstack.org/&lt;/a&gt;  and don't forget to give it a try for your own projects!&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you found this post helpful, please share it with your colleagues or friends who might also be interested in the Jamstack.&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>api</category>
    </item>
    <item>
      <title>NodeJS + Azure Service Bus + Windows Service</title>
      <dc:creator>pul</dc:creator>
      <pubDate>Thu, 18 Aug 2022 05:21:56 +0000</pubDate>
      <link>https://dev.to/pul/nodejs-azure-service-bus-windows-service-5262</link>
      <guid>https://dev.to/pul/nodejs-azure-service-bus-windows-service-5262</guid>
      <description>&lt;p&gt;In this tutorial we will see how to create a little nodejs service that react to Azure Service Bus Queue events.&lt;/p&gt;

&lt;p&gt;This could be useful in situation when you have an hybrid environment cloud + on premise and you want to orchestrate some kind of job that has to be done on premise.&lt;/p&gt;

&lt;p&gt;This is not the only use case but it’s simple and common enough to be useful as a tutorial.&lt;/p&gt;

&lt;p&gt;We will see how to create a Service Bus resource on Azure, how to configure a queue and how to create a small nodejs windows service that can consume the queue.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;I’ll assume you already have an Azure Subscription and a Resource Group.&lt;/p&gt;

&lt;p&gt;If not you can use the &lt;a href="https://azure.microsoft.com/en-us/pricing/free-services/" rel="noopener noreferrer"&gt;Azure Free Tier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create a new resource in your Resource Group, in this case you have to search for &lt;strong&gt;Service Bus,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjads2j4y1ofql1q0y3o9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjads2j4y1ofql1q0y3o9.png" alt="Service Bus resource creation on the Azure portal" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill the required fields. I’ve choose the West Europe Location just because is closer to me and the Basic pricing tier.&lt;/p&gt;

&lt;p&gt;If you plan to use topics instead of queues or both you have to choose at least the Standard pricing tier since the topic and subscription feature is not supported from the Basic plan.&lt;/p&gt;

&lt;p&gt;In this case you can leave all the other options as default and continue with the resource creation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a queue
&lt;/h2&gt;

&lt;p&gt;Once you have your service bus up and running you can create your first queue.&lt;/p&gt;

&lt;p&gt;It’s very easy you just have to navigate to the &lt;strong&gt;Overview&lt;/strong&gt; page of the newly created Service Bus resource and click on “Create Queue”.&lt;/p&gt;

&lt;p&gt;There are not many options to fill in, I've used the name “test-queue” and left all the defaults.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Consume queue events
&lt;/h1&gt;

&lt;p&gt;Now we can develop a little nodejs script installed as a Windows service that listen for Service Bus queue event end log in the OS Event Log,&lt;/p&gt;

&lt;p&gt;We will use the official nodejs library for interacting with the service bus and the &lt;a href="https://www.npmjs.com/package/node-windows" rel="noopener noreferrer"&gt;node-windows&lt;/a&gt; package to create the Windows service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project setup
&lt;/h2&gt;

&lt;p&gt;Create a new folder “service-bus-daemon” on your filesystem.&lt;/p&gt;

&lt;p&gt;Initialize a node project with the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;azure&lt;/span&gt;&lt;span class="sr"&gt;/service-bus node-windows@1.0.0-beta.&lt;/span&gt;&lt;span class="err"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will install the &lt;strong&gt;1.0.0-beta.6&lt;/strong&gt; version of &lt;strong&gt;node-windows&lt;/strong&gt; because at the time of writing the latest version 1.0.0-beta.7 has a &lt;a href="https://github.com/coreybutler/node-windows/issues/308" rel="noopener noreferrer"&gt;bug that affect the service start&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Service development
&lt;/h2&gt;

&lt;p&gt;Create 3 files in the root folder of your project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;index.js&lt;/strong&gt; is the main file where you can add your business logic&lt;/li&gt;
&lt;li&gt;.&lt;strong&gt;env&lt;/strong&gt; contains all the environment variables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;install.js&lt;/strong&gt; will install the script as a service on your machine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uninstall.js&lt;/strong&gt; will uninstall the previously created service
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file index.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ServiceBusClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@azure/service-bus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EventLogger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-windows&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;EventLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;QUEUE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QUEUE_NAME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CONNECTION_STRING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CONNECTION_STRING&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// log directly in the Windows Event Log&lt;/span&gt;
&lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queueName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;QUEUE_NAME&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ServiceBusClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CONNECTION_STRING&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receiver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createReceiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queueName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myMessageHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageReceived&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Received message: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;messageReceived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// function to handle any errors&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myErrorHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;processMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myMessageHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;processError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myErrorHandler&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;closeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Process terminated SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;closeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGINT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Process terminated SIGINT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;closeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGKILL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Process terminated SIGKILL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;closeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sbClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file install.js&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-windows&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a new service object&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;React to service bus queue messages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Listen for the "install" event, which indicates the&lt;/span&gt;
&lt;span class="c1"&gt;// process is available as a service.&lt;/span&gt;
&lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;install&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// start the process&lt;/span&gt;
  &lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file uninstall.js&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-windows&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a new service object&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Listen for the "uninstall" event so we know when it's done.&lt;/span&gt;
&lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uninstall&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Uninstall complete.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The service exists: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Uninstall the service.&lt;/span&gt;
&lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uninstall&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Install and test the service
&lt;/h1&gt;

&lt;p&gt;In order to install the service you have to run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node install.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;node-windows&lt;/strong&gt; will create an .exe wrapper of your script and it will create the service for you.&lt;/p&gt;

&lt;p&gt;You can test it by creating a message in the queue directly from the Azure Portal using the storing explorer as follow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0er3yd7xt8nqennylfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0er3yd7xt8nqennylfw.png" alt="Path to online service bus explorer 1" width="235" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekneqm9ydhtqpr8wtztu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekneqm9ydhtqpr8wtztu.png" alt="Path to online service bus explorer 2" width="269" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq61bjs30oeei7yw2j96y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq61bjs30oeei7yw2j96y.png" alt="Path to online service bus explorer 3" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to uninstall the service you just have to run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node uninstall.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this tutorial we've created a small script that can be useful as a starting point for creating a windows service with node js and Azure Service Bus.&lt;/p&gt;

</description>
      <category>node</category>
      <category>azure</category>
      <category>tutorial</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
