<?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: George Angel</title>
    <description>The latest articles on DEV Community by George Angel (@devtenshi).</description>
    <link>https://dev.to/devtenshi</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%2F1030185%2F90b41158-59eb-4a18-b8c8-2e70239cb59f.jpeg</url>
      <title>DEV Community: George Angel</title>
      <link>https://dev.to/devtenshi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devtenshi"/>
    <language>en</language>
    <item>
      <title>CarbonTrace</title>
      <dc:creator>George Angel</dc:creator>
      <pubDate>Mon, 20 Apr 2026 05:55:40 +0000</pubDate>
      <link>https://dev.to/devtenshi/carbontrace-2hjb</link>
      <guid>https://dev.to/devtenshi/carbontrace-2hjb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-04-16"&gt;Weekend Challenge: Earth Day Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;"my inbox already knows everything I do, so I built an agent to read it"&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;CarbonTrace is an AI-powered web application that automatically tracks a user's personal carbon footprint by scanning their Gmail inbox. Instead of asking users to manually log activities, the app connects to Gmail via OAuth, reads receipts and booking confirmations, and uses Google Gemini to classify each activity and estimate its CO₂ emissions. The result is a personalised carbon dashboard with actionable nudges.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a carbon footprint?
&lt;/h3&gt;

&lt;p&gt;Every action you take that consumes energy or resources releases greenhouse gases into the atmosphere. Driving to work, ordering food, buying a new phone, flying to another city. All of these activities burn fuel or require manufacturing processes that emit gases, primarily carbon dioxide (CO₂) and methane (CH₄).&lt;br&gt;
A carbon footprint is the total sum of all those emissions. That is everything you personally released into the atmosphere over a period of time, measured in kilograms or tonnes of CO₂ equivalent (CO₂e).&lt;br&gt;
The "equivalent" part matters because methane is far more potent than CO₂, so scientists convert all greenhouse gases into a single CO₂ unit for comparison.&lt;/p&gt;
&lt;h3&gt;
  
  
  How it connects to CarbonTrace
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The Metric Concept
The definition says carbon footprints measure the impact of individuals on climate change. That is exactly the problem CarbonTrace solves at the personal level.
For every activity, the energy is usually generated by burning fossil fuels, which releases Carbon Dioxide into the atmosphere. The "KG CO₂" number is an estimation of exactly how heavy those invisible greenhouse gas emissions are for that specific receipt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, a 15-mile Uber ride might produce roughly 5.2 kg CO₂.&lt;br&gt;
A domestic flight from NY to LA might produce 400.5 kg CO₂.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How CarbonTrace App Calculates It (The AI Magic)
Instead of forcing users to navigate complex scientific emission tables, your backend relies entirely on Google Gemini 2.5 Flash. When your API pulls the receipt text from a user's Gmail, it sends it to Gemini with this internal prompt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CarbonTrace simply takes the abstract definition: "total greenhouse gases from human activities", and makes it concrete and personal.&lt;/p&gt;

&lt;p&gt;The average Nigerian emits roughly 0.5 tonnes of CO₂ per year. The global average is 4.7 tonnes. A single Lagos–London flight emits approximately 0.5 tonnes per passenger, wiping out an entire year of average Nigerian emissions in one trip.&lt;br&gt;
Most people have no idea their flight just did that. CarbonTrace makes that invisible number visible. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because you cannot reduce what you cannot measure&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Live App:&lt;br&gt;&lt;br&gt;
How it Works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visit the live URL&lt;/li&gt;
&lt;li&gt;Click "Get started with Google"&lt;/li&gt;
&lt;li&gt;Sign in and grant Gmail read access&lt;/li&gt;
&lt;li&gt;Click "Scan my emails"&lt;/li&gt;
&lt;li&gt;Watch your carbon footprint appear in seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Demo Video: (embed your Loom link here)&lt;br&gt;
In the video I walk through the full user journey — from signing in with Google, through the Auth0 consent screen, to the dashboard populating with real CO₂ data classified by Gemini. The entire flow from login to result takes under 30 seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Github link:&lt;br&gt;
The repository is fully public. Here is a quick map of the most important files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  app/
    page.tsx              → Landing page with login button
    dashboard/
      page.tsx            → Server component, pre-fetches Supabase data
      DashboardClient.tsx → Client component, handles scan button and live results
    api/
      scan/
        route.ts          → Core agent: Gmail fetch, Gemini parse,
Supabase save
  lib/
    auth0.ts              → Auth0 client initialisation
    supabase.ts           → Supabase client initialisation
middleware.ts             → Auth0 v4 middleware, mounts /auth/*routes automatically
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most interesting file is &lt;code&gt;src/app/api/scan/route.ts&lt;/code&gt; — that is where the entire agent loop lives. Everything else is just plumbing to support it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I built CarbonTrace in 48 hours for the Earth Day 2026 hackathon. Here is the technical story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The stack&lt;/strong&gt;&lt;br&gt;
The app is built on Next.js 15 App Router with TypeScript and Tailwind CSS. I used pnpm as the package manager and deployed to Vercel. The entire project: frontend, backend API routes, and middleware, all in a single Next.js repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auth0 for Agent: The hardest part&lt;/strong&gt;&lt;br&gt;
The most technically interesting decision was using Auth0 for Agents to handle the Gmail OAuth consent flow. This is not regular login. it is agentic authentication, where the user grants the app permission to act on their behalf and read their Gmail even when they are not actively present.&lt;br&gt;
Auth0 v4 completely changed the SDK architecture from v3. Routes are no longer manually registered. The middleware mounts &lt;code&gt;/auth/login&lt;/code&gt;, &lt;code&gt;/auth/logout&lt;/code&gt;, and &lt;code&gt;/auth/callback&lt;/code&gt; automatically. The Auth0Client is initialised once in &lt;code&gt;src/lib/auth0.ts&lt;/code&gt; and shared across all server components and API routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth0Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/nextjs-auth0/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth0&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;Auth0Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single line handles the entire session lifecycle, which includes token storage, rotation, and expiry, without any additional configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Gemini: the brain&lt;/strong&gt;&lt;br&gt;
The intelligence layer is a single &lt;code&gt;POST&lt;/code&gt; route at &lt;code&gt;/api/scan&lt;/code&gt;. Instead of asking Gemini to return free-form text and parsing it with regex, I used Gemini's structured output feature with a &lt;code&gt;responseSchema&lt;/code&gt;. This forces Gemini to return exactly the JSON shape I need, every time, with zero parsing failures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getGenerativeModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;generationConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;responseMimeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;responseSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;scanSchema&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;Gemini reads each email and classifies it into one of three categories: Travel, Food, or Shopping. It estimates the CO₂ in kilograms using its knowledge of emissions factors. It also generates a personalised nudge based on the user's biggest emission source. The whole thing runs in under 3 seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supabase: persistence&lt;/strong&gt;&lt;br&gt;
Every activity Gemini detects gets saved as an individual row in a carbon_logs table in Supabase Postgres. Row Level Security is enabled so users can only ever query their own data, even if there is a bug in the API, one user can never see another user's logs.&lt;br&gt;
When you open the dashboard, the server component pre-fetches your existing logs from Supabase and passes them as initialData to the client component. This means the dashboard loads with your historical data immediately, no scan required on every visit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The biggest challenge
&lt;/h2&gt;

&lt;p&gt;Auth0 v4 was a significant hurdle. The SDK is a complete rewrite from v3: the UserProvider, handleAuth, and &lt;code&gt;/api/auth/[auth0]&lt;/code&gt; patterns that every tutorial on the internet uses are all gone. I spent roughly 2 hours debugging import errors before finding the v4 migration guide and understanding that middleware now handles everything automatically. &lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;always check the major version before installing a package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What I would build next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bank transaction scanning via Open Banking APIs for a more complete footprint picture&lt;/li&gt;
&lt;li&gt;Team and company accounts so organisations can track collective emissions&lt;/li&gt;
&lt;li&gt;Integration with verified offset registries like Gold Standard and Verra so users can take direct action from the dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;I am submitting to these categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Best Use of Auth0 for Agents&lt;/li&gt;
&lt;li&gt; Best Use of Google Gemini&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would love to get a feedback, if you happen to actually read to the end of this blog.Thanks for participating!&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
    </item>
    <item>
      <title>HTML Templating in NodeJs</title>
      <dc:creator>George Angel</dc:creator>
      <pubDate>Tue, 28 Feb 2023 14:19:43 +0000</pubDate>
      <link>https://dev.to/devtenshi/html-templating-in-nodejs-298g</link>
      <guid>https://dev.to/devtenshi/html-templating-in-nodejs-298g</guid>
      <description>&lt;p&gt;HTML templating is a technique that allows us to create a base HTML structure and use placeholders to dynamically generate content based on data retrieved from our JSON file or database.&lt;/p&gt;

&lt;p&gt;Let's consider a hypothetical instance where our website consists of numerous product cards, each containing specific product details that are retrieved from the JSON file.&lt;/p&gt;

&lt;p&gt;Now, if we were to add or remove any products from our JSON file, how would we update the corresponding cards on the front-end dynamically?&lt;/p&gt;

&lt;p&gt;Considering our content-based data is stored in a JSON file, we can proceed with creating reusable templates from our existing HTML code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Building the templates&lt;/strong&gt;&lt;br&gt;
As a developer, you're probably familiar with the concept of serving dynamic web content. One way to achieve this is by using templates.&lt;/p&gt;

&lt;p&gt;We would create two HTML templates, one for the product overview page and one for the individual product cards.&lt;/p&gt;

&lt;p&gt;The first template &lt;code&gt;template-card.html&lt;/code&gt; is used as a blueprint for the individual product cards, and the second &lt;code&gt;template-overview.html&lt;/code&gt; is used as a blueprint for the overview page. These templates contain placeholders that will be replaced with actual content when the page is requested by a user.&lt;/p&gt;

&lt;p&gt;Ensure that your placeholder does not contain any symbols that are part of the HTML code. A commonly used syntax for placeholders is&lt;code&gt;{%PLACEHOLDER_NAME%}.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here is &lt;code&gt;template-card.html&lt;/code&gt; our first template used as a blueprint to create as many cards as needed dynamically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;figure class="card"&amp;gt;
    &amp;lt;div class="card__emoji"&amp;gt;{%IMAGE%}{%IMAGE%}&amp;lt;/div&amp;gt;
    &amp;lt;div class="card__title-box"&amp;gt;
      &amp;lt;h2 class="card__title"&amp;gt;{%PRODUCTNAME%}&amp;lt;/h2&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class="card__details"&amp;gt;
      &amp;lt;div class="card__detail-box"&amp;gt;
          &amp;lt;h6 class="card__detail card__detail 
               {%NOT_ORGANIC%}"&amp;gt; Organic!&amp;lt;/h6&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div class="card__detail-box"&amp;gt;
        &amp;lt;h6 class="card__detail"&amp;gt;{%QUANTITY%} per 📦&amp;lt;/h6&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div class="card__detail-box"&amp;gt;
        &amp;lt;h6 class="card__detail card__detail--price"&amp;gt; 
            {%PRICE%}€&amp;lt;/h6&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;a class="card__link" href="/product?id={%ID%}"&amp;gt;
      &amp;lt;span&amp;gt;Detail &amp;lt;i class="emoji-right"&amp;gt;👉&amp;lt;/i&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/a&amp;gt;
  &amp;lt;/figure&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As this card will serve as a template, the information contained within it should be replaced with placeholders as well. Once the placeholders have been added, the card will resemble the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;figure class="card"&amp;gt;
    &amp;lt;div class="card__emoji"&amp;gt;🥦🥦&amp;lt;/div&amp;gt;
    &amp;lt;div class="card__title-box"&amp;gt;
      &amp;lt;h2 class="card__title"&amp;gt;Apollo Broccoli&amp;lt;/h2&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class="card__details"&amp;gt;
      &amp;lt;div class="card__detail-box"&amp;gt;
          &amp;lt;h6 class="card__detail card__detail--organic"&amp;gt;Organic!&amp;lt;/h6&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div class="card__detail-box"&amp;gt;
        &amp;lt;h6 class="card__detail"&amp;gt;3🥦 per 📦&amp;lt;/h6&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div class="card__detail-box"&amp;gt;
        &amp;lt;h6 class="card__detail card__detail- 
              price"&amp;gt;5.50€&amp;lt;/h6&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;a class="card__link" href="/product?id="&amp;gt;
      &amp;lt;span&amp;gt;Detail &amp;lt;i class="emoji-right"&amp;gt;👉&amp;lt;/i&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/a&amp;gt;
  &amp;lt;/figure&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The anchor tag contains an href link that includes a placeholder for an ID. This indicates that each card or product in our JSON file has a distinct ID. These IDs are unique and will be utilized in identifying each product during routing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also, when we need to style elements based on their category, CSS classes and IDs can be substituted with placeholders as is done in the image examples. This approach can prove especially useful in such cases.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
    &amp;lt;div class="container"&amp;gt;
      &amp;lt;h1&amp;gt;🌽 Node Farm 🥦&amp;lt;/h1&amp;gt;

      &amp;lt;div class="cards-container"&amp;gt;
        {%PRODUCT_CARDS%}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have substituted our template card with a placeholder. It's important to keep in mind that we will generate multiple cards dynamically using this single template card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is our second template card, &lt;code&gt;template-overview.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Filling the templates&lt;/strong&gt;&lt;br&gt;
Here comes the fun part, filling our templates by replacing our placeholders with actual content.&lt;/p&gt;

&lt;p&gt;When a user requests a URL, the code reads the relevant template file (either &lt;code&gt;template-overview.html&lt;/code&gt; or &lt;code&gt;template-card.html&lt;/code&gt;) synchronously, fills it dynamically with content from a JSON file, and sends back the relevant content as a response to the user.&lt;/p&gt;

&lt;p&gt;This is achieved through the use of the &lt;code&gt;replaceTemplate&lt;/code&gt; function, which replaces the placeholders in the template with actual content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SECOND STEP:
const replaceTemplate = (temp, product) =&amp;gt; {
    let output = temp.replace(/{%PRODUCTNAME%}/g, product.productName);
    output = output.replace(/{%IMAGE%}/g, product.image);
    output = output.replace(/{%PRICE%}/g, product.price);
    output = output.replace(/{%ID%}/g, product.id); 
     // /g is a regex global flag
    return output;
}

// FIRST STEP:
const tempOverview = fs.readFileSync(`${__dirname}/templates/template-overview.html`, 'utf-8');
const tempCard = fs.readFileSync(`${__dirname}/templates/template-card.html`, 'utf-8');
const data = fs.readFileSync(`${__dirname}/dev-data/data.json`, 'utf-8');
const dataObj = JSON.parse(data);

// THIRD STEP:
const server = http.createServer((req, res) =&amp;gt; {
    const pathName = req.url;

    //FOURTH STEP:
    //Here is the Overview
    if(pathName === '/' || pathName === '/overview') {
        res.writeHead(200, {'Content-type': 'text/html'});
        const cardsHtml = dataObj.map(el =&amp;gt; replaceTemplate(tempCard, el)).join('');
        const output = tempOverview.replace('{%PRODUCT_CARDS%', cardsHtml);

        res.end(output);

        //API
    } else if(pathName === '/api') {
        res.writeHead(200, {'Content-type': 'application/json'});
        res.end(data);
    // Not Found
    } else {
            res.writeHead(404, {
            'Content-type': 'text/html', //standard header
            'my-header': 'hello-world'
        });
        res.end('&amp;lt;h1&amp;gt;This page cannot be found.&amp;lt;/h1&amp;gt;');
    }
});

server.listen(8000, '127.0.0.1', () =&amp;gt; {
    console.log('Listening to requests on port 8000');
});
    res.writeHead(404, {
            'Content-type': 'text/html', //standard header
            'my-header': 'hello-world'
        });
        res.end('&amp;lt;h1&amp;gt;This page cannot be found.&amp;lt;/h1&amp;gt;');
    }
});

server.listen(8000, '127.0.0.1', () =&amp;gt; {
    console.log('Listening to requests on port 8000');
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.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%2Fdyuw7dhpbwekkks3rv84.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fdyuw7dhpbwekkks3rv84.gif" alt="suprised gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't worry, we will take a closer look at the big block of code up there and figure out what it does in simpler terms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, read the two HTML template files and the product data that is stored in a JSON file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, define a function that replaces placeholders in the templates with product-specific data. Here, our function is named &lt;code&gt;replaceTemplate&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Third, listen to incoming HTTP requests and check the pathname of the request URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fourth, If the pathname is &lt;code&gt;/&lt;/code&gt;or &lt;code&gt;/overview&lt;/code&gt;, generate HTML code for each product card by replacing placeholders in the &lt;code&gt;tempCard&lt;/code&gt; template using the &lt;code&gt;replaceTemplate&lt;/code&gt;function and the product data from the JSON file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The resulting HTML for each card is then concatenated to create the &lt;code&gt;cardsHtml&lt;/code&gt;string. The &lt;code&gt;tempOverview&lt;/code&gt; template is then modified to include the cardsHtml string and the resulting HTML code is sent back as the response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, if the pathname is &lt;code&gt;/api&lt;/code&gt; it sends back the product data in JSON format as the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, if the pathname is anything else, sends back a 404 error message.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fh8ml6b4hb0foqv7m7938.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fh8ml6b4hb0foqv7m7938.gif" alt="Relieved gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow, that code did look like a lot, but if we look closely and take it one step at a time, it's not that complicated. &lt;/p&gt;

&lt;p&gt;All it's doing is replacing some special words with real information and sending it back to the website so people can see it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of HTML templating&lt;/strong&gt;&lt;br&gt;
HTML templating offers several benefits that make it a popular choice among web developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;By utilizing HTML templating, we separate content from the presentation allowing developers to generate reusable templates that can handle varying amounts of data from multiple sources, and maintain multiple copies of similar code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTML templates provide a standard structure for presenting data, improving user experience and easy navigation on the site.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The flexibility of templating makes it easier to modify the underlying data. This saves time and effort, as developers don't need to change the HTML code manually.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since HTML templates are reusable, they are easier to maintain and update. Changes to the underlying data can be made without modifying the template code, which reduces the likelihood of errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTML templating can handle large amounts of data without compromising performance. This makes it an ideal choice for websites with a significant amount of dynamic content.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, HTML templating is an efficient, consistent, flexible, and scalable technique that simplifies the development and maintenance of dynamic web content.&lt;/p&gt;

&lt;p&gt;By separating content from presentation, HTML templating enables developers to create reusable templates that can handle varying amounts of data, without having to hard-code the content into each page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus Section:&lt;/strong&gt;&lt;br&gt;
There are several other templating engines available in Node.js, such as EJS, Pug (formerly known as Jade), Handlebars, and Mustache, among others.&lt;/p&gt;

&lt;p&gt;To use a templating engine in Node.js, you'll need to install it via npm and then require it in your code. These engines provide a way to generate HTML by inserting data into placeholders within the template.&lt;/p&gt;

&lt;p&gt;You've reached the end of the article! 🎉 Hope you enjoyed this post and learned something new 💡.&lt;br&gt;
Thanks for sticking around.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>tutorial</category>
      <category>html</category>
    </item>
  </channel>
</rss>
