<?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: LePhuongTrung</title>
    <description>The latest articles on DEV Community by LePhuongTrung (@lephuongtrung).</description>
    <link>https://dev.to/lephuongtrung</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F979479%2Fa927ca65-45dc-4a0a-8907-b67e53afd9f3.jpg</url>
      <title>DEV Community: LePhuongTrung</title>
      <link>https://dev.to/lephuongtrung</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lephuongtrung"/>
    <language>en</language>
    <item>
      <title>What Is MCP (Model Context Protocol) and Why Everyone Is Talking About It</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sat, 04 Jul 2026 12:46:26 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/what-is-mcp-model-context-protocol-and-why-everyone-is-talking-about-it-m70</link>
      <guid>https://dev.to/lephuongtrung/what-is-mcp-model-context-protocol-and-why-everyone-is-talking-about-it-m70</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Artificial Intelligence has advanced rapidly over the past few years, but Large Language Models (LLMs) still have one significant limitation—they cannot naturally interact with your applications, databases, APIs, or local files.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;MCP is emerging as a common standard that allows AI assistants to communicate with external tools in a consistent and secure way.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; is an open protocol designed to standardize communication between AI models and external services.&lt;/p&gt;

&lt;p&gt;Instead of creating a custom integration for every application, developers can expose their services through an MCP server. AI assistants can then discover and use these capabilities through a unified interface.&lt;/p&gt;

&lt;p&gt;Think of MCP as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;USB-C for AI applications&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just as USB-C allows many devices to connect using one standard, MCP enables AI systems to work with many different tools using a common protocol.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Do We Need MCP?
&lt;/h2&gt;

&lt;p&gt;Without MCP, every AI application needs separate integrations for every service it wants to access.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Assistant
 ├── GitHub API
 ├── Slack API
 ├── Notion API
 ├── Google Drive API
 ├── Database API
 └── CRM API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each integration requires its own authentication, implementation, and maintenance.&lt;/p&gt;

&lt;p&gt;With MCP, the architecture becomes much simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Assistant
      │
      ▼
  MCP Client
      │
      ▼
  MCP Server
      │
 ├── Files
 ├── GitHub
 ├── Database
 ├── REST APIs
 ├── Browser
 └── Custom Services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One protocol can expose many different capabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Can MCP Do?
&lt;/h2&gt;

&lt;p&gt;Depending on the server implementation, MCP can allow AI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read local files&lt;/li&gt;
&lt;li&gt;Query databases&lt;/li&gt;
&lt;li&gt;Access documentation&lt;/li&gt;
&lt;li&gt;Execute commands&lt;/li&gt;
&lt;li&gt;Call REST APIs&lt;/li&gt;
&lt;li&gt;Automate browsers&lt;/li&gt;
&lt;li&gt;Search project files&lt;/li&gt;
&lt;li&gt;Manage Git repositories&lt;/li&gt;
&lt;li&gt;Connect to cloud services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes AI assistants much more useful in real-world applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Example
&lt;/h2&gt;

&lt;p&gt;Imagine asking your AI assistant:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Find my latest sales report, summarize it, and email the summary to my manager."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With MCP, the assistant can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search your files.&lt;/li&gt;
&lt;li&gt;Read the report.&lt;/li&gt;
&lt;li&gt;Generate a summary.&lt;/li&gt;
&lt;li&gt;Send the email.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Instead of manually switching between multiple applications, the AI performs the workflow using available MCP tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Is Everyone Talking About MCP?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. It Is Open
&lt;/h3&gt;

&lt;p&gt;MCP is an open protocol that anyone can implement.&lt;/p&gt;

&lt;p&gt;Developers can build custom servers for their own applications and services.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. It Simplifies Integrations
&lt;/h3&gt;

&lt;p&gt;Rather than maintaining dozens of different integrations, developers only need to implement the MCP interface.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. It Enables Smarter AI Agents
&lt;/h3&gt;

&lt;p&gt;Modern AI agents are expected to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browse websites&lt;/li&gt;
&lt;li&gt;Read files&lt;/li&gt;
&lt;li&gt;Execute code&lt;/li&gt;
&lt;li&gt;Search documentation&lt;/li&gt;
&lt;li&gt;Update spreadsheets&lt;/li&gt;
&lt;li&gt;Connect with APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MCP provides a standard way to perform these actions.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Rapid Ecosystem Growth
&lt;/h3&gt;

&lt;p&gt;Many AI tools and open-source projects have started adopting MCP, making it easier for different systems to work together.&lt;/p&gt;

&lt;p&gt;As adoption grows, developers can expect more reusable MCP servers for common services.&lt;/p&gt;




&lt;h2&gt;
  
  
  Typical MCP Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------------+
|    AI Assistant      |
+----------+-----------+
           |
      MCP Client
           |
+----------+-----------+
|      MCP Server      |
+----------+-----------+
           |
  -------------------------
  |     |      |        |
 Files APIs Database Browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Who Should Learn MCP?
&lt;/h2&gt;

&lt;p&gt;MCP is especially valuable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI developers&lt;/li&gt;
&lt;li&gt;Software engineers&lt;/li&gt;
&lt;li&gt;Backend developers&lt;/li&gt;
&lt;li&gt;Browser automation developers&lt;/li&gt;
&lt;li&gt;SaaS founders&lt;/li&gt;
&lt;li&gt;AI agent builders&lt;/li&gt;
&lt;li&gt;DevOps engineers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building AI-powered applications, learning MCP is becoming an increasingly valuable skill.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is MCP Replacing APIs?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Traditional APIs remain the foundation of software communication.&lt;/p&gt;

&lt;p&gt;MCP simply provides a standardized layer that allows AI assistants to discover and use those APIs more efficiently.&lt;/p&gt;

&lt;p&gt;You can think of MCP as a bridge between language models and existing software systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Model Context Protocol is one of the most exciting developments in the AI ecosystem.&lt;/p&gt;

&lt;p&gt;Instead of writing countless custom integrations, developers can expose capabilities through a standard interface that AI models understand.&lt;/p&gt;

&lt;p&gt;As AI agents become more capable, MCP is likely to become a key building block for intelligent automation.&lt;/p&gt;




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

&lt;p&gt;MCP is more than just another AI buzzword.&lt;/p&gt;

&lt;p&gt;It offers a practical way for AI assistants to interact with software, services, and data using a common standard.&lt;/p&gt;

&lt;p&gt;Whether you're building AI applications, automation tools, or developer platforms, understanding MCP today will prepare you for the next generation of AI-powered software.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contact
&lt;/h2&gt;

&lt;p&gt;If you'd like to learn more about my projects or get in touch, visit:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.lephuongtrung.id.vn" rel="noopener noreferrer"&gt;https://www.lephuongtrung.id.vn&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Exposed: How "Testers Community" Schemes Will Get Your Google Play App Rejected</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Mon, 29 Jun 2026 04:29:49 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/exposed-how-testers-community-schemes-will-get-your-google-play-app-rejected-57f4</link>
      <guid>https://dev.to/lephuongtrung/exposed-how-testers-community-schemes-will-get-your-google-play-app-rejected-57f4</guid>
      <description>&lt;h1&gt;
  
  
  Google Rejected My Play Store Production Access After 14 Days of Closed Testing (Here's What I Learned)
&lt;/h1&gt;

&lt;p&gt;If you're an indie Android developer, you've probably run into one of the biggest hurdles in publishing on Google Play:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;12 closed testers for 14 consecutive days.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Like many solo developers, I wanted to get through this requirement as quickly as possible.&lt;/p&gt;

&lt;p&gt;I joined several "tester exchange" communities (including Testers Community and similar platforms), where developers install each other's apps to satisfy the requirement. I completed the process, waited the full 14 days, and confidently applied for Production access.&lt;/p&gt;

&lt;p&gt;Instead, I received this email:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;More testing required to access Google Play production&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Possible reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testers were not engaged with your app during your closed test.&lt;/li&gt;
&lt;li&gt;You didn't follow testing best practices, including gathering feedback and improving your app through updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;That rejection forced me to rethink how closed testing actually works.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Tester Exchange Communities Didn't Work (At Least for Me)
&lt;/h1&gt;

&lt;p&gt;On paper, these communities sound perfect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get 12 testers quickly.&lt;/li&gt;
&lt;li&gt;Everyone helps each other.&lt;/li&gt;
&lt;li&gt;Wait 14 days.&lt;/li&gt;
&lt;li&gt;Publish.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality, my experience was very different.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Very little real engagement
&lt;/h2&gt;

&lt;p&gt;Most people simply installed the app and never opened it again.&lt;/p&gt;

&lt;p&gt;From a developer's perspective, that technically satisfies the install requirementùbut it doesn't look like genuine testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Almost no feedback
&lt;/h2&gt;

&lt;p&gt;My closed testing track had almost no meaningful feedback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No private reviews&lt;/li&gt;
&lt;li&gt;No bug reports&lt;/li&gt;
&lt;li&gt;No discussions&lt;/li&gt;
&lt;li&gt;Very little evidence that anyone actually used the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether Google explicitly checks these signals or not, the result was clear: my application was rejected.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. No testing cycle
&lt;/h2&gt;

&lt;p&gt;Real testing usually looks something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users find issues&lt;/li&gt;
&lt;li&gt;Developer fixes them&lt;/li&gt;
&lt;li&gt;New version is released&lt;/li&gt;
&lt;li&gt;Testers verify the fixes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My testing period didn't resemble that process.&lt;/p&gt;

&lt;p&gt;Looking back, I probably should have shipped at least one or two updates during the 14 days and encouraged testers to provide actual feedback.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I'm Doing Differently
&lt;/h1&gt;

&lt;p&gt;After the rejection, I'm treating the next closed test more like a real beta.&lt;/p&gt;

&lt;p&gt;My plan is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recruit people who are genuinely willing to use the app.&lt;/li&gt;
&lt;li&gt;Ask testers to leave private feedback in Google Play.&lt;/li&gt;
&lt;li&gt;Release updates based on that feedback.&lt;/li&gt;
&lt;li&gt;Keep communicating with testers throughout the 14-day period instead of simply waiting for the countdown to finish.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully that demonstrates an actual testing process rather than just meeting the minimum number of installs.&lt;/p&gt;




&lt;h1&gt;
  
  
  My Biggest Challenge
&lt;/h1&gt;

&lt;p&gt;Finding &lt;strong&gt;12 real, engaged testers&lt;/strong&gt; is much harder than writing the app itself.&lt;/p&gt;

&lt;p&gt;Friends and family usually install the app once and forget about it.&lt;/p&gt;

&lt;p&gt;Tester exchange communities make it easy to get installs, but (in my experience) they don't necessarily provide meaningful testing.&lt;/p&gt;

&lt;p&gt;So I'm curious how other indie developers are handling this in 2026.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where do you find engaged beta testers?&lt;/li&gt;
&lt;li&gt;Have you successfully passed the 12-tester requirement?&lt;/li&gt;
&lt;li&gt;Are there communities that focus on genuine testing rather than simply exchanging installs?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd really appreciate hearing your experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm sure many solo Android developers are running into the same problem.
&lt;/h2&gt;

&lt;p&gt;If you're interested in Android development, indie projects, or just want to connect with a fellow developer, feel free to stop by my website.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://www.lephuongtrung.id.vn/" rel="noopener noreferrer"&gt;Let's connect&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testerscommunity</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>How to Install Hermes Agent on Your VPS with a Single Click</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sat, 30 May 2026 13:35:30 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/how-to-install-hermes-agent-on-your-vps-with-a-single-click-13am</link>
      <guid>https://dev.to/lephuongtrung/how-to-install-hermes-agent-on-your-vps-with-a-single-click-13am</guid>
      <description>&lt;p&gt;If you're looking for the fastest way to deploy &lt;strong&gt;Hermes Agent&lt;/strong&gt; on your VPS without spending hours configuring environments manually, this guide is for you.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how to install and run Hermes Agent using a &lt;strong&gt;single command&lt;/strong&gt; — perfect for developers who want a clean and automated setup experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What is Hermes Agent?
&lt;/h2&gt;

&lt;p&gt;Hermes Agent is a lightweight automation and orchestration agent designed for developers who want to run intelligent workflows, background services, or AI-powered automation directly on their own infrastructure.&lt;/p&gt;

&lt;p&gt;Instead of manually configuring dependencies, services, and runtime environments, Hermes Agent provides a streamlined bootstrap installer that handles everything automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Requirements
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A VPS running Ubuntu 22.04+ (recommended)&lt;/li&gt;
&lt;li&gt;Root or sudo access&lt;/li&gt;
&lt;li&gt;Docker installed (optional depending on your setup)&lt;/li&gt;
&lt;li&gt;A stable internet connection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommended VPS providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;Hetzner&lt;/li&gt;
&lt;li&gt;Vultr&lt;/li&gt;
&lt;li&gt;Oracle Cloud Free Tier&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ One-Click Installation
&lt;/h2&gt;

&lt;p&gt;SSH into your VPS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@your-server-ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://your-install-script-url.sh&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;The installer will automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update system packages&lt;/li&gt;
&lt;li&gt;Install required dependencies&lt;/li&gt;
&lt;li&gt;Configure Hermes Agent&lt;/li&gt;
&lt;li&gt;Start the service&lt;/li&gt;
&lt;li&gt;Enable auto-restart on reboot&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 Verify Installation
&lt;/h2&gt;

&lt;p&gt;After installation, check the service status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status hermes-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see something similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also verify logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; hermes-agent &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠 Common Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Restart Hermes Agent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl restart hermes-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stop Hermes Agent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl stop hermes-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Hermes Agent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://your-update-script-url.sh&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔒 Security Tips
&lt;/h2&gt;

&lt;p&gt;When running any automation agent on a public VPS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use SSH keys instead of passwords&lt;/li&gt;
&lt;li&gt;Disable root login if possible&lt;/li&gt;
&lt;li&gt;Configure a firewall (&lt;code&gt;ufw&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Keep your server updated regularly&lt;/li&gt;
&lt;li&gt;Monitor logs and resource usage&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📈 Why Use VPS Deployment Instead of Localhost?
&lt;/h2&gt;

&lt;p&gt;Running Hermes Agent on a VPS gives you:&lt;/p&gt;

&lt;p&gt;✅ 24/7 uptime&lt;br&gt;
✅ Better scalability&lt;br&gt;
✅ Remote accessibility&lt;br&gt;
✅ Dedicated compute resources&lt;br&gt;
✅ Easier automation workflows&lt;/p&gt;

&lt;p&gt;This setup is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI automation&lt;/li&gt;
&lt;li&gt;Bots&lt;/li&gt;
&lt;li&gt;Data pipelines&lt;/li&gt;
&lt;li&gt;Scheduled jobs&lt;/li&gt;
&lt;li&gt;Background workers&lt;/li&gt;
&lt;li&gt;Multi-service orchestration&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The biggest advantage of Hermes Agent is simplicity.&lt;/p&gt;

&lt;p&gt;You don't need to spend hours configuring infrastructure manually. With a one-click installer, you can go from a fresh VPS to a fully running automation agent in minutes.&lt;/p&gt;

&lt;p&gt;As the ecosystem grows, future releases will include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web dashboard&lt;/li&gt;
&lt;li&gt;Plugin system&lt;/li&gt;
&lt;li&gt;Distributed workers&lt;/li&gt;
&lt;li&gt;AI workflow orchestration&lt;/li&gt;
&lt;li&gt;Cloud-native deployment support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Connect With Me &amp;amp; Follow the Journey
&lt;/h2&gt;

&lt;p&gt;I am actively building this project in public and regularly sharing deep-dives, architectural updates, and my personal fitness transformation. Let's connect!&lt;/p&gt;

&lt;h3&gt;
  
  
  🌐 Discover My Engineering Work
&lt;/h3&gt;

&lt;p&gt;Check out my personal project hub at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://lephuongtrung.id.vn" rel="noopener noreferrer"&gt;https://lephuongtrung.id.vn&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Explore my portfolio and active developer experiments.&lt;/p&gt;




&lt;h3&gt;
  
  
  🎥 Watch the App in Action
&lt;/h3&gt;

&lt;p&gt;Follow my &lt;strong&gt;"Refactor Body"&lt;/strong&gt; series on TikTok:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/lephuongtrung"&gt;@lephuongtrung&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See real-world:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grocery shopping&lt;/li&gt;
&lt;li&gt;Meal prepping&lt;/li&gt;
&lt;li&gt;Lifting routines&lt;/li&gt;
&lt;li&gt;Fitness system design&lt;/li&gt;
&lt;li&gt;Developer lifestyle experiments&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ❤️ Support the Project
&lt;/h2&gt;

&lt;p&gt;If this guide helped you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leave a ❤️ on Dev.to&lt;/li&gt;
&lt;li&gt;Share it with fellow developers&lt;/li&gt;
&lt;li&gt;Star the repository&lt;/li&gt;
&lt;li&gt;Follow the journey&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading 🚀&lt;/p&gt;

</description>
      <category>hermesagentchallenge</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>I Built an "AI Meal Planner." It Almost Produced a Nutritionally Invalid Plan.</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sun, 24 May 2026 09:05:19 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/i-built-an-ai-meal-planner-it-almost-produced-a-nutritionally-invalid-plan-34pm</link>
      <guid>https://dev.to/lephuongtrung/i-built-an-ai-meal-planner-it-almost-produced-a-nutritionally-invalid-plan-34pm</guid>
      <description>&lt;p&gt;Last week, my constraint-optimization engine suggested I live on nothing but protein powder and frozen peas for 7 days to stay under my $27/week budget. It wasn't trying to be funny; it was a &lt;strong&gt;logical failure in my multi-step agentic workflow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m a NestJS engineer. I thought I could solve "budget meal prep" with a clean schema and a prompt. I was wrong. Building this for the Google I/O 2026 challenge wasn't about building a demo; it was about fixing a system that kept breaking in the messiest ways possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The "Failure" Moment: The Gap Between Logic and Reality
&lt;/h2&gt;

&lt;p&gt;My initial MVP was simple: feed the API a budget, get back a JSON list of meals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Failure:&lt;/strong&gt; The model hallucinated prices based on global averages, not my local market. My engine accepted the hallucinated price as "ground truth," resulting in a plan that was technically within budget but &lt;strong&gt;nutritionally invalid&lt;/strong&gt; (missing critical micronutrients).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Insight:&lt;/strong&gt; AI isn't an "optimizer"; it's a "generator." I had to shift my architecture from a Single-Prompt Request to a &lt;strong&gt;Multi-Step Validation Loop&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Quantitative Results: Measuring the Drift
&lt;/h2&gt;

&lt;p&gt;I didn't just "fix" the prompts; I implemented a hard constraint-validation layer. Here is how the system improved after I introduced the &lt;strong&gt;Zod-based Fallback Strategy:&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%2Fgmv2rzaltkzq6zih4d15.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%2Fgmv2rzaltkzq6zih4d15.png" alt="Measuring the Drift" width="799" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Implementation: Failing Safely
&lt;/h2&gt;

&lt;p&gt;I learned that you cannot JSON.parse() your way to a production app. My agentic workflow now treats AI output as "untrusted input."&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="c1"&gt;// The Reality: Handling LLM non-determinism in NestJS&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;optimizeBudget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MealPlan&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;try&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;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gemini&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Schema validation ensures we never crash on malformed AI output&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MealPlanSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;));&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// When AI reasoning drifts, we don't return an invalid plan. &lt;/span&gt;
    &lt;span class="c1"&gt;// We pivot to a deterministic "safe-mode" heuristic.&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AI reasoning drift detected, falling back to deterministic heuristic.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;staticMealService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFallbackPlan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;budget&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;h2&gt;
  
  
  4. What Google I/O 2026 Taught Me
&lt;/h2&gt;

&lt;p&gt;This year’s I/O keynotes shifted my perspective on "Deterministic Agentic Workflows."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serverless is a feature: I moved my reasoning logic to Cloud Run. During Sunday-night traffic spikes, the system auto-scales. I only pay for compute when the agent is actually "thinking."&lt;/li&gt;
&lt;li&gt;Firestore as the Ambient Glue: By using Firestore, my meal plan isn't just a web app state—it’s an ambient data stream that syncs instantly to my mobile device. It’s the "ambient computing" vision I saw on stage, 
applied to my own grocery list.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Conclusion: The Real Goal
&lt;/h2&gt;

&lt;p&gt;The goal was never just to build an AI meal planner. It was to build a system that &lt;strong&gt;fails safely.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As developers, we are moving into an era where AI is no longer a "nice-to-have" feature; it is a core dependency. If we cannot build systems that fail gracefully when the LLM hallucinates, we aren't building software—we're just building technical debt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Live Mess:&lt;/strong&gt; &lt;a href="http://lephuongtrung.id.vn" rel="noopener noreferrer"&gt;lephuongtrung&lt;/a&gt;&lt;/p&gt;

</description>
      <category>googleiochallenge</category>
      <category>googleio</category>
    </item>
    <item>
      <title>How I Built an Intelligent, Budget-Friendly Meal Planner to Refactor My Fitness Journey</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sun, 24 May 2026 04:01:36 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/how-i-built-an-intelligent-budget-friendly-meal-planner-to-refactor-my-fitness-journey-5doe</link>
      <guid>https://dev.to/lephuongtrung/how-i-built-an-intelligent-budget-friendly-meal-planner-to-refactor-my-fitness-journey-5doe</guid>
      <description>&lt;p&gt;Every software engineer knows the concept of refactoring—improving the internal structure of code without changing its external behavior. But a few months ago, I decided to apply this exact mindset to a different kind of system: my own body.&lt;/p&gt;

&lt;p&gt;As a full-stack developer navigating a serious fitness and body recomposition journey, I quickly hit a major bottleneck that wasn't code-related. It was meal prepping. Calculating macro targets (Protein, Carbs, Fats) manually on Excel is tedious. Worse, trying to balance those nutrient goals with a strict weekly budget while avoiding foods I dislike felt like solving an NP-hard problem every single Sunday.&lt;/p&gt;

&lt;p&gt;So, instead of complaining, I did what any developer would do: I built a web application to automate it.&lt;/p&gt;

&lt;p&gt;The Core Product Workflow&lt;br&gt;
I designed the application to be completely streamlined, focusing on constraints that matter to real people: fitness goals, budget restrictions, and personal food preferences.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dynamic Constraint Setting (Goal &amp;amp; Budget)
The workflow starts by letting the user choose their fitness direction—either Cut (caloric deficit for fat loss) or Bulk (caloric surplus for clean muscle gain).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next is the strict budget input. The system is smart enough to calculate a baseline budget based on the user's physical metrics. If you try to input an unrealistic budget, the system warns you. For my current cutting phase, I locked in a budget of 700,000 VND/week (~$27 USD).&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%2Fijglyekziwbkxeilkmj3.jpg" 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%2Fijglyekziwbkxeilkmj3.jpg" alt="Goal and budget setup" width="596" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 1: English localized UI for goal and weekly budget configuration (700,000 VND / ~$27 USD).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preference Filtering (Blacklisting Ingredients)
We all have foods we absolutely refuse to eat. Whether it's pork liver, specific greens, or seafood, the app allows users to toggle off ingredients. The backend algorithm dynamically excludes these food items from the pool before generating the menu.&lt;/li&gt;
&lt;/ol&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%2Fdzxvuxqjc62h2txxytl3.jpg" 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%2Fdzxvuxqjc62h2txxytl3.jpg" alt="Disliked ingredients checklist" width="592" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 2: Ingredient blacklist interface showing localized Vietnamese data layer mapped against an English UI framework.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Smart Weekly Menu Generation
Once you hit "Generate", the application builds a customized weekly meal plan. For instance, looking at my generated Sunday menu, the app successfully hit a highly optimized macro profile: 1350 kcal, 95g Protein, 199g Carbs, and 20g Fats. It broke the meals down into delicious, budget-friendly options like pan-seared tilapia fillets, boiled sweet potatoes, and steamed carrots.&lt;/li&gt;
&lt;/ol&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%2Fr2fu4qujhfq57beliikv.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%2Fr2fu4qujhfq57beliikv.png" alt="Weekly meal plan generator" width="514" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 3: Weekly view and single-day macro breakdown using localized clean-eating ingredients.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Consolidated Automated Shopping List
The biggest time-saver is the automated grocery list aggregation. The app parses the entire week’s menu, calculates the exact weight needed for every ingredient, and presents a checkbox list.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to the app, I needed exactly 1086g of tilapia fillet (costing around 84,972 VND) and 1053g of raw sweet potatoes (76,253 VND) for the week. The final calculated cost for the entire week came out to just 501,707 VND—well under my 700k budget!&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%2Ffru4aubzqndfyovn7a29.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%2Ffru4aubzqndfyovn7a29.png" alt="Automated grocery shopping list" width="528" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 4: Automated grocery list aggregating exact weights. The algorithm successfully optimized the total cost well below the 700k limit.&lt;/p&gt;

&lt;p&gt;The Engineering Behind the Scenes (Tech Stack)&lt;br&gt;
To keep the system highly responsive, type-safe, and capable of scaling into a mobile app later, I leveraged a modern full-stack ecosystem:&lt;/p&gt;

&lt;p&gt;Frontend: React / Next.js with a dark-themed, sleek user interface optimized for scannability.&lt;/p&gt;

&lt;p&gt;Backend: Node.js &amp;amp; NestJS managing the heavy data parsing, modular routing, and ingredient databases.&lt;/p&gt;

&lt;p&gt;Language: TypeScript end-to-end to ensure robust type-safety across data payloads.&lt;/p&gt;

&lt;p&gt;How the Algorithm Thinks&lt;br&gt;
The fundamental challenge was mapping fluid monetary constraints against fixed nutritional values. The database stores individual ingredients with their respective market prices per gram and their nutritional profile (P/C/F per 100g).&lt;/p&gt;

&lt;p&gt;The application core filters out the blacklisted items first, estimates the daily caloric target based on body data, and then executes a matching mechanism to find the cheapest combinations of ingredients that successfully fulfill the required macro distribution.&lt;/p&gt;

&lt;p&gt;🌐 A Smart Approach to Hybrid Localization&lt;br&gt;
If you look closely at the application screenshots, you will notice an interesting architectural choice: The Frontend UI is fully localized in English, while the dynamic dataset (ingredients like "Bắp bò tươi", "Chả lụa") remains in Vietnamese. This is a deliberate Hybrid Localization strategy.&lt;/p&gt;

&lt;p&gt;Frontend Presentation Layer: All static text, user instructions, navigation buttons, and system alerts are handled via localization JSONs, making the application immediately friendly to an international audience or English-speaking expats.&lt;/p&gt;

&lt;p&gt;Dynamic Data Layer: The core database—storing ingredient names, localized nutrition profiles, and historical market pricing—is kept in the regional language. Why? Because these items are tightly coupled with physical inventory at local Vietnamese supermarkets, traditional wet markets, and regional grocery costs.&lt;/p&gt;

&lt;p&gt;By separating the UI translation layer from the localized data layer, the system remains highly accurate for the target market's budget calculation, while the codebase is structurally prepared to scale globally just by swapping the underlying ingredient database.&lt;/p&gt;

&lt;p&gt;What’s Next?&lt;br&gt;
Building this tool in public has drastically optimized my weekly developer routine and body metrics. No more guessing at the grocery store, no more macro calculation errors, and zero wasted budget.&lt;/p&gt;

&lt;p&gt;Moving forward, I am planning to expand this system into a cross-platform mobile application, integrate voice-transcription AI to allow seamless hands-free food logging, implement an LLM-driven cooking instruction assistant, and expand multi-language localization to global ingredient databases.&lt;/p&gt;

&lt;p&gt;🔗 Connect With Me &amp;amp; Follow the Journey&lt;br&gt;
I am actively building this project in public and regularly sharing deep-dives, architectural updates, and my personal fitness transformation. Let's connect!&lt;/p&gt;

&lt;p&gt;Discover my engineering work: Check out my personal project hub at &lt;a href="https://lephuongtrung.id.vn/" rel="noopener noreferrer"&gt;lephuongtrung.id.vn&lt;/a&gt; to see my portfolio and active dev experiments.&lt;/p&gt;

&lt;p&gt;Watch the app in action: Follow my "Refactor Body" series on TikTok &lt;a href="https://www.tiktok.com/@lephuongtrung" rel="noopener noreferrer"&gt;@lephuongtrung&lt;/a&gt; to see real-world grocery shopping, meal prepping, and lifting routines.&lt;/p&gt;

&lt;p&gt;How do you manage your meal preps and fitness goals as a developer? I’d love to hear your thoughts, feature ideas, or tech suggestions in the comments below!&lt;/p&gt;

&lt;p&gt;Feel free to drop a comment, reaction, or follow my blog here on Hashnode if you want to see more content blending Software Engineering and FitTech!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Complete code Send mail on node JS for 60s</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sat, 03 Dec 2022 04:53:02 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/complete-code-send-mail-on-node-js-for-80s-23jc</link>
      <guid>https://dev.to/lephuongtrung/complete-code-send-mail-on-node-js-for-80s-23jc</guid>
      <description>&lt;h2&gt;
  
  
  Install Nodemailer
&lt;/h2&gt;

&lt;p&gt;If you want to learn more about Nodemailer you can read here:&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/nodemailer" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/nodemailer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turn on the Terminal and type the following command to install&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i nodemailer
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Handling Send Mail
&lt;/h2&gt;

&lt;p&gt;The outermost of the project creates the file as follows the following folder&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%2Fvdlv7bainrhzl218w8rv.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%2Fvdlv7bainrhzl218w8rv.png" alt="handle sendMail" width="294" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code handle send mail (sendMail.js)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const nodemailer = require("nodemailer");
const transport = nodemailer.createTransport({
  service: "Gmail",
  auth: {
    user: Email name you use to send,
    pass: Email password you use to send,
  },
});
module.exports.sendConfirmationEmail = (name, email) =&amp;gt; {
  transport
    .sendMail({
      from: user,
      to: email,
      subject: "Confirm your registered account",
      html: `&amp;lt;h1&amp;gt;Email Confirmation&amp;lt;/h1&amp;gt;
        &amp;lt;h2&amp;gt;Hello ${name}&amp;lt;/h2&amp;gt;
        &amp;lt;p&amp;gt;You have successfully registered an account. Please confirm your email by clicking on the following link&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;`,
    })
    .catch((err) =&amp;gt; console.log(err));
};
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Handling Router
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Code handle router (router.js)&lt;/strong&gt;&lt;br&gt;
Add the following code to the router .js&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sendMail = require("../utils/sendMail");
router.post("/sendmail", async (req, res, next) =&amp;gt; {
  try {
    sendMail.sendConfirmationEmail(req.body.name, req.body.email);
    return res.status(200).send("Oke");
  } catch (err) {
    console.log("🚀 ~ file: Routers.js:11 ~ router.post ~ err", err);
    next(err);
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Run test results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Here I use insomnia to test API&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%2Ftef30g7kh5ca29ivnh7h.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%2Ftef30g7kh5ca29ivnh7h.png" alt="insomnia" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check mail&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%2Fzswz3lb3eqmxxlxn4hfi.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%2Fzswz3lb3eqmxxlxn4hfi.png" alt="Check mail" width="799" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We have successfully implemented email notification functionality using Nodemailer. In the next posts, we will explore deeper into system architecture and security. You can follow all my upcoming technical insights and lifestyle updates at &lt;a href="https://www.lephuongtrung.id.vn" rel="noopener noreferrer"&gt;Lê Phương Trung - Middle Fullstack Developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you do not understand something, feel free to message me or join our Zalo community: Join Node.js Backend Group to exchange knowledge about Node.js and Backend development!&lt;/p&gt;

</description>
      <category>backend</category>
      <category>javascript</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Fix CORS policy error on Nodejs with 2 super simple steps</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sat, 03 Dec 2022 03:57:50 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/fix-cors-policy-error-on-nodejs-with-2-super-simple-steps-302i</link>
      <guid>https://dev.to/lephuongtrung/fix-cors-policy-error-on-nodejs-with-2-super-simple-steps-302i</guid>
      <description>&lt;h2&gt;
  
  
  What is CORS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cross-origin resource sharing (CORS)&lt;/strong&gt; is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does CORS policy error show?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access to XMLHttpRequest at 'http://localhost:3333/user/Login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to fix CORS policy error on nodejs?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: Install CORS &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i cors
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Step 2: put CORS in request
Open the app.js file and add the following 3 lines.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var cors = require('cors')
var app = express()
app.use(cors())
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, you can add some more customizations here: &lt;a href="https://www.npmjs.com/package/cors" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/cors&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Fixing CORS is one of the first steps to making your backend production-ready. You can follow my blog updates, fitness journey, and more full-stack web development tips directly at &lt;a href="https://www.lephuongtrung.id.vn" rel="noopener noreferrer"&gt;Lê Phương Trung - Middle Fullstack Developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you do not understand something, you can message me or join this group Zalo: Link, to exchange knowledge about BackEnd NodejsBackEnd Nodejs&lt;/p&gt;

</description>
      <category>security</category>
      <category>career</category>
    </item>
    <item>
      <title>User Security - P1 How to encrypt password in Nodejs?</title>
      <dc:creator>LePhuongTrung</dc:creator>
      <pubDate>Sun, 27 Nov 2022 10:10:01 +0000</pubDate>
      <link>https://dev.to/lephuongtrung/user-security-p1-how-to-encrypt-password-in-nodejs-1j9o</link>
      <guid>https://dev.to/lephuongtrung/user-security-p1-how-to-encrypt-password-in-nodejs-1j9o</guid>
      <description>&lt;p&gt;With any software provider, there is also a responsibility that is to protect user information. Data breaches can cause millions of dollars in damages, and according to Imperva, the US has the highest data breach costs.&lt;/p&gt;

&lt;p&gt;One of the ways to secure user information is to encrypt confidential information. This article will guide you to encrypt passwords with Bcrypt in Node.js. If you want to check out more backend best practices or follow my fullstack coding journey, feel free to visit &lt;strong&gt;&lt;a href="https://www.lephuongtrung.id.vn" rel="noopener noreferrer"&gt;Lê Phương Trung Hub&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 Install the necessary dependencies
&lt;/h2&gt;

&lt;p&gt;in your &lt;strong&gt;Project&lt;/strong&gt;  open &lt;strong&gt;terminal&lt;/strong&gt; and enter command &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;npm install bcrypt&lt;br&gt;
npm install dotenv&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;in the &lt;strong&gt;package.json&lt;/strong&gt; file the &lt;strong&gt;dependencies&lt;/strong&gt; section has &lt;strong&gt;"bcrypt": "^5.1.0"&lt;/strong&gt; and &lt;strong&gt;"dotenv": "^16.0.3",&lt;/strong&gt;, which is ok&lt;br&gt;
Note the version may change depending on the time of installation (currently the latest version)&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2 Define environment variable
&lt;/h2&gt;

&lt;p&gt;in the outermost create file .env&lt;br&gt;
&lt;strong&gt;SALT&lt;/strong&gt;: number of data hashes&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SALT=10&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Step 3 HashPassword
&lt;/h2&gt;

&lt;p&gt;create a new founder named &lt;strong&gt;utils&lt;/strong&gt;, in utils create a new file named &lt;strong&gt;handlePassword&lt;/strong&gt;&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;bcrypt&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;bcrypt&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;hashPassword&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;plainPassword&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;try&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;hashPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plainPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;parseInt&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="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SALT&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;hashPassword&lt;/span&gt; &lt;span class="p"&gt;;&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;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;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="s2"&gt;🚀 ~ file: bcrypt.js ~ line 12 ~ hashPassword ~ error&lt;/span&gt;&lt;span class="dl"&gt;"&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="k"&gt;return&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="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;hashPassword&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;h2&gt;
  
  
  Step 4 Handle Controller
&lt;/h2&gt;

&lt;p&gt;in the outermost create the &lt;strong&gt;Controller&lt;/strong&gt; folder, in the controller create the file &lt;strong&gt;Auth.js&lt;/strong&gt;&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;UserModel&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;../Database/Models/User&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hashPassword&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;../utils/bcrypt&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;signUp&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&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="c1"&gt;//look in database User has email entered yet&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;412&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You have not filled in the required information&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;findAccount&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The email has already been registered&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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;createNewAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;createNewAccount&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Internal server error&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;);&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="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="s2"&gt;🚀 ~ file: Controllers.js ~ line 34 ~ signUp ~ err&lt;/span&gt;&lt;span class="dl"&gt;"&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="nf"&gt;next&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 Handle router
&lt;/h2&gt;

&lt;p&gt;in the outermost create the &lt;strong&gt;Router&lt;/strong&gt; folder, in the Router folder create the file &lt;strong&gt;AuthRouter.js&lt;/strong&gt;&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;var&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&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;AuthController&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;../Controllers/Auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AuthController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the additional App.js file:&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;var&lt;/span&gt; &lt;span class="nx"&gt;authRouter&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;./Router/AuthRouter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//IIFE&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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;await&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectDatabase&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With today's post we have done the password hashing, tomorrow we will continue with 2 articles: login and send verified mail.&lt;br&gt;
If you do not understand something, you can message me or join this group Zalo: &lt;a href="https://zalo.me/g/ogwolo655" rel="noopener noreferrer"&gt;Link&lt;/a&gt;, to exchange knowledge about BackEnd Nodejs&lt;/p&gt;

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