<?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>Forem: Ben Borla</title>
    <description>The latest articles on Forem by Ben Borla (@benborla).</description>
    <link>https://forem.com/benborla</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%2F190323%2Fc579ce31-5851-4d8a-9670-bd65c290adfc.jpeg</url>
      <title>Forem: Ben Borla</title>
      <link>https://forem.com/benborla</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/benborla"/>
    <language>en</language>
    <item>
      <title>MCP Server for MySQL</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Mon, 31 Mar 2025 09:21:31 +0000</pubDate>
      <link>https://forem.com/benborla/mcp-server-for-mysql-3jf1</link>
      <guid>https://forem.com/benborla/mcp-server-for-mysql-3jf1</guid>
      <description>&lt;p&gt;In today's data-driven world, the ability to interact with databases through natural language has become increasingly valuable. Enter &lt;strong&gt;MCP Server for MySQL&lt;/strong&gt; - a powerful tool that bridges the gap between Large Language Models (LLMs) like Claude and your MySQL databases.&lt;/p&gt;

&lt;p&gt;This innovative tool enables LLMs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inspect database schemas&lt;/li&gt;
&lt;li&gt;Execute SQL queries directly&lt;/li&gt;
&lt;li&gt;Analyze data without manual copying&lt;/li&gt;
&lt;li&gt;Perform database operations through natural language commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're a developer looking to streamline your database interactions, a data analyst seeking more intuitive ways to query data, or a database administrator wanting to leverage AI for database management, &lt;strong&gt;&lt;a href="https://github.com/benborla/mcp-server-mysql" rel="noopener noreferrer"&gt;MCP Server for MySQL&lt;/a&gt;&lt;/strong&gt; offers a seamless solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is MCP?
&lt;/h3&gt;

&lt;p&gt;MCP (Model Context Protocol) is a framework that extends the capabilities of LLMs, allowing them to interact with external tools and systems. In this case, MCP Server for MySQL acts as a connector between LLMs and MySQL databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQL Query Execution&lt;/strong&gt;: Send SQL queries directly to your MySQL database from your conversations with Claude&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Inspection&lt;/strong&gt;: Allow Claude to understand your database structure without manual explanations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Analysis&lt;/strong&gt;: Have Claude analyze your database data and return insights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Features&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;SQL injection prevention through prepared statements&lt;/li&gt;
&lt;li&gt;Configurable write permissions (INSERT, UPDATE, DELETE)&lt;/li&gt;
&lt;li&gt;Query whitelisting and rate limiting capabilities&lt;/li&gt;
&lt;li&gt;Configurable connection encryption&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Optimized connection pooling&lt;/li&gt;
&lt;li&gt;Query result caching&lt;/li&gt;
&lt;li&gt;Large result set streaming&lt;/li&gt;
&lt;li&gt;Query execution plan analysis&lt;/li&gt;
&lt;li&gt;Configurable query timeouts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database Exploration&lt;/strong&gt;: Ask Claude to explain complex database structures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query Generation&lt;/strong&gt;: Request specific data without writing SQL yourself&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Analysis&lt;/strong&gt;: Have Claude analyze patterns or insights from your database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Maintenance&lt;/strong&gt;: When configured, allow Claude to help update or clean your data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Getting started with MCP Server for MySQL is straightforward, with multiple installation methods available depending on your environment and preferences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Node.js v18 or higher&lt;/li&gt;
&lt;li&gt;MySQL 5.7 or higher (MySQL 8.0+ recommended)&lt;/li&gt;
&lt;li&gt;MySQL user with appropriate permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installation Options
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Using Claude Desktop
&lt;/h4&gt;

&lt;p&gt;For Claude Desktop App, add the following to your &lt;code&gt;claude_desktop_config.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mcp_server_mysql"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"@benborla29/mcp-server-mysql"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MYSQL_HOST"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MYSQL_PORT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3306"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MYSQL_USER"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MYSQL_PASS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MYSQL_DB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_database"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ALLOW_INSERT_OPERATION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ALLOW_UPDATE_OPERATION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ALLOW_DELETE_OPERATION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/node/bin:/usr/bin:/bin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"NODE_PATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/node/lib/node_modules"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  For Cursor IDE (Version: 0.47+)
&lt;/h4&gt;

&lt;p&gt;Add this to your &lt;code&gt;mcp.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"MySQL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcprunner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"MYSQL_HOST=127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"MYSQL_PORT=3306"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"MYSQL_USER=root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"MYSQL_PASS=root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"MYSQL_DB=demostore"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ALLOW_INSERT_OPERATION=true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ALLOW_UPDATE_OPERATION=true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ALLOW_DELETE_OPERATION=false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"@benborla29/mcp-server-mysql"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a lower version you may use this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx mcprunner MYSQL_HOST=127.0.0.1 MYSQL_PORT=3306 MYSQL_USER=root MYSQL_PASS=root MYSQL_DB=demostore ALLOW_INSERT_OPERATION=true ALLOW_UPDATE_OPERATION=true ALLOW_DELETE_OPERATION=false -- npx -y @benborla29/mcp-server-mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to replace the values in the &lt;code&gt;env&lt;/code&gt; strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  How You Can Help
&lt;/h2&gt;

&lt;p&gt;MCP Server for MySQL is an open-source project that welcomes community contributions! If you're interested in helping improve this tool, here are some ways to get involved:&lt;/p&gt;

&lt;h3&gt;
  
  
  Contributing to the Project
&lt;/h3&gt;

&lt;p&gt;Visit the GitHub repository at &lt;a href="https://github.com/benborla/mcp-server-mysql/" rel="noopener noreferrer"&gt;https://github.com/benborla/mcp-server-mysql/&lt;/a&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Report bugs or issues you encounter&lt;/li&gt;
&lt;li&gt;Suggest new features or improvements&lt;/li&gt;
&lt;li&gt;Submit pull requests for bug fixes or new functionality&lt;/li&gt;
&lt;li&gt;Help improve documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Development Setup
&lt;/h3&gt;

&lt;p&gt;If you want to contribute code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork the repository&lt;/li&gt;
&lt;li&gt;Clone your fork: &lt;code&gt;git clone https://github.com/your-username/mcp-server-mysql.git&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install dependencies: &lt;code&gt;npm install&lt;/code&gt; or &lt;code&gt;pnpm install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Build the project: &lt;code&gt;npm run build&lt;/code&gt; or &lt;code&gt;pnpm run build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run tests: &lt;code&gt;npm test&lt;/code&gt; or &lt;code&gt;pnpm test&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Project Roadmap
&lt;/h3&gt;

&lt;p&gt;The team is actively working on enhancing this MCP server with features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhanced query capabilities with prepared statements&lt;/li&gt;
&lt;li&gt;Advanced security features&lt;/li&gt;
&lt;li&gt;Performance optimizations&lt;/li&gt;
&lt;li&gt;Comprehensive monitoring&lt;/li&gt;
&lt;li&gt;Expanded schema information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your contributions to any of these areas would be greatly appreciated!&lt;/p&gt;




&lt;p&gt;By connecting LLMs like Claude directly to your MySQL databases, MCP Server for MySQL opens up new possibilities for database interaction and management. Whether you're using it for personal projects, development workflows, or enterprise applications, this tool provides a powerful bridge between natural language AI and your structured data.&lt;/p&gt;

&lt;p&gt;Give it a try today, and join the community to help shape the future of AI-powered database interactions!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>node</category>
      <category>cursor</category>
    </item>
    <item>
      <title>MCP Server for MySQL</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Mon, 09 Dec 2024 19:04:38 +0000</pubDate>
      <link>https://forem.com/benborla/mcp-server-for-mysql-4d7</link>
      <guid>https://forem.com/benborla/mcp-server-for-mysql-4d7</guid>
      <description>&lt;p&gt;Hi! I'd like to share the tool that I just worked. If you are using Anthropic's Claude AI and MySQL, this might be helpful to you.&lt;/p&gt;

&lt;p&gt;You may visit this Github link:&lt;br&gt;
&lt;a href="https://github.com/benborla/mcp-server-mysql" rel="noopener noreferrer"&gt;https://github.com/benborla/mcp-server-mysql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know what you think of it. Thanks!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>node</category>
      <category>claudeai</category>
      <category>mcpserver</category>
    </item>
    <item>
      <title>Hi, I'd like to share an MCP Server tool I have been working. If you use Claude API and MySQL on your development, this might be helpful. Please visit this Github link. https://github.com/benborla/mcp-server-mysql Let me know what you think of it. Tnx!</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Mon, 09 Dec 2024 19:00:26 +0000</pubDate>
      <link>https://forem.com/benborla/hi-id-like-to-share-an-mcp-server-tool-i-have-been-working-if-you-use-claude-api-and-mysql-on-2k4p</link>
      <guid>https://forem.com/benborla/hi-id-like-to-share-an-mcp-server-tool-i-have-been-working-if-you-use-claude-api-and-mysql-on-2k4p</guid>
      <description></description>
      <category>github</category>
      <category>mysql</category>
      <category>api</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🔥🔥🔥 I Turned My Terminal into a Time Machine</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Fri, 18 Oct 2024 03:20:24 +0000</pubDate>
      <link>https://forem.com/benborla/i-turned-my-terminal-into-a-time-machine-3dl5</link>
      <guid>https://forem.com/benborla/i-turned-my-terminal-into-a-time-machine-3dl5</guid>
      <description>&lt;p&gt;Hey there! Remember those days when journaling meant scribbling "Dear Diary" in a notebook hidden under your mattress? Well, dust off your keyboards because we're about to take a leap into the simplicity of journaling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Journaling Journey: More Than Just Teen Angst
&lt;/h2&gt;

&lt;p&gt;Let's face it, we've all had those moments when life feels like a washing machine on spin cycle. You know, when your to-do list is longer than a CVS receipt, and your brain feels like a browser with 100 tabs open. That's where journaling comes in, like a superhero swooping down to save your sanity.&lt;/p&gt;

&lt;p&gt;But here's the kicker – journaling isn't just about venting your frustrations or documenting your crush on that cute barista (though that's totally valid). It's a powerful tool for mindfulness, organization, and habit-sticking. It's like having a personal trainer for your brain, minus the intimidating muscles and protein shake obsession.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the Journal Bash Script: Your New BFF (Best Function for Fulfillment)
&lt;/h2&gt;

&lt;p&gt;Now, I know what you're thinking. "Bash script? Isn't that something only hackers in hoodies use?" Well, prepare to have your mind blown like a dandelion in a hurricane.&lt;/p&gt;

&lt;p&gt;Imagine having a journaling tool that's as easy to use as typing a single word into your terminal. No need to fumble with apps, remember passwords, or navigate through clunky interfaces. Just you, your thoughts, and the comforting glow of your command line.&lt;/p&gt;

&lt;p&gt;Our journal bash script is like the Swiss Army knife of journaling tools. It's got more features than a Hollywood celebrity has Instagram followers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Daily Entries&lt;/strong&gt;: Because consistency is key, like remembering to water your plants (RIP, Steve the Succulent).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Location&lt;/strong&gt;: Store your journals wherever you want. Under your digital bed, perhaps?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configurable Editor&lt;/strong&gt;: Use your favorite text editor. Vim, Emacs, or even Notepad if you're feeling nostalgic (but seriously, why would you do that to yourself?).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time Travel&lt;/strong&gt;: Okay, not really. But you can create entries for past or future dates. Perfect for when you forget to journal or want to leave a message for your future self ("Dear Future Me, I hope you finally learned how to fold fitted sheets").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List All Entries&lt;/strong&gt;: Because sometimes you need to remind yourself of how far you've come (or how many days in a row you complained about your neighbor's yodeling practice).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Tool Will Change Your Life (No Exaggeration... Okay, Maybe a Little)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mindfulness&lt;/strong&gt;: It's like meditation, but you get to use words instead of sitting in silence wondering if you left the stove on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization&lt;/strong&gt;: Keep your thoughts as tidy as Marie Kondo's sock drawer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Habit Formation&lt;/strong&gt;: Because the only thing standing between you and your goals is consistency (and maybe that last slice of pizza).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: It's always there, just a terminal away. No excuses!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt;: Your thoughts stay local. No cloud storage, no data breaches, no awkward explanations about why you wrote a sonnet to your cat.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Get Started (It's Easier Than Assembling IKEA Furniture)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the project's GitHub repository: &lt;a href="https://github.com/benborla/journal-cli" rel="noopener noreferrer"&gt;https://github.com/benborla/journal-cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Clone the repo or download the script (don't worry, it won't bite).&lt;/li&gt;
&lt;li&gt;Make it executable (chmod +x, for the cool kids).&lt;/li&gt;
&lt;li&gt;Move it somewhere in your PATH (so you can summon it like a genie, but without the limited wishes).&lt;/li&gt;
&lt;li&gt;Start journaling! Type &lt;code&gt;journal&lt;/code&gt; and watch the magic happen.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Look, I'm not saying this journal bash script will solve all your problems. It won't do your laundry or explain why pineapple on pizza is controversial. But it will give you a simple, powerful tool to reflect, organize your thoughts, and build better habits.&lt;/p&gt;

&lt;p&gt;Remember, in the grand debugging of life, self-reflection is the best breakpoint.&lt;/p&gt;

&lt;p&gt;P.S. If all else fails, you can always use the script to document your attempts at becoming a professional bubble tea taster. Hey, everyone needs a dream!&lt;/p&gt;

&lt;p&gt;P.P.S. Don't forget to star the GitHub repo. It's like giving a digital high-five to the developers, and who doesn't love high-fives?&lt;/p&gt;

&lt;p&gt;Let me know in the comments if you have tried it and what you think about it. &lt;/p&gt;

&lt;p&gt;Have a great day everyone!&lt;/p&gt;

</description>
      <category>bash</category>
      <category>devjournal</category>
      <category>development</category>
      <category>programming</category>
    </item>
    <item>
      <title>Moon Phases | CSS Art: Space</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Tue, 10 Sep 2024 08:52:32 +0000</pubDate>
      <link>https://forem.com/benborla/moon-phases-css-art-space-lc7</link>
      <guid>https://forem.com/benborla/moon-phases-css-art-space-lc7</guid>
      <description>&lt;h1&gt;
  
  
  CSS Art: Interactive Space Scene
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2024-09-04"&gt;Frontend Challenge v24.09.04&lt;/a&gt;, CSS Art: Space.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;For this challenge, I wanted to capture the dynamic and interactive nature of our night sky. The ever-changing phases of the moon, the twinkling stars, and the occasional thrill of a shooting star have always fascinated humanity. By creating an animated and interactive representation of these celestial phenomena, I aimed to bring a small piece of the universe to our screens, reminding us of the constant motion and beauty in space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Link: &lt;a href="https://moon-phase.fly.dev/" rel="noopener noreferrer"&gt;https://moon-phase.fly.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a live demo of the interactive space scene. The centerpiece is the moon with its ever-changing phases, represented by an animation that cycles through different stages. Surrounding the moon, you'll see a sky full of twinkling stars, each blinking at its own rhythm. For an extra interactive element, try hovering your mouse over the stars - you'll trigger a comet animation, simulating a shooting star effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;This project has been an exhilarating journey into the world of CSS animations and interactive web design. When I first approached the challenge, I was both excited and slightly overwhelmed by the idea of creating a dynamic space scene purely with HTML and CSS. However, as I delved deeper into the project, I discovered the incredible power and flexibility of these technologies.&lt;/p&gt;

&lt;p&gt;One of the most significant learnings was mastering CSS animations. Creating the moon phase effect was particularly challenging and rewarding. I learned how to use keyframe animations to smoothly transition the moon through its different phases, which opened up a whole new world of possibilities for future projects.&lt;/p&gt;

&lt;p&gt;The twinkling star effect taught me a lot about using random values in CSS animations. By applying different animation delays to each star, I was able to create a more natural, organic feel to the night sky. This technique of introducing controlled randomness is something I'm excited to explore further in future designs.&lt;/p&gt;

&lt;p&gt;I'm particularly proud of the interactive comet effect. Implementing this feature pushed me to combine CSS animations with pseudo-elements and hover states. It was a breakthrough moment when I finally got the comet to streak across the sky upon hovering over a star. This intersection of animation and user interaction has sparked many ideas for future interactive web elements.&lt;/p&gt;

&lt;p&gt;The process of refining the colors and timing of animations was also enlightening. I spent considerable time tweaking the shades of blue for the space background and adjusting the animation speeds to find the perfect balance between an active scene and a calming night sky. This exercise greatly improved my understanding of color theory and the impact of timing in animations.&lt;/p&gt;

&lt;p&gt;Moving forward, I'm excited to explore more complex CSS animations and interactions. I'd love to add features like parallax scrolling for different layers of stars or even incorporate subtle audio effects to complement the visual experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;MIT License&lt;/p&gt;

&lt;p&gt;Copyright (c) 2024 Ben Borla&lt;/p&gt;

&lt;p&gt;Permission is hereby granted, free of charge, to any person obtaining a copy&lt;br&gt;
of this software and associated documentation files (the "Software"), to deal&lt;br&gt;
in the Software without restriction, including without limitation the rights&lt;br&gt;
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&lt;br&gt;
copies of the Software, and to permit persons to whom the Software is&lt;br&gt;
furnished to do so, subject to the following conditions:&lt;/p&gt;

&lt;p&gt;The above copyright notice and this permission notice shall be included in all&lt;br&gt;
copies or substantial portions of the Software.&lt;/p&gt;

&lt;p&gt;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&lt;br&gt;
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&lt;br&gt;
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&lt;br&gt;
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&lt;br&gt;
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&lt;br&gt;
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE&lt;br&gt;
SOFTWARE.&lt;/p&gt;

&lt;p&gt;This challenge has not only improved my technical skills but also reminded me of the joy of creating immersive, interactive experiences on the web. It's empowering to know that with CSS and a bit of creativity, we can bring a piece of the universe to life on a webpage. I'm grateful for this experience and the renewed appreciation it's given me for both the wonders of space and the limitless possibilities of web design.&lt;/p&gt;

&lt;p&gt;This journey has taught me that the frontier of web development, much like space itself, is boundless. I'm excited to continue exploring and pushing the limits of what's possible with CSS and HTML.&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>Clean Architecture Demystified: A Practical Guide for Software Developers</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Mon, 02 Sep 2024 04:00:15 +0000</pubDate>
      <link>https://forem.com/benborla/clean-architecture-demystified-a-practical-guide-for-software-developers-4nna</link>
      <guid>https://forem.com/benborla/clean-architecture-demystified-a-practical-guide-for-software-developers-4nna</guid>
      <description>&lt;p&gt;As developers, we've all encountered codebases that feel like navigating a maze blindfolded. Clean Architecture, proposed by &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Robert C. Martin (Uncle Bob)&lt;/a&gt;, offers a way out of this chaos. Let's break it down in practical terms using NextJS, TypeScript, DrizzleORM, and PostgreSQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Code Structure Matters
&lt;/h2&gt;

&lt;p&gt;Imagine you're working on an e-commerce app built with NextJS. Here's how it might look with poor structure vs. Clean Architecture:&lt;/p&gt;

&lt;p&gt;Poor Structure:&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;// pages/api/products/[id].ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&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;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drizzle&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;drizzle-orm/node-postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;eq&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;drizzle-orm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&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;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;products&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;@/schema&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;pool&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;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;connectionString&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;DATABASE_URL&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&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;NextApiRequest&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;NextApiResponse&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&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;query&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;product&lt;/span&gt;&lt;span class="p"&gt;]&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;product&lt;/span&gt;&lt;span class="p"&gt;)&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="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;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product not found&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, changing from PostgreSQL to another database would require rewriting every API route that interacts with the database.&lt;/p&gt;

&lt;p&gt;Clean Architecture:&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;// entities/Product.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// use-cases/GetProduct.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetProduct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="c1"&gt;// infrastructure/DrizzleProductRepository.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drizzle&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;drizzle-orm/node-postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;eq&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;drizzle-orm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&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;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;products&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;@/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&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;@/use-cases/GetProduct&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;class&lt;/span&gt; &lt;span class="nc"&gt;DrizzleProductRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&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;pool&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;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;connectionString&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;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;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;product&lt;/span&gt;&lt;span class="p"&gt;]&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;product&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="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="c1"&gt;// pages/api/products/[id].ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&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;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GetProduct&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;@/use-cases/GetProduct&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DrizzleProductRepository&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;@/infrastructure/DrizzleProductRepository&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;getProduct&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;GetProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DrizzleProductRepository&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&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;NextApiRequest&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;NextApiResponse&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&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;query&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;product&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;getProduct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;product&lt;/span&gt;&lt;span class="p"&gt;)&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="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;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product not found&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this structure, swapping databases only requires creating a new repository implementation. The use case and API route don't need to change at all. That's the power of Clean Architecture - it isolates the impact of changes to specific parts of your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Architecture: The Layer Cake
&lt;/h2&gt;

&lt;p&gt;Picture your NextJS app as a layer cake:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Entities&lt;/strong&gt; (Core): These are your business objects. In our e-commerce app, think &lt;code&gt;Product&lt;/code&gt;, &lt;code&gt;Order&lt;/code&gt;, and &lt;code&gt;Customer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Cases&lt;/strong&gt; (Application Business Rules): These orchestrate data flow between entities and the outer layers. Example: &lt;code&gt;GetProduct&lt;/code&gt;, &lt;code&gt;PlaceOrder&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interface Adapters&lt;/strong&gt;: They convert data between use cases and external agencies. In NextJS, this includes your API routes and controllers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks and Drivers&lt;/strong&gt; (Outermost layer): This is where NextJS, DrizzleORM, PostgreSQL, and UI components live.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Key Principles in Action
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The Dependency Rule
&lt;/h3&gt;

&lt;p&gt;Inner layers should not know about outer layers. This means your &lt;code&gt;Product&lt;/code&gt; entity shouldn't know about your database or NextJS.&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;// Good: Entity doesn't know about storage or framework&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Bad: Entity depends on a database&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InferModel&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;drizzle-orm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;products&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;@/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;InferModel&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;products&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;save&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="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// This violates Clean Architecture&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use Cases Define Application Behavior
&lt;/h3&gt;

&lt;p&gt;Use cases encapsulate and implement all of the use cases of the system.&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdateProduct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;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;product&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;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product not found&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;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;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Interface Adapters
&lt;/h3&gt;

&lt;p&gt;In NextJS, your API routes act as interface adapters. They convert incoming HTTP requests into calls to your use cases and convert the results back into HTTP responses.&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;// pages/api/products/[id].ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&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;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UpdateProduct&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;@/use-cases/UpdateProduct&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DrizzleProductRepository&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;@/infrastructure/DrizzleProductRepository&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;updateProduct&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;UpdateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DrizzleProductRepository&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&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;NextApiRequest&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;NextApiResponse&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&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;query&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;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="k"&gt;try&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;updateProduct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;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;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product updated successfully&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;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;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;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&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="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Allow&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Method &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;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Not Allowed`&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;h3&gt;
  
  
  4. Frameworks and Drivers
&lt;/h3&gt;

&lt;p&gt;This layer is where all the details go. Your NextJS configuration, DrizzleORM setup, database connection, and React components live here.&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;// infrastructure/DrizzleProductRepository.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drizzle&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;drizzle-orm/node-postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;eq&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;drizzle-orm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&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;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;products&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;@/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&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;@/use-cases/UpdateProduct&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;class&lt;/span&gt; &lt;span class="nc"&gt;DrizzleProductRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&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;pool&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;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;connectionString&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;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;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;product&lt;/span&gt;&lt;span class="p"&gt;]&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;product&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="k"&gt;void&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set&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="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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="c1"&gt;// components/ProductForm.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&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;next/router&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;function&lt;/span&gt; &lt;span class="nf"&gt;ProductForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPrice&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&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;handleSubmit&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&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;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&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;body&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;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;price&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&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;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&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="cm"&gt;/* form fields */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;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;
  
  
  Real-World Benefits
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt;: You can test business rules without UI, database, or any external element.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independence&lt;/strong&gt;: You can easily swap out your database or even migrate from NextJS to another framework with minimal changes to your core business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: New developers can easily understand and navigate the system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Is It Always Necessary?
&lt;/h2&gt;

&lt;p&gt;For a simple CRUD app, Clean Architecture might be overkill. But it's a game-changer for complex applications where business rules are crucial. It's the difference between dreading and embracing changes to your codebase.&lt;/p&gt;

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

&lt;p&gt;Clean Architecture isn't just theoretical—it's a practical approach to building maintainable, flexible software with NextJS, even when using modern ORMs like DrizzleORM. By separating concerns and adhering to the dependency rule, you create a codebase that's resilient to change and a joy to work with.&lt;/p&gt;

&lt;p&gt;Next time you start a NextJS project, consider how Clean Architecture principles could make your future self (and your team) thank you. Your code will be cleaner, your architecture is more robust, and your development process smoother.&lt;/p&gt;

&lt;p&gt;As you implement Clean Architecture in your NextJS projects, remember that the examples provided in this guide are starting points. The beauty of Clean Architecture lies in its flexibility within its core principles. Feel free to iterate and refine these patterns to best suit your project's needs while maintaining the separation of concerns and dependency rules that make Clean Architecture so powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Clean Architecture Project Structure for NextJS with DrizzleORM
&lt;/h2&gt;

&lt;p&gt;Here's a sample project structure that follows Clean Architecture principles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nextjs-app/
├── src/
│   ├── entities/
│   │   └── Product.ts
│   ├── use-cases/
│   │   ├── GetProduct.ts
│   │   └── UpdateProduct.ts
│   ├── interfaces/
│   │   └── repositories/
│   │       └── ProductRepository.ts
│   ├── infrastructure/
│   │   ├── DrizzleProductRepository.ts
│   │   └── schema.ts
│   ├── pages/
│   │   ├── api/
│   │   │   └── products/
│   │   │       └── [id].ts
│   │   ├── products/
│   │   │   ├── [id].tsx
│   │   │   └── edit/[id].tsx
│   │   └── index.tsx
│   └── components/
│       └── ProductForm.tsx
├── public/
├── tests/
│   ├── unit/
│   ├── integration/
│   └── e2e/
├── package.json
├── tsconfig.json
└── next.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: This project structure is a suggested template based on Clean Architecture principles. You may adjust it to fit your specific project needs, development practices, and team preferences. The key is to maintain a clear separation between the layers of your application, ensuring that dependencies point inwards towards the core business logic.&lt;/p&gt;

&lt;p&gt;Happy coding, and happy Monday!&lt;/p&gt;




&lt;p&gt;Reference:&lt;br&gt;
&lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cleancoding</category>
      <category>softwaredevelopment</category>
      <category>codemaintainability</category>
      <category>cleanarchitecture</category>
    </item>
    <item>
      <title>Debugging Your Productivity: A Guide to Mindfulness and Efficiency</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Fri, 30 Aug 2024 06:39:52 +0000</pubDate>
      <link>https://forem.com/benborla/debugging-your-productivity-a-guide-to-mindfulness-and-efficiency-4le1</link>
      <guid>https://forem.com/benborla/debugging-your-productivity-a-guide-to-mindfulness-and-efficiency-4le1</guid>
      <description>&lt;h1&gt;
  
  
  Taming the Chaos: A Real-World Guide to Mindfulness and Productivity
&lt;/h1&gt;

&lt;p&gt;Look, we've all been there. You sit down to tackle that big project, and suddenly your phone chirps. Before you know it, you're down a rabbit hole of cat videos and obscure Wikipedia articles. Two hours later, you're wondering where the day went. Sound familiar?&lt;/p&gt;

&lt;p&gt;In this wild, wired world of ours, staying focused is like trying to herd cats – while the cats are on caffeine. But fear not! I've stumbled through the productivity maze and come out the other side with some hard-earned wisdom to share.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Modern Brain: Overwhelmed and Underprepared
&lt;/h2&gt;

&lt;p&gt;Let's face it: our noggins weren't built for this. We're bombarding our poor brains with a firehose of information every day. How much? Try 34GB – that's like reading "War and Peace" seven times over. Every. Single. Day.&lt;/p&gt;

&lt;p&gt;No wonder we're all walking around like zombies half the time. This info deluge is doing a number on us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our attention spans are shrinking faster than my patience in rush hour traffic&lt;/li&gt;
&lt;li&gt;Stress levels are through the roof (and the roof is already pretty high)&lt;/li&gt;
&lt;li&gt;Making decisions feels like defusing a bomb blindfolded&lt;/li&gt;
&lt;li&gt;Creative juices? More like a creative drought&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But hey, recognizing the problem is half the battle, right? So let's dive into the murky waters of our overloaded minds and see if we can't find some treasure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Procrastination vs. Burnout: The Productivity Frenemies
&lt;/h2&gt;

&lt;p&gt;Here's a fun game: try to guess which productivity killer you're dealing with today! Is it our old pal procrastination, or its evil twin, burnout? Spoiler alert: they're both the worst.&lt;/p&gt;

&lt;h3&gt;
  
  
  Procrastination: The "I'll Do It Tomorrow" Trap
&lt;/h3&gt;

&lt;p&gt;Ah, procrastination. It's not just being lazy (though sometimes a nap does sound pretty good). It's more like your brain's way of playing hooky from adulting.&lt;/p&gt;

&lt;p&gt;You might be in Procrastination Nation if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You've got more excuses than a politician caught with their hand in the cookie jar&lt;/li&gt;
&lt;li&gt;The guilt of not working is almost as bad as actually working&lt;/li&gt;
&lt;li&gt;You've become a champion at "productive procrastination" (hello, spotless kitchen!)&lt;/li&gt;
&lt;li&gt;Deadlines whoosh by like you're standing still&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why do we do this to ourselves? Well, it could be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fear of messing up (hello, perfectionism, my old friend)&lt;/li&gt;
&lt;li&gt;Feeling lost in the sauce (what even are goals?)&lt;/li&gt;
&lt;li&gt;Time management skills that would make a sloth look efficient&lt;/li&gt;
&lt;li&gt;Emotions? In this economy? No thanks!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Burnout: When Your Get-Up-And-Go Has Got-Up-And-Gone
&lt;/h3&gt;

&lt;p&gt;Now burnout, that's a whole other kettle of fish. It's like your brain has gone on strike, and it's not accepting any negotiations.&lt;/p&gt;

&lt;p&gt;You might be burning out if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The mere thought of your to-do list makes you want to hibernate&lt;/li&gt;
&lt;li&gt;Even the fun stuff feels like a chore (Netflix and chill? More like Netflix and stare blankly at the wall)&lt;/li&gt;
&lt;li&gt;You're about as cheerful as a wet cat&lt;/li&gt;
&lt;li&gt;Your body's sending out SOS signals (hello, insomnia, my least favorite bedfellow)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's cooking this burnout stew? Often it's:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Work stress that never lets up (like a bad houseguest)&lt;/li&gt;
&lt;li&gt;Feeling like a puppet on strings (where's the control?)&lt;/li&gt;
&lt;li&gt;Job expectations clearer than mud&lt;/li&gt;
&lt;li&gt;Work-life balance? More like work-work imbalance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Knowing which beast you're battling is key to picking the right weapons. So, let's gear up!&lt;/p&gt;

&lt;h2&gt;
  
  
  Outsmarting Your Own Brain: Jedi Mind Tricks for Productivity
&lt;/h2&gt;

&lt;p&gt;Time to pull a fast one on that grey matter of yours. Your brain might think it's the boss, but we're about to stage a coup.&lt;/p&gt;

&lt;p&gt;Try this on for size: when your mind whispers "Maybe later," you shout back "How about now?" When it starts spinning yarns about why you can't possibly work right now, call it bluff.&lt;/p&gt;

&lt;p&gt;Here's a real-life example: that report you've been dreading? Set a timer for 5 measly minutes and dive in. Chances are, once you're in, you're in. It's like tricking yourself into cleaning the house by saying you'll "just do one thing."&lt;/p&gt;

&lt;h2&gt;
  
  
  Future You: Your New Best Friend
&lt;/h2&gt;

&lt;p&gt;Imagine your future self as a real person. Would you dump all your work on them? Force them to pull an all-nighter? Probably not, unless you're a real jerk to yourself (in which case, we need to have a different talk).&lt;/p&gt;

&lt;p&gt;Before you make a decision, ask yourself: "Is Future Me going to high-five me for this, or curse my name?" It's amazing how this little mental trick can light a fire under your butt.&lt;/p&gt;

&lt;p&gt;Some ways to be Future You's hero:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tidy up your workspace before calling it a day (Future You will feel like they've got their life together)&lt;/li&gt;
&lt;li&gt;Prep some healthy snacks (Future You won't be hangry)&lt;/li&gt;
&lt;li&gt;Lay out your gym clothes (Future You will have one less excuse)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mornings: Setting the Stage for Awesome
&lt;/h2&gt;

&lt;p&gt;I get it, mornings can be rough. But hear me out: how you kick off your day can make or break your productivity.&lt;/p&gt;

&lt;p&gt;Instead of face-planting into your phone first thing, try this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep a notebook by your bed (old school, I know, but trust me)&lt;/li&gt;
&lt;li&gt;When you wake up, take a few deep breaths (no, hitting snooze doesn't count as breathing)&lt;/li&gt;
&lt;li&gt;Spend 5-10 minutes brain-dumping everything on your mind&lt;/li&gt;
&lt;li&gt;For the important stuff, use this magic formula:
"I will [what] at [when] in [where]" (Implementation Intention from Atomic Habits)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"I will tackle those soul-crushing spreadsheets at 10 AM in my home office (with plenty of coffee)."&lt;/li&gt;
&lt;li&gt;"I will attempt to touch my toes without pulling a muscle at 6 PM in the living room."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's like giving your day a roadmap before you even brush your teeth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power of Pause: Because Sometimes Doing Nothing Is Everything
&lt;/h2&gt;

&lt;p&gt;In our mad dash to tick off to-do lists, we sometimes forget to ask if we're even running in the right direction. Enter the power of pause.&lt;/p&gt;

&lt;p&gt;Here's a little experiment for you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set an alarm for every couple of hours&lt;/li&gt;
&lt;li&gt;When it goes off, stop whatever you're doing (yes, even if you're in the middle of beating your high score on Candy Crush)&lt;/li&gt;
&lt;li&gt;Take 20 deep breaths (count them, it's oddly satisfying)&lt;/li&gt;
&lt;li&gt;Ask yourself: "Is what I'm doing right now important, or am I just spinning my wheels?"&lt;/li&gt;
&lt;li&gt;If you're off track, no biggie. Just course-correct and carry on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This little check-in can save you from spending hours on tasks that seemed crucial but were actually about as useful as a chocolate teapot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It All Together: Your "Get Your Act Together" Action Plan
&lt;/h2&gt;

&lt;p&gt;Rome wasn't built in a day, and your productivity empire won't be either. But here's a weekly plan to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monday: Kick off with your new morning routine (you've got this!)&lt;/li&gt;
&lt;li&gt;Tuesday: Outsmart your brain – tackle that one thing you've been avoiding&lt;/li&gt;
&lt;li&gt;Wednesday: Channel your inner time traveler and do something nice for Future You&lt;/li&gt;
&lt;li&gt;Thursday: Practice your pausing skills&lt;/li&gt;
&lt;li&gt;Friday: Look back on your week and give yourself a gold star (or identify where it all went pear-shaped)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, we're aiming for progress, not perfection. If you mess up, no worries. There's always tomorrow (but don't use that as an excuse to procrastinate, you hear?).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Grand Finale: Small Steps, Big Wins
&lt;/h2&gt;

&lt;p&gt;Living in our crazy, distracted world is like trying to meditate in the middle of a rock concert. It's tough, but it's not impossible.&lt;/p&gt;

&lt;p&gt;By being more mindful, constantly tweaking your approach, and treating your future self like your best friend, you're setting yourself up for success. Every small win adds up. The you of tomorrow, next month, next year? They'll be doing a happy dance thanks to the efforts you make today.&lt;/p&gt;

&lt;p&gt;Remember, being productive isn't about turning yourself into a work robot. It's about doing the stuff that actually matters and finding time for the good things in life (like binge-watching your favorite show without guilt).&lt;/p&gt;

&lt;p&gt;Your journey to mastering your mind in this bonkers world starts now. So, what's your first move going to be? Whatever it is, Future You is already breaking out the pom-poms.&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jamesclear.com/atomic-habits" rel="noopener noreferrer"&gt;Atomic Habits&lt;/a&gt; by James Clear&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/6708.The_Power_of_Now" rel="noopener noreferrer"&gt;The Power Of Now&lt;/a&gt; by Eckhart Tolle&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Discipline-Equals-Freedom-Field-Manual/dp/1250156947" rel="noopener noreferrer"&gt;Discipline Equals Freedom&lt;/a&gt; by Jocko Willink&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivityhacks</category>
      <category>devlifebalance</category>
      <category>techwellness</category>
      <category>focusedcoding</category>
    </item>
    <item>
      <title>Rust Microservice Starter Kit powered by Neon</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Wed, 28 Aug 2024 17:01:14 +0000</pubDate>
      <link>https://forem.com/benborla/rust-microservice-starter-kit-powered-by-neon-11n7</link>
      <guid>https://forem.com/benborla/rust-microservice-starter-kit-powered-by-neon-11n7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/neon"&gt;Neon Open Source Starter Kit Challenge&lt;/a&gt;: Ultimate Starter Kit&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Kit
&lt;/h2&gt;

&lt;p&gt;🦀 Rust Microservice Starter Kit - a powerful, type-safe, and memory-safe foundation for building high-performance APIs! This starter kit combines the robustness of Rust with the Axum web framework and the serverless PostgreSQL capabilities of Neon.&lt;/p&gt;

&lt;p&gt;🌟 Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust's strong type system and ownership model for safety and concurrency&lt;/li&gt;
&lt;li&gt;Axum's modular web framework for building scalable APIs&lt;/li&gt;
&lt;li&gt;Neon's serverless PostgreSQL with autoscaling and bottomless storage&lt;/li&gt;
&lt;li&gt;SeaORM for intuitive database interactions&lt;/li&gt;
&lt;li&gt;Comprehensive documentation and examples&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Link to Kit
&lt;/h2&gt;

&lt;p&gt;🔗 Repository: &lt;a href="https://github.com/benborla/rust-microservice-starter-kit" rel="noopener noreferrer"&gt;https://github.com/benborla/rust-microservice-starter-kit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demo: &lt;a href="https://rust-microservice-starter-kit.fly.dev/" rel="noopener noreferrer"&gt;https://rust-microservice-starter-kit.fly.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository includes detailed setup instructions, covering prerequisites, installation, project structure, testing, and deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;p&gt;Learning Rust was initially challenging, with concepts like borrowing, ownership, and lifetimes seeming confusing. However, with dedication and persistence, I gradually unraveled the language's intricacies.&lt;/p&gt;

&lt;p&gt;Creating this starter kit allowed me to apply my Rust knowledge to a real-world project. I encountered obstacles but learned valuable lessons in perseverance and growth. The Rust community provided invaluable support throughout the journey.&lt;/p&gt;

&lt;p&gt;Integrating Neon's serverless PostgreSQL was a game-changer, enabling me to focus on writing code without worrying about database management. SeaORM made database interactions seamless and intuitive.&lt;/p&gt;

&lt;p&gt;Structuring the project in a maintainable and scalable manner was crucial. By separating concerns and leveraging Rust's module system, I created a clean and organized codebase.&lt;/p&gt;

&lt;p&gt;🎉 I'm excited to share this starter kit with the community and empower developers to build robust microservices using Rust and Neon. Whether you're a seasoned Rust developer or just starting, this kit provides a solid foundation to kickstart your journey.&lt;/p&gt;

&lt;p&gt;Happy coding, and may your Rust journey be filled with growth and success! 🚀✨&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>neonchallenge</category>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>Efficient editor navigation for BEGINNERS in VIM - Part 1</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Thu, 07 Nov 2019 02:25:42 +0000</pubDate>
      <link>https://forem.com/benborla/efficient-editor-navigation-for-beginners-in-vim-part-1-1oof</link>
      <guid>https://forem.com/benborla/efficient-editor-navigation-for-beginners-in-vim-part-1-1oof</guid>
      <description>&lt;p&gt;In this post, I'm going to teach you how to efficiently navigate in Vim editor instead of you spamming keys &lt;code&gt;j, k, l, h&lt;/code&gt; (or the arrow keys) just to go to a certain character or line.&lt;/p&gt;

&lt;p&gt;This post is for aspiring Vim ninjas that want to make Vim as their primary editor when coding, or even writing anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;I recommend not to read the whole post but instead follow the guide that I will leave on each paragraph, so you would have time to learn and build that muscle memory as we go learn each command in Vim.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;I suggest to archive or save this so you can go back to this post anytime. The goal is to learn it step-by-step, and not learning all at once.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vim is great and powerful (if you have mastered all the keystrokes, shortcuts, mnemonics, etc), but it does take time to get used to it, especially building that muscle memory. It takes guts to fully grasp Vim and hone your skills with it.&lt;/p&gt;

&lt;p&gt;Without further ado, let's start! &lt;/p&gt;

&lt;p&gt;But first, let's go back to basics. To navigate to each character:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;j&lt;/code&gt; to go down, &lt;code&gt;k&lt;/code&gt; to go up, &lt;code&gt;h&lt;/code&gt; to get left, and &lt;code&gt;l&lt;/code&gt; to go right. For beginners, this may seem awkward because we used to do it on arrow keys or &lt;code&gt;WASD&lt;/code&gt; keys, in VIM, it's different.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When Bill Joy created the vi text editor he used the ADM-3A terminal, which had the arrows on hjkl keys. Naturally he reused the same keys and the rest is history. &lt;br&gt;
&lt;a href="https://catonmat.net/why-vim-uses-hjkl-as-arrow-keys" rel="noopener noreferrer"&gt;https://catonmat.net/why-vim-uses-hjkl-as-arrow-keys&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And for me, this is fine, so I can rest my fingers where I can reach the most common shortcut keys in Vim.&lt;/p&gt;

&lt;p&gt;Now you know the basic navigation, let's take another level, will take it slowly, as we tackle each command that we will be using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Legend&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
TTL - Time to Learn 😅&lt;/p&gt;

&lt;p&gt;To start, copy this gist and save it somewhere you can easily find.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Once done, open your terminal and run this command &lt;code&gt;vim path-to-lorem.txt&lt;/code&gt;, this will bring up the &lt;code&gt;lorem.txt&lt;/code&gt; that you just saved. We will be using this sample text file to practice.&lt;/p&gt;

&lt;p&gt;In order to navigate easily, we have to enable the &lt;code&gt;Line Number&lt;/code&gt;, most IDE has this built-in on their application, but in Vim, you have to enable this feature.&lt;/p&gt;

&lt;p&gt;In your VIM make sure you are in Normal mode, type &lt;code&gt;:set number&lt;/code&gt; and hit enter, as you can see this will show the line number(s) in your editor, most of Vim users I know use Relative Number as this is much easier to navigate line by line.&lt;/p&gt;

&lt;p&gt;You can see more about relative number by typing &lt;code&gt;:h relativenumber&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Show the line number relative to the line with the cursor in front of each line.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Navigate through each word&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;w&lt;/code&gt; jump to the start of the word this includes punctuation.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/JszvSZJFtdEvXwHryA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/JszvSZJFtdEvXwHryA/giphy.gif" alt="w command" width="823" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;W&lt;/code&gt; jump to the start of the word, does not include punctuations.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/ViOf8MKKbKgfkZwWZA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/ViOf8MKKbKgfkZwWZA/giphy.gif" alt="W command" width="823" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;b&lt;/code&gt; jump to the end of the word this includes punctuation.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/Js1FK2eV37rvMMEowr/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Js1FK2eV37rvMMEowr/giphy.gif" alt="b command" width="823" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;B&lt;/code&gt; jump to the end of the word, does not include punctuations.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/f8ytZhFhVsD8WacZ73/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/f8ytZhFhVsD8WacZ73/giphy.gif" alt="B command" width="823" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** Jump to the start or the end of the line **&lt;br&gt;
&lt;code&gt;0&lt;/code&gt; jump to the start of the line&lt;br&gt;
&lt;a href="https://i.giphy.com/media/KbAyk6OiIvqH60LKi5/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/KbAyk6OiIvqH60LKi5/giphy.gif" alt="0 command" width="823" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$&lt;/code&gt; jump to the end of the line.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/TLCqqfgGdO5qkLobqK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/TLCqqfgGdO5qkLobqK/giphy.gif" alt="$ command" width="823" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;*** TTL: 5 to 10 minutes ***&lt;/p&gt;




&lt;p&gt;&lt;em&gt;End of Part 1&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ide</category>
      <category>vim</category>
      <category>code</category>
      <category>vscode</category>
    </item>
    <item>
      <title>VIM | Getting rid of ESC key to switch to Normal mode</title>
      <dc:creator>Ben Borla</dc:creator>
      <pubDate>Tue, 05 Nov 2019 03:38:45 +0000</pubDate>
      <link>https://forem.com/benborla/vim-getting-rid-of-esc-key-to-switch-to-normal-mode-f3e</link>
      <guid>https://forem.com/benborla/vim-getting-rid-of-esc-key-to-switch-to-normal-mode-f3e</guid>
      <description>&lt;p&gt;It's important that you place your hands in a correct position to reach different keyboard keys, but it has been a pain for me ever since to reach the &lt;code&gt;ESC&lt;/code&gt; key just to switch to normal mode.&lt;/p&gt;

&lt;p&gt;Some say you have to remap the &lt;code&gt;CAPSLOCK&lt;/code&gt; key with &lt;code&gt;ESC&lt;/code&gt;, but that doesn't work for me since I need the &lt;code&gt;CAPSLOCK&lt;/code&gt; key sometimes if I need to write capitalized phrases or sentences.&lt;/p&gt;

&lt;p&gt;Obviously, remap is the only solution. With this, I can place my hands in one place, and not stressing my fingers to reach certain keys. &lt;/p&gt;

&lt;p&gt;You can put this in your .vimrc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;" Press nn to return to normal mode when in insert mode
inoremap ii &amp;lt;ESC&amp;gt;
inoremap &amp;lt;ESC&amp;gt; &amp;lt;NOP&amp;gt;

" Press ii to return to normal mode when in visual mode
vnoremap ii &amp;lt;ESC&amp;gt;
vnoremap &amp;lt;ESC&amp;gt; &amp;lt;NOP&amp;gt;

" Press ii when in Command mode, to go back to normal mode
cnoremap ii &amp;lt;ESC&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above will allow you to use &lt;code&gt;ESC&lt;/code&gt; functionality when pressing &lt;code&gt;ii&lt;/code&gt; on these modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert mode&lt;/li&gt;
&lt;li&gt;Visual mode&lt;/li&gt;
&lt;li&gt;Command mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This doesn't mean that you can't use the &lt;code&gt;ESC&lt;/code&gt;, it's still usable but if you prefer switching to normal mode, then &lt;code&gt;ii&lt;/code&gt; is the key to press.&lt;/p&gt;

&lt;p&gt;It will take some time to train your hands and build that muscle memory, but once you have, I can assure you that it's worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BONUS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Saving your changes, instead of &lt;code&gt;:w&lt;/code&gt; or &lt;code&gt;:w!&lt;/code&gt;, you can either map this with your leader key:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;noremap &amp;lt;Leader&amp;gt;s :update&amp;lt;CR&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;OR!!!&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;" Press ww to do a w!
inoremap ww &amp;lt;ESC&amp;gt;:w!&amp;lt;CR&amp;gt;
" nnoremap ww &amp;lt;ESC&amp;gt;:w!&amp;lt;CR&amp;gt;
vnoremap ww &amp;lt;ESC&amp;gt;:w!&amp;lt;CR&amp;gt;
" Press nww to do a save on normal mode
nnoremap nww &amp;lt;ESC&amp;gt;:w!&amp;lt;CR&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow you to save your changes without going to the command mode.&lt;/p&gt;

&lt;p&gt;For Insert mode, press &lt;code&gt;ww&lt;/code&gt; to save your changes.&lt;br&gt;
When in Normal mode, press &lt;code&gt;nww&lt;/code&gt; to save your changes.&lt;br&gt;
Lastly on Visual mode,  &lt;code&gt;ww&lt;/code&gt; to save your changes.&lt;/p&gt;

&lt;p&gt;I hope the remapped keys will help you to be more efficient when editing files on Vim.&lt;/p&gt;

&lt;p&gt;Thank you for your time!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>ide</category>
      <category>vscode</category>
      <category>editor</category>
    </item>
  </channel>
</rss>
