<?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: Clifton Beale</title>
    <description>The latest articles on Forem by Clifton Beale (@bealecs).</description>
    <link>https://forem.com/bealecs</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%2F1075689%2F2cebae7c-74ea-4075-b281-9a046a6a3d71.jpg</url>
      <title>Forem: Clifton Beale</title>
      <link>https://forem.com/bealecs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bealecs"/>
    <language>en</language>
    <item>
      <title>Building Games with JavaScript and PostreSQL</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Mon, 03 Feb 2025 01:52:44 +0000</pubDate>
      <link>https://forem.com/bealecs/building-games-with-javascript-and-postresql-5bb6</link>
      <guid>https://forem.com/bealecs/building-games-with-javascript-and-postresql-5bb6</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check out the online board game:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://clifs-boggle.vercel.app" rel="noopener noreferrer"&gt;Clif's Boggle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Table of Contents:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Game Breakdown&lt;/li&gt;
&lt;li&gt;Incorporating Players Without Authentication&lt;/li&gt;
&lt;li&gt;Real Time Updates&lt;/li&gt;
&lt;li&gt;Under the hood&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Being a software developer is a very rewarding profession. I love to build cool things, and the software that I build in my free time is almost exclusively a solution to a problem that I am facing. My family loves playing Boggle, a popular word game, when we are all together. Now that my brothers and I have all moved out of our parent's house, we seldom get to enjoy family game nights like we once did. In an effort to solve this issue, I decided to recreate the beloved Boggle but open-source and free!&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Breakdown
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-1"&gt;&lt;/a&gt;&lt;br&gt;
Just like starting out any other project, of course I took to the whiteboard (&lt;a href="https://excalidraw.com/" rel="noopener noreferrer"&gt;Excalidraw&lt;/a&gt;). Laying out the blueprints for the game is an important first step when building.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv11dgwg465f6uwgy1zqs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv11dgwg465f6uwgy1zqs.png" alt="Whiteboard depiction of the game" width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
When outlining the project, I came up with a couple of different pages to tie the whole game together.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial landing page&lt;/li&gt;
&lt;li&gt;/lobbies page&lt;/li&gt;
&lt;li&gt;/&lt;a href="https://dev.todynamic%20slug"&gt;lobby_code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;/[lobby_code]/[player_name]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The way that the game works is quite simple: the player will initially land on the home page where they will be asked to create a game or join a lobby. Players can click a button to navigate to the /lobbies page where they can view any publicly open lobbies (Lobbies are set as public or private upon creation).&lt;/p&gt;

&lt;p&gt;I needed to track a couple of persistent variables for each lobby, such as: - Game state (active/inactive): Boolean&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Board configuration (letter arrangement): String[]&lt;/li&gt;
&lt;li&gt;Players within a lobby: String[]&lt;/li&gt;
&lt;li&gt;Lobby status (public or private): Boolean&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The game state is changed when the lobby's game starts or ends as you would imagine. The board configuration manages how the letters are composed on the board so that the letters/order are persistent across clients (generated on each game start). When a player joins a lobby they will be prompted with an input for a name. Their input is sent to the boggle_game table row that matches the lobby code that the player is attempting to join. Players creating a new lobby are prompted with the same + an option to make the lobby public or private, and a random lobby code is generated on creation of the new lobby. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcib4pr694lekloksia18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcib4pr694lekloksia18.png" alt="Boggle_game table in Supabase database" width="800" height="40"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Incorporating Players Without Authentication
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-2"&gt;&lt;/a&gt;&lt;br&gt;
Typically on an application that requires multiplayer connectivity, developers would opt for an authentication solution to save player data to an account. After careful consideration, I decided that I wanted the game to be as simple as possible without needing account creation. This decision has it's pitfalls for sure, but for the nature of what I was working to achieve it gets the job done. &lt;/p&gt;

&lt;p&gt;Next.js happens to be my favorite framework to build software on the web, mostly because I find the developer experience to be fantastic. Next makes it simple to create dynamic routes for web applications, which is how I managed to separate game clients. Upon creating/joining a lobby and choosing a display name for the game, players are directed to the dynamic slug /[lobby_code]/[player_name] which will prime the board game to the respective client. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtpjtq4l27oi7u92xyei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtpjtq4l27oi7u92xyei.png" alt="Active game boggle online board" width="579" height="916"&gt;&lt;/a&gt;&lt;br&gt;
A boggle_player table is created to track player stats like word count and score after choosing a display name. This is necessary for the logic to differentiate between game clients and track player respective data for the game over screen. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5f19muu4y3lq7y4yjdjb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5f19muu4y3lq7y4yjdjb.png" alt="Game over screen for the boggle game online" width="775" height="624"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Real Time Updates
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-3"&gt;&lt;/a&gt;&lt;br&gt;
This is all very straightforward and seems simple enough to create, but I run into a major problem when thinking about how to get all of this to update on each client as needed so that changes are rendered to all players, not just the client that directs the change.&lt;/p&gt;

&lt;p&gt;I have used &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; as my go-to option for setting up a database. The software is open source if you wanted to operate it in a closed environment, but for the sake of what I am doing I opted to use their hobby(free) tier as it is very generous. Supabase has great documentation to get started making a piece of CRUD.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq1pcq11yjo8xmz6r8gb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq1pcq11yjo8xmz6r8gb.jpg" alt="Gordon Ramsay CRUD meme" width="600" height="360"&gt;&lt;/a&gt;&lt;br&gt;
Luckily after a quick google search, I found out that Supabase offers the functionality of real-time updates within their free plan! This seemed very generous to me, and after viewing the docs I was shocked to see how easy it looked to incorporate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const channels = supabase.channel('custom-all-channel')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'boggle_game' },
    (payload) =&amp;gt; {
      console.log('Change received!', payload)
    }
  )
  .subscribe()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above creates a channel in which Supabase will listen to any changes from the table: "boggle_game". &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The property, "event:" determines what the channel listens for (Insert, Update, Delete, or all - *). This makes it super simple to determine what to listen for and where to listen for it. &lt;/li&gt;
&lt;li&gt;The payload contains the new and old values from before/after the change to the DB table&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From here you can either extract the change from the payload or run a function to fetch the updated data from the table. Now, I incorporated a timer to the board game so that when the timer is done, an endGame() function is run that updates the game_status in the DB table which triggers the real-time update. With this done, the game was multiplayer ready!&lt;/p&gt;

&lt;h3&gt;
  
  
  Under the hood
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-4"&gt;&lt;/a&gt;&lt;br&gt;
When building real-time applications, there are a few ways to keep clients updated when data changes. The most common approaches are database polling and WebSockets, but they work very differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database Polling&lt;/strong&gt;&lt;br&gt;
Polling is a straightforward but inefficient way to check for updates. The client repeatedly sends requests to the server at fixed intervals (e.g., every second) to check if the data has changed. While this works, it comes with drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unnecessary load– The server handles requests even when no data has changed.&lt;/li&gt;
&lt;li&gt;Laggy updates – The UI only refreshes when the next request is made, making real-time interactions feel slow.&lt;/li&gt;
&lt;li&gt;Scalability issues – More users mean more requests, which can quickly become costly and inefficient.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7pi0t7zevnkhdn1qare9.png" alt="Diagram of database polling" width="800" height="583"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Web Sockets &amp;amp; Supabase’s Real-Time Setup&lt;/strong&gt;&lt;br&gt;
Instead of polling, a better approach is Web Sockets, which provide a persistent, two-way communication channel between the client and server. Once a Web Socket connection is established, the server can push updates to clients instantly, without waiting for them to ask.&lt;/p&gt;

&lt;p&gt;PostgreSQL, the database behind Supabase, doesn’t have native Web Socket support. However, Supabase bridges this gap using Replication and real time engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL’s Logical Replication – Whenever a change happens in a table (insert, update, delete), PostgreSQL emits a “change event.”&lt;/li&gt;
&lt;li&gt;Supabase Real time – This service listens to PostgreSQL’s replication stream and forwards those events to an internal Web Socket server.&lt;/li&gt;
&lt;li&gt;Web Socket Communication – Any client subscribed to real-time updates receives the changes immediately as soon as they happen in the database.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrgwh3wqe3axro5rr58v.png" alt="Diagram of a web socket connection" width="225" height="225"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this setup, my Boggle game doesn’t need to spam the server with requests. Instead, each client opens a Web Socket connection and gets notified only when something actually changes—whether a player joins, a word is submitted, or the game ends. This makes the game feel instant while keeping performance smooth, even with multiple players in a lobby.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;&lt;a id="section-5"&gt;&lt;/a&gt;&lt;br&gt;
Overall, I learned a lot from this project which is the underlying goal of any of my hobby projects. The end result is an online replica of a popular word game that my family loves playing. My family is now able to play any time and any place, allowing us to keep up with our traditions from anywhere. I learned what web sockets are, how web socket connections differ from other solutions like database polling, and how to implement such a solution with the help of Supabase. This project was really rewarding to work on, and I look forward to seeing what else I can build with web sockets in the future. &lt;/p&gt;

&lt;p&gt;Check out the game below:&lt;br&gt;
&lt;a href="https://clifs-boggle.vercel.app" rel="noopener noreferrer"&gt;Clif's Boggle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While the game does support multiplayer lobbies, you can also enjoy playing by yourself to see how many words you can get in 3 minutes. Enjoy :)&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Chrome Extensions</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Tue, 05 Mar 2024 21:09:22 +0000</pubDate>
      <link>https://forem.com/bealecs/chrome-extensions-1kmh</link>
      <guid>https://forem.com/bealecs/chrome-extensions-1kmh</guid>
      <description>&lt;h4&gt;
  
  
  I took a day off of work...
&lt;/h4&gt;

&lt;p&gt;I needed a personal day from my 9 to 5 today, and so I slept in a little later. I had the urge to learn something new, specifically something that has been on my mind for quite a while - I have just never been able to find the time. Luckily enough, I had the time to learn how to create my own Google Chrome extension.&lt;/p&gt;

&lt;p&gt;Google Chrome is one of the most popular browsers, hitting numbers of 3.2 billion users in December of 2023 (Source: &lt;a href="https://www.demandsage.com/chrome-statistics/#:~:text=Based%20on%20data%20from%20Statista,to%203.229%20billion%20in%202021" rel="noopener noreferrer"&gt;Demand Sage&lt;/a&gt;). I, for one, use Chrome each day as my browser of choice. I have found that the extensions offered by Chrome are quite helpful tools day in and day out, but I had never created my own. &lt;/p&gt;

&lt;p&gt;Lately, I have been wondering what the process to create a Chrome extension was. Given that I had time today, I watched a quick YouTube video; I did not realize how easy it truly was to create your own extension. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=B8Ihv3xsWYs" rel="noopener noreferrer"&gt;Check out the YouTube Video I watched&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only thing different than just creating a static site with HTML/CSS/JavaScript was that I had to set up a manifest.json file to configure my extension settings, which looked like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0cxyx0k86sr5568y50q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0cxyx0k86sr5568y50q.png" alt="Code snippet of my manifest.json" width="656" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it is not a lot of work setting up this manifest.json. You just need to fill in a couple of the settings for the extension, like name and description. There are optional properties you can add, like "default_icon": to the action property.. This would replace the extension icon to the icon of your choice. More on the extension settings here in the tutorial: &lt;a href="https://developer.chrome.com/docs/extensions/get-started" rel="noopener noreferrer"&gt;Chrome Extensions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided to make an extension that would interact with me on a daily basis.. What do I do on a daily basis that could be enhanced, though? Well, I decided to create a dynamic job search extension. This extension pulls job search results directly from LinkedIn (in real time!) based on a pre determined search query that I created for myself. Check out the &lt;a href="https://github.com/bealecs/chrome-extension" rel="noopener noreferrer"&gt;public GitHub Repository&lt;/a&gt; for a look at the code that went into the project.&lt;/p&gt;

&lt;p&gt;I am looking at new job postings on LinkedIn each day, and this extension that I created (in just about an hour) will streamline personal job search results based off my preferences each day. I pinned my extension for even more convenience, so now with just one click I have custom-queried job results in real time. I am all about creating solutions to real world scenarios/issues, and this tool is guaranteed to save me time in my future job searching.&lt;/p&gt;

&lt;p&gt;Check out the README.md in the &lt;a href="https://github.com/bealecs/chrome-extension" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt; to clone the repo and set it up yourself. I used &lt;a href="https://rapidapi.com/collection/list-of-free-apis" rel="noopener noreferrer"&gt;RapidAPI&lt;/a&gt; to find the API for LinkedIn, and then set my custom search preferences from there. Otherwise, you can directly update the search parameters in the API call from the script.js file.&lt;/p&gt;

&lt;p&gt;All in all, this side project only took around an hour to complete and was super cool to learn. Not only that, but I also have the added reward of saving time down the road - that's what coding is all about to me. &lt;/p&gt;

&lt;h4&gt;
  
  
  Resources and Links
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/bealecs/chrome-extension" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://rapidapi.com/collection/list-of-free-apis" rel="noopener noreferrer"&gt;RapidAPI&lt;/a&gt; - List of free APIs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.demandsage.com/chrome-statistics/#:~:text=Based%20on%20data%20from%20Statista,to%203.229%20billion%20in%202021" rel="noopener noreferrer"&gt;Demand Sage&lt;/a&gt; - Reference to fact about Google Chrome users&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=B8Ihv3xsWYs" rel="noopener noreferrer"&gt;YouTube Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/extensions/get-started" rel="noopener noreferrer"&gt;Chrome Extension Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>extensions</category>
      <category>chrome</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Journey to Freelancing</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Tue, 20 Feb 2024 17:43:56 +0000</pubDate>
      <link>https://forem.com/bealecs/journey-to-freelancing-42e2</link>
      <guid>https://forem.com/bealecs/journey-to-freelancing-42e2</guid>
      <description>&lt;h2&gt;
  
  
  Check out my latest website:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://clifcodes.dev" rel="noopener noreferrer"&gt;Clif Codes&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Programming, not just web development, has been a passion of mine since I was a child. I have been coding since my early teen years, however I have shifted my main focus since separating from the U.S. military. My goal has been to become a web developer, which I have done an amazing job at, personally speaking.&lt;/p&gt;

&lt;p&gt;I received some advice from a mentor recently that I needed to stand out from the other applicants in my job search in order to get anywhere. I am all for a little bit of competition amongst job applicants, but in the field of web development right now - it's absurd (if you know you know). This is when I felt the need for a shift. I love what I do, however I do not love how competitive the nature of finding a job (doing what I love) has become. I feel that there is an unnecessary anxiety and hopelessness brought about with the overall competitiveness of the job market right now. With that being said, I figured it was time to take matters into my own hands.&lt;/p&gt;

&lt;p&gt;After completing several of my own projects, releasing a portfolio, and then creating a large scale, full-stack application ... I was still no closer to finding work than I was before. The difference, however, is that I am now stacked with all of these amazing skills that I have picked up and have been dying to show off. I am so excited to engage with clients, give consults, and be the boss of my own work environment. I have never taken on a challenge like this, and I am excited to see where this road leads me and my work in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  New webiste
&lt;/h3&gt;

&lt;p&gt;I created a fresh new landing page for my services as a freelance web developer. Seeing as this is a sort of fresh start for my career, I wanted to start off on a new foot. &lt;/p&gt;

&lt;p&gt;I leveraged Tailwind CSS to create my static app which was something new for me. &lt;/p&gt;

&lt;p&gt;The app offers an outlet to see my schedule/availability, find my contact links quickly and efficiently, schedule consults with me, and see the core services that I will be offering. I cannot list every possible service that I can perform, as my skills over the years have grown vast in the world of web development - which is why there is the 1-off solution service listed as well.&lt;/p&gt;

&lt;p&gt;After months of grueling job searching without any success, I am nervous and excited to be able to take control of my destiny. I believe that I will be successful in this endeavor as I am a self-starter; I have gotten this far into my journey on my own accord and I believe I have done well thus far. Be sure to check out my new website and leave my some anonymous feedback on the &lt;a href="https://clifcodes.dev/contact" rel="noopener noreferrer"&gt;contact&lt;/a&gt; page :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>freelance</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Debounce Solution</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Mon, 05 Feb 2024 22:41:43 +0000</pubDate>
      <link>https://forem.com/bealecs/debounce-solution-16in</link>
      <guid>https://forem.com/bealecs/debounce-solution-16in</guid>
      <description>&lt;p&gt;Today, data is issued and received so rapidly that solutions are needed to keep up with demand. When users are engaging with web applications, many times the content that they are engaging with is dynamic in nature. Essentially, this just means that the content that the user is receiving can be manipulated and served as situations unfold based on user input. &lt;/p&gt;

&lt;p&gt;For example, imagine you have a search bar function on a web application. Popularly, many web applications have their search bar show results as the user is typing their input, rather than waiting for a 'submit' button. A common problem that arises from this, though, is that users are sending requests to the server with each keystroke (as the state of the search input updates). Naturally, it is not necessary for the user to have results returned after each keystroke - which is where &lt;strong&gt;debouncing&lt;/strong&gt; comes into play.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk903v5wjt3yofeq4qm8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk903v5wjt3yofeq4qm8e.png" alt="Debounce approach illustration" width="800" height="480"&gt;&lt;/a&gt;&lt;br&gt;
Debouncing a function essentially is ensuring that the function in question is not getting called too hastily. &lt;/p&gt;

&lt;p&gt;I remember first learning about debouncing in a front-end masters course taught by Jem Young. It was one of the solutions to an interview question simulation as part of the online course. I remember at the time not really being able to understand the use case in full; just hearing about things doesn't always give me the full understanding, often times I need to build with it myself.&lt;/p&gt;

&lt;p&gt;At the time, all I knew was how to replicate the code for implementing debouncing as a solution and that it was used for the auto-suggesting text feature for the iPhone. After learning deeper, I have found that debouncing is a solution to a great number of different scenarios, many of which protect resource usage. &lt;/p&gt;
&lt;h3&gt;
  
  
  Building a Search Bar
&lt;/h3&gt;

&lt;p&gt;As my previous blog posts have foretold, I am still going through the next.js /learn course and building out the dynamic user dashboard web app. In &lt;strong&gt;chapter 11&lt;/strong&gt;, I was tasked with implementing a functional search bar for the customer invoices page. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Without Debounce&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7tptoip81uzkh3eogt0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7tptoip81uzkh3eogt0.png" alt="Code snippet of the search function without using debounce" width="774" height="540"&gt;&lt;/a&gt;&lt;br&gt;
Going off the tutorial provided by Next.js, I was instructed to handle the search bar as above provided so that the handleSearch function could be passed with an event handler to the input element (search bar). This way, with the hooks like useSearchParams and usePathName, I am able to update the URL in real time based off of the input in the search bar. &lt;/p&gt;

&lt;p&gt;The above method is not using debouncing, and would put the database at risk for many unnecessary search attempts once the users started adding up. This is because with each keystroke, the server would be reloading the search with the updated input field (because I am calling the function with an onChange event listener from the input element).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;With Debounce&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i use-debounce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ylxoudkxjrpkaa13r5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ylxoudkxjrpkaa13r5k.png" alt="Code snipping of the search function with using debounce" width="664" height="353"&gt;&lt;/a&gt;&lt;br&gt;
After installing the use-debounce package and importing useDebouncedCallback in the search bar component, you can simply change the function code to above and the library function will automatically debounce your function for you (you can change the 300 number to however many milliseconds you would like the debounce to take).&lt;/p&gt;

&lt;p&gt;With this method, keep in mind it is a downloadable solution. If you wanted to create your own solution and implement it, you might do something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc3bzr0yq03c9u671r39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc3bzr0yq03c9u671r39.png" alt="Code snippet for the debounce solution" width="732" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that debouncing has been added as a solution, users can get live results as they type in the search bar, but only after a brief pause. This way, resources from the database are saved once there are more users and the site is more performant in this area.&lt;/p&gt;

&lt;p&gt;I have never before done a search bar this way, and am once again learning something new from this Next.js/learn course. With Next Meal, I had used a 'submit' button once the user had finished what they were typing to find their search. This was an attempt to avoid problems that come from not debouncing (as it didn't occur to me to use it as a solution here). In the near future, I will be implementing debouncing into Next Meal's search bar as well since it is so easy. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp9s0uwqe5qoof4xvkhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp9s0uwqe5qoof4xvkhb.png" alt="Landing page for Next.js /learn course invoices page" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Credits:
&lt;/h4&gt;

&lt;p&gt;Code Snippet Clips: &lt;a href="https://carbon.now.sh/" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt;&lt;br&gt;
Learn Next.js 14: &lt;a href="https://nextjs.org/learn" rel="noopener noreferrer"&gt;Learn Next.js&lt;/a&gt;&lt;br&gt;
Frontend Masters - Jem Young: &lt;a href="https://frontendmasters.com/teachers/jem-young/" rel="noopener noreferrer"&gt;Front-end Masters - Jem Young&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>developer</category>
    </item>
    <item>
      <title>Loading.... Suspense</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Thu, 01 Feb 2024 22:24:27 +0000</pubDate>
      <link>https://forem.com/bealecs/loading-suspense-6hp</link>
      <guid>https://forem.com/bealecs/loading-suspense-6hp</guid>
      <description>&lt;p&gt;If you use React, you may have heard of 'Suspense' or even used it before. What exactly is it used for, though?&lt;/p&gt;

&lt;p&gt;An element to a lot of popular dynamic web applications like Instagram, X - formerly Twitter, Facebook, and etc. is that while a component to the app is loading there is typically a skeleton UI that will render in its place.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5ctclq1d7nse2gvyqeb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5ctclq1d7nse2gvyqeb.jpg" alt="Skeleton UI preview" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
One of the main benefits to using React is the ability to build with components. Especially with a dynamic web app, a component fetching some data can slow down a chunk of the web app. React created Suspense boundaries for these components, in order to create a fallback UI for the web app to display until all of the nodes have finished rendering for the dynamic element. While the dynamic elements are fetching data, a loading UI will be shown alongside the static UI on the web app. This also helps with keeping navigation interruptible, meaning one does not need to wait for the content of the route to fully load before navigating to another route.&lt;/p&gt;

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

&lt;p&gt;Next.js v14 introduces a new way to implement this same Suspense, with partial pre rendering. For the dynamic web applications, the static components of will be served rapidly and the asynchronous content is served in parallel as it is fetched. The Next team believes that this method will be the future default rendering model of web applications. (You can check it out on chapter 10 of the &lt;a href="https://nextjs.org/learn" rel="noopener noreferrer"&gt;learn Next.js 14&lt;/a&gt; course)&lt;/p&gt;

&lt;h4&gt;
  
  
  It helped me with Next Meal
&lt;/h4&gt;

&lt;p&gt;I found out about Suspense while creating Next Meal, as the performance of my application was seemingly degraded due to the dynamic nature. I used Suspense boundaries as a solution to implement loading UI to the dynamic elements of the dashboard - this way users know that the screen is loading, not frozen. &lt;/p&gt;

&lt;p&gt;I even got a little creative with it, since I know that some users don't have blazing internet speeds and might be waiting for the data fetches. I created an array of dad jokes (all food centric) which get selected at random on each instance of a loading element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8jj0pxl30e2jpowh1ogr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8jj0pxl30e2jpowh1ogr.png" alt="Dad joke loading screen from Next Meal" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Check out my GitHub:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/bealecs" rel="noopener noreferrer"&gt;https://github.com/bealecs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Check out Next Meal:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://next-meal-cookbook.vercel.app" rel="noopener noreferrer"&gt;https://next-meal-cookbook.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Resources for post:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://react.dev/reference/react/Suspense" rel="noopener noreferrer"&gt;React Docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://nextjs.org/learn" rel="noopener noreferrer"&gt;Next.js learn 14&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Learn Next.js 14</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Mon, 22 Jan 2024 22:08:16 +0000</pubDate>
      <link>https://forem.com/bealecs/learn-nextjs-14-446e</link>
      <guid>https://forem.com/bealecs/learn-nextjs-14-446e</guid>
      <description>&lt;h3&gt;
  
  
  Vercel has been up to some big things lately
&lt;/h3&gt;

&lt;p&gt;When I started using Next.js in January of 2023, I was quickly thankful for the upgrade in developer experience. With the intro of &lt;strong&gt;version 13&lt;/strong&gt; in October, 2022, came the &lt;strong&gt;/app&lt;/strong&gt; layout for the popular web framework. While the new layouts, page routing, and React Server Components were very useful, there was a bit of a learning curve. &lt;/p&gt;

&lt;p&gt;The documentation was rather poor for the early months of version 13, and there were even some issues that needed work - it was an interesting challenge all the more. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In my last post I talk a bit about my latest break, and how it helped me. I have decided to jump back into learning the latest updates of Next, with their release of Next.js Version 14. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54jh1v103d28aiapepi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54jh1v103d28aiapepi5.png" alt="Landing page of the learn Nextjs 14 course website" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What I learned so far
&lt;/h4&gt;

&lt;p&gt;Next.js has a site - &lt;a href="https://nextjs.org/learn" rel="noopener noreferrer"&gt;Learn Next.js 14&lt;/a&gt; where they have some &lt;strong&gt;wonderful&lt;/strong&gt; documentation in regards to the new update (Next.js Version 14 - released Oct 26, 2023). &lt;/p&gt;

&lt;p&gt;Within the material, you will learn how to set up a fully functioning dynamic web application with a back end using Next.js v14 - all while learning about the new updates and how to add them. Not only is this good for new users, but also good for users that just would like to stay current with the latest updates in their tech stack.&lt;/p&gt;

&lt;p&gt;Currently, I have seeded my postgres SQL database (offered with free tier version from Vercel) with my dummy info for customers in accordance with the course instructions, and I am working now on adding in dynamic information to the dashboard. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4ys1bpgjda09bg0m4tc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4ys1bpgjda09bg0m4tc.png" alt="Dashboard page for user on the Nextjs 14 course web app" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is very pleasing when there is clear, guided documentation to walk you through the updates to a major framework like Next, especially when you learn better visually - like me. The team at Next.js really did an amazing job being very clear and helpful within the documentation, while even providing troubleshooting tips for some sections. I was honestly &lt;em&gt;blown away&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This little course, &lt;strong&gt;completely free&lt;/strong&gt;, is helping me come back from my break and re familiarize myself with a lot of the great benefits of Next.js, while also helping to really cement the new stuff - like how they have added font optimization by statically pre-rendering additional fonts at build time (the same way it does with the images). &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not to mention&lt;/em&gt; that it is a cool little project that can be hosted on your portfolio (or wherever you showcase your work). I personally am hosting my repo on &lt;a href="https://github.com/bealecs/learnNext14" rel="noopener noreferrer"&gt;my GitHub&lt;/a&gt;, and have started creating branches for each chapter so I can keep track of the curriculum. I am looking forward to continuing to building more this year with Next.js v14.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Burnout Post / Happy New Years</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Sun, 14 Jan 2024 20:47:43 +0000</pubDate>
      <link>https://forem.com/bealecs/burnout-post-happy-new-years-2ke</link>
      <guid>https://forem.com/bealecs/burnout-post-happy-new-years-2ke</guid>
      <description>&lt;p&gt;I &lt;strong&gt;&lt;em&gt;must&lt;/em&gt;&lt;/strong&gt; make that commit; I &lt;strong&gt;&lt;em&gt;must&lt;/em&gt;&lt;/strong&gt; fix that error tonight; I &lt;em&gt;&lt;strong&gt;must&lt;/strong&gt;&lt;/em&gt; finish this project; I &lt;strong&gt;&lt;em&gt;must&lt;/em&gt;&lt;/strong&gt; keep my GitHub chart green&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2u8r2lk4uv6bkes8tv55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2u8r2lk4uv6bkes8tv55.png" alt="A cartoon man stressing out about work while using the computer" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Take a break&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I did.&lt;/p&gt;

&lt;p&gt;Nearing the end of 2024, I postponed working on my latest project (&lt;a href="https://next-meal-cookbook.vercel.app" rel="noopener noreferrer"&gt;Next Meal&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Next Meal had gotten to a place where I could be proud of what I had learned and accomplished. After more than 6 months on the job search, several months unemployed working on Next Meal and other projects - I had to go back to work. &lt;/p&gt;

&lt;h3&gt;
  
  
  Breaks are good for you
&lt;/h3&gt;

&lt;p&gt;During my break, I took the opportunity to reflect on my initial motivation for becoming a web developer as well as the significant progress I've made along the way.&lt;/p&gt;

&lt;p&gt;When I caught a mental glimpse at how much I had learned from the beginning of my journey to where I am now, I was blown away. I am so happy with where my work is at as a web developer now that I am ready to commit more publicly. I am looking to work with opensource projects or groups of individuals with a common interest. &lt;/p&gt;

&lt;p&gt;Before my break, I was starting to get very tired of working towards seemingly nothing. I was tired of not hearing any positive news with my job search, and I was losing hope.&lt;/p&gt;

&lt;p&gt;Flash forward to a couple of months later, and my head is back in the game. I have been working a different job while taking a break from web development, so my mind is still &lt;em&gt;sharp&lt;/em&gt; and ready.&lt;/p&gt;

&lt;p&gt;I took from the break, &lt;strong&gt;most importantly&lt;/strong&gt;, that I need time to reflect on my achievements and successes, &lt;em&gt;especially&lt;/em&gt; when I am experiencing failure. My work is important, but it is important that I am well enough to continue caring for my work. It is important, for me, that I recognize my progress and even celebrate it - for it is a step in the journey towards the end goal. &lt;/p&gt;

&lt;h3&gt;
  
  
  Going back to work
&lt;/h3&gt;

&lt;p&gt;I started working as a delivery driver for Amazon once again, and took a break from my studies at the end of October. Here and there, I would sit at my computer and change a couple of things on my portfolio to keep it up to date, but other than that I was taking a strategic mental pause. &lt;/p&gt;

&lt;p&gt;Here we are in 2024, a new year with amazing possibilities ahead of each of us. &lt;strong&gt;I am back&lt;/strong&gt; to claim what I have been working so hard for in these previous years. &lt;/p&gt;

&lt;h3&gt;
  
  
  My goals for 2024
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Meet new people&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find a new mentor (maybe?)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explore new and updated technologies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the best father I can be to my new son&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find a job that pushes me to learn new things&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My plans for 2024
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Continue improving my work on Next Meal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continue keeping my portfolio up to date&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be more active on LinkedIn&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interact with groups of individuals on open sourced projects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continue my job search for a position as a web developer&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b1kl65l7ltrdhhd3h3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b1kl65l7ltrdhhd3h3k.png" alt="Fireworks generated by OpenAI's DALL-E" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope that everyone had wonderful holidays in 2023, and an amazing new year so far -  I know I have. I am so excited for what this year has to bring, yet. &lt;/p&gt;

&lt;p&gt;If you have not seen my work check, be sure to check out &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://clif.codes" rel="noopener noreferrer"&gt;Clif Codes Portfolio&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://next-meal-cookbook.vercel.app" rel="noopener noreferrer"&gt;Next Meal&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>break</category>
      <category>webdev</category>
      <category>selfcare</category>
      <category>careerdevelopment</category>
    </item>
    <item>
      <title>Fine-Tuning Vercel AI SDK</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Wed, 27 Sep 2023 21:50:09 +0000</pubDate>
      <link>https://forem.com/bealecs/fine-tuning-vercel-ai-sdk-5ek6</link>
      <guid>https://forem.com/bealecs/fine-tuning-vercel-ai-sdk-5ek6</guid>
      <description>&lt;h3&gt;
  
  
  Creating custom responses based on user data:
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Jump to section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Overview&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the purpose?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementation and Troubleshooting&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conclusion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resources&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Overview
&lt;/h4&gt;

&lt;p&gt;&lt;a id="section-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently unveiled a sneak peak into my work over the last few months on 'Next-Meal'. One of the major features of the web app is the Sous-chef which leverages Vercel's AI SDK to incorporate a live chat bot to assist users in their search for their &lt;em&gt;&lt;strong&gt;next meal&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At first, the functionality remained pretty basic, as I simply followed &lt;a href="https://vercel.com/blog/introducing-the-vercel-ai-sdk" rel="noopener noreferrer"&gt;Vercel's documentation&lt;/a&gt; to implement it which was pretty straightforward. (See my blog post on adding Vercel's AI SDK &lt;a href="https://dev.to/bealecs/vercel-ai-sdk-tutorial-3jg3"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;After adding some cool features to the web app like user preferences (allowing users to filter through meals based on their account's preferences), I figured it was time to take the AI a step further. With a desire to sharpen my skills involving AI, I embarked on the task of implementing the user preferences filtering into the chat bot as well.&lt;/p&gt;

&lt;p&gt;This proved to be difficult, as once again I was navigating unfamiliar territory that has not been charted by many (not much documentation outside of Vercel for issues/implementation).&lt;/p&gt;

&lt;h4&gt;
  
  
  What is the purpose?
&lt;/h4&gt;

&lt;p&gt;&lt;a id="section-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While it is true that the AI on its own is a fascinating tool, for the sake of my use-case it could have proven dangerous. Once users set their preference on Next-Meal, most user's would assume that all of the app's functionality would automatically take their preferences into consideration. With this not being the case (out of the box), users could potentially consume food from the Sous-chef's suggestions that they may be allergic too or have an intolerance for unknowingly.&lt;/p&gt;

&lt;p&gt;My goal for Next-Meal, from the beginning, has been to give the users the most seamless experience when searching for a meal or recipe. With this extra step involved with the Sous-chef, users can be at ease knowing that their preferences are being accounted for in all areas of the web app. &lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation and Troubleshooting
&lt;/h4&gt;

&lt;p&gt;&lt;a id="section-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without a doubt, I ran into many different challenges during my attempts to implement this functionality. While I did persevere and eventually find a viable solution, I figured I would share my steps and some of my hardships that I faced so that maybe someone else won't run into the same issues.&lt;/p&gt;

&lt;p&gt;First off, I needed to figure out how to get the chatbot to understand each user's preferences. In order to achieve this, I gathered the preference information on the client, and sent it with the message to the chat API route on the server. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3atkbgkm29v9lubpbmg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3atkbgkm29v9lubpbmg6.png" alt="client side function for grabbing user preference values" width="800" height="454"&gt;&lt;/a&gt;&lt;br&gt;
Above is the function that retrieves the user preference values for my web app. &lt;br&gt;
&lt;em&gt;For reference&lt;/em&gt;, the user profile is an array that contains two objects, preferences and favorites. For this case, I am iterating through the key value pairs on the userPreferences object and only returning the key for the values that are truthy booleans (meaning that these preferences are set by the user already).&lt;/p&gt;

&lt;p&gt;This part definitely took some trial and error, and I am ashamed to admit I spent a great deal of time treating the preferences object as an array and trying to leverage built in JS array methods before realizing my error. &lt;/p&gt;

&lt;p&gt;Well, now I have the preferences on the client, but how do I get them over to the server when I am using a built in custom hook to send my information over to the server? &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9gi1bz2xmg8ktkrf1lp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9gi1bz2xmg8ktkrf1lp.png" alt="useChat hook offered by Vercel AI SDK" width="740" height="205"&gt;&lt;/a&gt;&lt;br&gt;
After doing some digging on the Vercel docs for the best method to handle this issue, I came across &lt;a href="https://sdk.vercel.ai/docs/api-reference/use-chat" rel="noopener noreferrer"&gt;this documentation&lt;/a&gt; for their useChat hook (shoutout Vercel for amazing docs!). After realizing you can pass an extra body object to the hook to be accessed by the server, I was back in the ball game. I quickly altered my code:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxpkkosys9iqlnd04z5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxpkkosys9iqlnd04z5n.png" alt="revised usage of useChat hook" width="800" height="494"&gt;&lt;/a&gt;&lt;br&gt;
Now I was checking to make sure that there was an active session (because the Sous-chef can be used by users that have not created an account) and also checking to make sure that there were preferences to send from the user, and if not then sending nothing (obviously) - incase the users had not yet set preferences. &lt;/p&gt;

&lt;p&gt;I will also admit from here, I was a bit unsure how to leverage this body property as I was getting some weird errors trying to access the req.body on the server side.&lt;/p&gt;

&lt;p&gt;Once I realized my error, I felt stupid... The body off the request was the body of the useChat hook, which also encompassed other values, such as the message from the hook. Once I realized this much, I was able to simple destructure the preferences from the req.json, right alongside the messages.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g3ow1hpdtkrkvudfgnu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g3ow1hpdtkrkvudfgnu.png" alt="de-structuring values from req.json" width="580" height="205"&gt;&lt;/a&gt;&lt;br&gt;
Finally, things are starting to come together. Now I just need to somehow tell Chat-GPT about these preferences that I now have on the server. Vercel's AI SDK offers a very easy solution to customize your prompts, which I had already tinkered with previously. Once I had the preferences on the server, I simply adjusted my code to let the system know about the preferences, and voila! &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fal3ztesodfio9itifzcy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fal3ztesodfio9itifzcy.png" alt="Setting up the bot's response pattern" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;&lt;a id="section-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I now, after several days of troubleshooting and reading through documentation (and also consulting with Chat-GPT), had finished.&lt;/p&gt;

&lt;p&gt;The functionality is all in tact, and users can now leverage their preferences through the Sous-chef.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpk1c725ccm9uyixn3mm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpk1c725ccm9uyixn3mm.png" alt="Example of Sous-chef in action" width="635" height="663"&gt;&lt;/a&gt;&lt;br&gt;
Above is a screenshot of the Sous-chef in action. I personally don't care for dairy or pork, so I have marked those two ingredients in my preferences to avoid. As you can see, the chatbot provides accurate suggestions without needing to be reminded of the preferences manually. There was some tinkering with the prompts, of course, before the Sous-chef was able to achieve this behavior. Prompt engineering for AI is very important, as it only knows information it is given. When working towards a solution such as this, the model is not trained on the user preferences that I was seeking it to have, so I had to get the prompt just right.&lt;/p&gt;

&lt;p&gt;Overall, this challenge was very rewarding to overcome. Now, I have a better understanding of the fundamentals of the AI model, as well as how to better manipulate the data given and received from Vercel's AI SDK.&lt;/p&gt;

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

&lt;p&gt;&lt;a id="section-5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://sdk.vercel.ai/docs" rel="noopener noreferrer"&gt;Vercel AI SDK Playground Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://sdk.vercel.ai/docs/getting-started" rel="noopener noreferrer"&gt;Vercel AI SDK Installation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/bealecs/vercel-ai-sdk-tutorial-3jg3"&gt;My previous blog post on the Vercel AI SDK&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/chatgpt?pivots=programming-language-chat-completions" rel="noopener noreferrer"&gt;Prompt engineering Microsoft Azure&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Next Meal</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Fri, 15 Sep 2023 20:29:02 +0000</pubDate>
      <link>https://forem.com/bealecs/next-meal-p2g</link>
      <guid>https://forem.com/bealecs/next-meal-p2g</guid>
      <description>&lt;h3&gt;
  
  
  Find your &lt;em&gt;next meal&lt;/em&gt; easier than ever
&lt;/h3&gt;

&lt;p&gt;I have been rather dormant with my blog posts lately, admittedly. I have not quit writing, but rather put my writings on pause for a moment. I was focusing my free time towards building my largest project that I have created yet. &lt;/p&gt;

&lt;p&gt;With little to no familiarity with a lot of the tools and technologies that I was choosing to leverage, I was heading towards mostly uncharted territory for me. What's more, I elected to complete this project with out leveraging tutorials. However, I did use the docs, Stack Overflow, and even sometimes Chat-GPT for some assistance.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is Next Meal
&lt;/h4&gt;

&lt;p&gt;Next Meal was designed based off of one of my initial projects as a web developer: &lt;a href="https://github.com/bealecs/meal" rel="noopener noreferrer"&gt;Clif's Catalog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next Meal blows its predecessor out of the water, however, offering many more features and benefits to its use. Some of the features of Next Meal include &lt;em&gt;(but are not limited to)&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sous-chef: Vercel AI SDK, essentially leveraging an API to Chat- 
GPT. Users can gather meal suggestions, instructions, 
information, and more from the live chat bot.&lt;/li&gt;
&lt;li&gt;Favorites: Users can select their favorite meals to save to 
their dashboard.&lt;/li&gt;
&lt;li&gt;Search Bar: Users can search through our vast catalog that is 
brought to us by &lt;a href="https://spoonacular.com/food-api" rel="noopener noreferrer"&gt;Spoonacular API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since creating Clif's Catalog, I have learned a lot about web development and different frameworks and libraries (specifically Next.js and TypeScript while building my portfolio). I decided to put my newfound knowledge to the test with this web app, and even push my limits a bit.&lt;/p&gt;

&lt;p&gt;The technologies and tools that I leveraged for this project are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;React/Next.js/TypeScript&lt;/li&gt;
&lt;li&gt;Next-Auth for authentication&lt;/li&gt;
&lt;li&gt;Prisma &amp;amp; Supabase for backend (User database)&lt;/li&gt;
&lt;li&gt;Spoonacular (API endpoints)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There were many challenges faced throughout the build process of Next Meal, but what web developer doesn't like a good challenge &lt;em&gt;(am I right)&lt;/em&gt;? I will be writing more in depth about individual issues faced, how I overcame them, and how I built out the app in further blog posts.&lt;/p&gt;

&lt;p&gt;For now, Next Meal is hosted on a Vercel Deployment, and is available to anyone.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Please Note:&lt;/strong&gt; Next Meal is not Production ready yet, and is currently in BETA stage. There are active issues and updates being posted daily on the GitHub repository; please feel free to follow along, the link is below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bealecs/NextMeal" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=rnOYdnrvLQ8" rel="noopener noreferrer"&gt;UX Flow Preview Video - Youtube&lt;/a&gt;&lt;br&gt;
&lt;a href="https://next-meal-cookbook.vercel.app" rel="noopener noreferrer"&gt;Next Meal - Direct Site Link&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Vercel AI SDK Walkthrough</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Wed, 26 Jul 2023 21:58:51 +0000</pubDate>
      <link>https://forem.com/bealecs/vercel-ai-sdk-tutorial-3jg3</link>
      <guid>https://forem.com/bealecs/vercel-ai-sdk-tutorial-3jg3</guid>
      <description>&lt;h3&gt;
  
  
  Implementing Vercel's AI SDK as a component
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Knowledge of Next.js v13+ (App directory) &lt;/li&gt;
&lt;li&gt;React/TypeScript (preferred)&lt;/li&gt;
&lt;li&gt;Intermediate level JavaScript knowledge&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Documentation can be found &lt;a href="https://vercel.com/blog/introducing-the-vercel-ai-sdk" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this video, I showcase how to implement Vercel's AI SDK into your web app as a component. In order to achieve this with Vercel's SDK, you will need to use Next.js. &lt;/p&gt;

&lt;p&gt;I bootstrapped a project,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9tfaosri9umhgkjgxbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9tfaosri9umhgkjgxbp.png" alt="Carbon copy of npx code used to create a next app" width="738" height="410"&gt;&lt;/a&gt;&lt;br&gt;
but you can also add the dependencies manually if you have an existing project that is not already using Next.js.&lt;/p&gt;

&lt;h4&gt;
  
  
  Getting Started
&lt;/h4&gt;

&lt;p&gt;Once you have your project layout, install the dependency necessary to implement the SDK&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxok79ahejdjw3wugg6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxok79ahejdjw3wugg6q.png" alt="Carbon copy of the code used to install the necessary dependencies" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, create your server side API @ root/api/chat/route.ts &lt;em&gt;(or route.js if you are not leveraging TypeScript)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inside this component, you will find all the code necessary for your server side API call &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwsx4rtxk5q3su67c8e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwsx4rtxk5q3su67c8e6.png" alt="Carbon copy of the server sided API call" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Excellent! Now we just need to create the component to showcase the new LLM on our site. &lt;/p&gt;

&lt;p&gt;At the root level of your layout, or in a components directory or wherever, you will create a component, Chat.tsx, which will handle your client side information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falbqbsukfj3irzalatv8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falbqbsukfj3irzalatv8.png" alt="Carbon copy for client side API call" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implement your client sided functionality, and there you have it. You have created a component that holds jsx for a form. Inside the form, users can type out an input, and click send. Submitting this input to the API is done through the useChat hook that is imported and provided to us. &lt;/p&gt;

&lt;p&gt;Essentially, we are just adding an interface to which we can string responses from OpenAI's Chat-GPT via an API call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind, this does cost money&lt;/strong&gt;, which is why I leverage the &lt;em&gt;3.5 turbo model&lt;/em&gt;. User input is transferred to tokens and charged to your account via your apiKey that is added in the server side API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another FYI&lt;/strong&gt;&lt;br&gt;
Add your .env.local file to your .gitignore file if you are leveraging a GitHub repository for your project. This will keep you safe from potential malicious attacks on your apiKey, resulting in charges to your credit card.&lt;/p&gt;

&lt;p&gt;On Production, you will need to add your environment variables to whatever service you are deploying with. Vercel makes it exceptionally easy to deploy, which you can check out &lt;a href="https://vercel.com/docs/concepts/deployments/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>vercel</category>
    </item>
    <item>
      <title>Advancements In Tech</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Thu, 06 Jul 2023 21:04:27 +0000</pubDate>
      <link>https://forem.com/bealecs/advancements-in-tech-5dig</link>
      <guid>https://forem.com/bealecs/advancements-in-tech-5dig</guid>
      <description>&lt;h3&gt;
  
  
  Exploring the Potential:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Discussing the impact and future of Generative Artificial Intelligence
&lt;/h4&gt;

&lt;p&gt;Jump to section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Blast Off - Birth of generative AI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generative AI Ethics - What if...?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Job Security - Are we in danger of losing jobs?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vercel AI SDK&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am sure that we have all heard some of the buzz around the &lt;strong&gt;large language models&lt;/strong&gt; (&lt;a href="https://en.wikipedia.org/wiki/Large_language_model" rel="noopener noreferrer"&gt;LLM&lt;/a&gt;) by now. What exactly do these advancements mean for the &lt;strong&gt;future&lt;/strong&gt; of our technology, though? &lt;/p&gt;

&lt;p&gt;Some &lt;strong&gt;speculate&lt;/strong&gt; that jobs will be threatened by the advancement of generative AI, and believe that it is not in our best interest moving forward. Others are thrilled and inspired by the winds of change, and are helping to propel towards &lt;em&gt;uncharted territory&lt;/em&gt; in the tech world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blast Off - Birth of generative AI
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-1"&gt;&lt;/a&gt;While it has been studied since around 2014, &lt;strong&gt;generative AI&lt;/strong&gt; really became prevalent in the tech community around late 2022. By early 2023, a lot of people had heard about it, and even started using models like &lt;a href="https://openai.com/blog/chatgpt" rel="noopener noreferrer"&gt;Chat-GPT&lt;/a&gt; to explore the capabilities of a LLM.&lt;/p&gt;

&lt;p&gt;Speaking of, &lt;strong&gt;OpenAI&lt;/strong&gt; launched Chat-GPT November 30, 2022. Since then, there have been &lt;strong&gt;major&lt;/strong&gt; improvements built into the LLMs, specifically how much data they use to &lt;strong&gt;generate&lt;/strong&gt; a response. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rivaling&lt;/strong&gt; companies have also started creating their own versions of the LLMs within their products, giving users a wider range of options to choose from.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Microsoft (Bing):&lt;/strong&gt; Implemented their own version of the LLM licensed through OpenAI, and has seen a reported 16% increase in traffic since. &lt;a href="https://searchengineland.com/new-bing-small-gains-vs-google-search-394733" rel="noopener noreferrer"&gt;See reference&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google (Bard):&lt;/strong&gt; Google hopped onto the generative AI bandwagon as well, creating their own version, Bard. Google's Bard works off of different data sets than OpenAI's Chat-GPT and has been listed as a great alternative&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, there are many other companies that have created their own adaptations, which you can view &lt;a href="https://techmonitor.ai/technology/companies-large-language-models-llms-chatgpt-alternatives" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jommf3zk1496pg3yzp1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jommf3zk1496pg3yzp1.jpeg" alt="AI bot saying can I help you" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generative AI Ethics
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-2"&gt;&lt;/a&gt;With new technology comes the responsibility of making sure that we are creating/using it &lt;strong&gt;ethically&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With new generative AI models like Chat-GPT becoming ever present, it is becoming easier to handle some tasks. For example, I could have Chat-GPT write this whole blog post for me if I wanted to. For me, that &lt;em&gt;defeats the whole purpose&lt;/em&gt; of posting my blogs; for others, it may be a &lt;strong&gt;valid tool&lt;/strong&gt; to assist in the writing process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fmgy21d5p76wsapptux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fmgy21d5p76wsapptux.png" alt="Image of Chat-GPT conversation displaying ethics conflict" width="728" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The inherent &lt;strong&gt;danger&lt;/strong&gt; comes when the AI is utilizing data that it is getting from all over, and spitting it back out to the user, who then is presenting the data as their own. In the image above, you can see I ask Chat-GPT for a sub heading to my blog post. Whenever I use something like that from Chat-GPT, I like to use it as a baseline &lt;strong&gt;suggestion&lt;/strong&gt;, and &lt;em&gt;alter&lt;/em&gt; it to my own. Read the conversation between Chat-GPT and myself, and you can understand some of the dangers that lie there.&lt;/p&gt;

&lt;p&gt;There have been lawsuits already against big companies (who's names I will not reveal) for copyright infringement as the AI is trained on information that is from all over, some even copyrighted.&lt;/p&gt;

&lt;p&gt;Personally, I have used Chat-GPT to help me out with my learning journey as it can be a &lt;strong&gt;great tool&lt;/strong&gt;. Chat-GPT can easily help you identify that pesky little spelling error that has been holding you up for hours. It can also, however, become a &lt;strong&gt;crutch&lt;/strong&gt;. Is it ethically correct to call yourself a coder when you can &lt;em&gt;only&lt;/em&gt; rely on tools like Chat-GPT? &lt;/p&gt;

&lt;p&gt;While tools will continue to be built upon, innovated, and invented, it is important to keep in mind that they are just that: &lt;strong&gt;tools&lt;/strong&gt;. We, as users, need to leverage tools &lt;strong&gt;ethically&lt;/strong&gt; and responsibly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Job Security - Are we in danger of losing jobs?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5blkat0udo6kxajrbsj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5blkat0udo6kxajrbsj.jpeg" alt="Text bubble saying " width="800" height="568"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a id="section-3"&gt;&lt;/a&gt;The job market in the tech world is like a revolving door. Each day, there may be a job title that did not previously exist. On the other hand, there are going to be jobs that are no longer needed as technology evolves.&lt;/p&gt;

&lt;p&gt;I believe this to be the case with generative AI. No doubt, I believe that some jobs will become &lt;em&gt;unnecessary&lt;/em&gt;, as they will be able to be done by AI or bots in the future (this has already started years back with AI machines in factories). With that being said, I also believe that this will &lt;strong&gt;create&lt;/strong&gt; more jobs than it will destroy.&lt;/p&gt;

&lt;p&gt;With so many companies competing to release the next &lt;em&gt;cutting-edge&lt;/em&gt; AI tech, more and &lt;strong&gt;more positions&lt;/strong&gt; will be needed to fill these roles. There will always need to be people updating/innovating on the technology that they are creating, which is why I believe that jobs are &lt;strong&gt;safe&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In tech, I do think it is a good idea to stay current with the times. While I did say I believe that jobs are safe, I meant that as in the grand scheme of things. &lt;strong&gt;Your&lt;/strong&gt; job, however may be affected down the road. Stay up to date on updates and releases, and don't get left behind in &lt;strong&gt;yesterday's&lt;/strong&gt; world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vercel AI SDK
&lt;/h3&gt;

&lt;p&gt;&lt;a id="section-4"&gt;&lt;/a&gt;&lt;em&gt;Be sure to check out Vercel's documentation on their AI SDK &lt;a href="https://vercel.com/blog/introducing-the-vercel-ai-sdk" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While several companies have been achieving great feats with AI, I wanted to specifically touch on Vercel's latest updates in AI.&lt;/p&gt;

&lt;p&gt;Vercel has released an &lt;strong&gt;open sourced&lt;/strong&gt; library for their AI SDK for developers. This &lt;a href="https://www.redhat.com/en/topics/cloud-native-apps/what-is-SDK" rel="noopener noreferrer"&gt;SDK&lt;/a&gt; is easy to use, with just a few lines of code you are up and running with an interactive &lt;a href="https://en.wikipedia.org/wiki/Large_language_model" rel="noopener noreferrer"&gt;LLM&lt;/a&gt; on your web app. The SDK leverages API requests to the LLM of your choice. Several different templates of LLM have been implemented by Vercel, including Open AI, Hugging Face, and LangChain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo5eoqdo3xacb1akf1pp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo5eoqdo3xacb1akf1pp.png" alt="Screenshot from Vercel's Post about their new SDK" width="768" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vercel has even included React and Svelte hooks within their library to ensure a clean user experience. These hooks allow the data received from the API request to be rendered smoothly as needed to give a better user experience. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of useChat() hook from &lt;a href="https://vercel.com/blog/introducing-the-vercel-ai-sdk#the-vercel-ai-sdk" rel="noopener noreferrer"&gt;Vercel AI SDK docs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fleyjmmca7z82odl8xapj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fleyjmmca7z82odl8xapj.png" alt="Example code for useChat() hook" width="800" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Naturally, being curious as I am, I attempted to implement this as a feature to my latest project. Surely enough, I was blown away by the overall simplicity of incorporating it. I will create another blog post soon explaining how I incorporated it into my project.&lt;/p&gt;

&lt;p&gt;I am very excited to see where this technology is going to go, personally. With less than a year's time, we have already made monumental advancements; I feel the best is yet to come. I will be staying tuned to advancements and updates as they come flying out from all corners, and yes, I will be writing about them! Stay tuned.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>writing</category>
    </item>
    <item>
      <title>Snakes in the Grass</title>
      <dc:creator>Clifton Beale</dc:creator>
      <pubDate>Fri, 30 Jun 2023 22:53:17 +0000</pubDate>
      <link>https://forem.com/bealecs/snakes-in-the-grass-j0i</link>
      <guid>https://forem.com/bealecs/snakes-in-the-grass-j0i</guid>
      <description>&lt;h3&gt;
  
  
  Staying safe throughout your job hunt
&lt;/h3&gt;

&lt;p&gt;Recently, I have embarked on a full time job hunt, in search of an &lt;strong&gt;opportunity&lt;/strong&gt; as a web developer. Even though times are tough right now, there are still good jobs out there worth applying to. While I have been applying to a number of different jobs, I have recently come across what I believe to be a &lt;strong&gt;scammer&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;With technology where it is today, and especially after the pandemic with remote jobs rising, &lt;strong&gt;phishing&lt;/strong&gt; for someone to scam through job boards has become prevalent (accord to &lt;a href="https://consumer.ftc.gov/articles/job-scams" rel="noopener noreferrer"&gt;The Federal Trade Commission's Consumer Advice&lt;/a&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  Real World Example
&lt;/h4&gt;

&lt;p&gt;I received an email recently from someone, who's name I will reveal (fake or not). The email, while it did not sound 100% legit, piqued my interest as I am intently looking for a job. I emailed back, and received a questionnaire to fill out in return. &lt;/p&gt;

&lt;p&gt;This questionnaire ran for about 20 questions long, and asked questions from entry level software engineer questions to personal questions about my life and experiences. I believed that this was a &lt;strong&gt;legit&lt;/strong&gt; pre screening document, and that I would fill it out and turn it in to them. &lt;/p&gt;

&lt;p&gt;After doing some digging, I saw that the address provided by the recruiter for the business was not even owned by that business. It was a random building owned by another business in the middle of Texas. Furthermore, the company had little to no digital footprint, and from there things started to look very shady. I looked up the recruiter on LinkedIn, and my search result revealed a fake persona. &lt;/p&gt;

&lt;p&gt;I am anxious to see what they say next, as I did respond with answering the questionnaire (most of the info could have been found on my LinkedIn) but I assume they will ask for more sensitive information down the road.&lt;/p&gt;

&lt;p&gt;With the world of technology as it is today, don't fall victim to those that want to prey on you. Protect yourself, and don't ignore the signs. Stay vigilant, and on the hunt. Good luck on your search for a job!&lt;/p&gt;

</description>
      <category>jobhunt</category>
      <category>scam</category>
      <category>security</category>
    </item>
  </channel>
</rss>
