<?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: Lucas Lima do Nascimento</title>
    <description>The latest articles on Forem by Lucas Lima do Nascimento (@llxd).</description>
    <link>https://forem.com/llxd</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%2F527863%2F2031d4d6-b921-4e94-b368-58981603dff1.png</url>
      <title>Forem: Lucas Lima do Nascimento</title>
      <link>https://forem.com/llxd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/llxd"/>
    <language>en</language>
    <item>
      <title>Super glad to have put that one out! Check it out if you're looking to learn a little more about architecture! 🚀</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Mon, 02 Dec 2024 14:53:00 +0000</pubDate>
      <link>https://forem.com/llxd/super-glad-to-have-put-that-one-out-check-it-out-if-youre-looking-to-learn-a-little-more-about-2lhj</link>
      <guid>https://forem.com/llxd/super-glad-to-have-put-that-one-out-check-it-out-if-youre-looking-to-learn-a-little-more-about-2lhj</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/encore" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F4094%2F34ea76ef-564a-401f-85bd-4ae600dc8955.png" alt="Encore" width="400" height="400"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F527863%2F2031d4d6-b921-4e94-b368-58981603dff1.png" alt="" width="510" height="585"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/encore/from-monolithic-to-microservices-architectures-101-3f2e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;From Monolithic to Microservices: Architectures 101&lt;/h2&gt;
      &lt;h3&gt;Lucas Lima do Nascimento for Encore ・ Dec 2 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#architecture&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>From Monolithic to Microservices: Architectures 101</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Mon, 02 Dec 2024 10:10:00 +0000</pubDate>
      <link>https://forem.com/encore/from-monolithic-to-microservices-architectures-101-3f2e</link>
      <guid>https://forem.com/encore/from-monolithic-to-microservices-architectures-101-3f2e</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&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%2Fh17c3k5o2xmx9grw53a9.gif" 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%2Fh17c3k5o2xmx9grw53a9.gif" alt="https://media4.giphy.com/media/UYgK6kSXD1WDu/giphy.gif?cid=7941fdc6fptefe0fdm2rpfsnozxvox6mvw4065mg2pbhymrp&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello there, dear reader! Well, if you’re reading this I assume that you probably have already a basic understanding of how the web works and you probably got a few things done by yourself as well, so congrats on that!&lt;/p&gt;

&lt;p&gt;The next big step is to understand a few of the patterns and architectures that exist out there. Not only that will make your software building more consistent, but also, way more solid too — from scalability to maintainability. &lt;/p&gt;

&lt;p&gt;This article will explore two of the most popular software architectures: the monolithic architecture and the microservices architecture (with some other important concepts in between).&lt;/p&gt;

&lt;p&gt;As always, we have a bunch of discussions regarding which of them is better and the answer here is as always the same: there’s no silver bullet, you should learn which are the cases for using each of them and how to transition between both as well to be a rational engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  First one: The Monolith
&lt;/h2&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%2Fwq14ghsmp2kqb31xrn8x.gif" 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%2Fwq14ghsmp2kqb31xrn8x.gif" alt="https://media4.giphy.com/media/kvT69yjOSlPtGPUexS/giphy.gif?cid=7941fdc6hg2npd5vgfjywwuckuamkd1c4u7j1u1sknwolmrp&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case you’re unfamiliar, the monolithic architecture is one of the most traditional ways to design software applications. In this approach, an application is built as a single unit — which we call the &lt;strong&gt;monolith&lt;/strong&gt; — where the components of the software are interconnected and interdependent. &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%2Ff1ydzol3dob0n2nn1kjh.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%2Ff1ydzol3dob0n2nn1kjh.png" alt="MVC model" width="300" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This architecture is characterized by a single codebase (usually using the &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" rel="noopener noreferrer"&gt;MVC pattern&lt;/a&gt;), shared database, and typically a single deployment unit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;p&gt;Monolithic applications are often simpler to develop, especially for smaller projects or teams. They have a straightforward development process since the interactions between different parts of your application reside in the same place — this also means that there are generally fewer API calls and fiddling data around to make stuff work!&lt;/p&gt;

&lt;p&gt;In terms of deployment, it generally is easier as well. Since you have a single unit, once you deploy it, everything should be up and running, meaning you don’t have any extra work on that.&lt;/p&gt;

&lt;p&gt;When we talk debugging, it is generally simpler because the entire application runs within a single unit (which means you generally don’t have to jump around between multiple applications, trying to find the problem). End-to-end testing can also be easier and can run smoothly through entire journeys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;p&gt;As the application grows, a few challenges start to appear. The first one is organization-wise — since everything is in the same place keeping the context of a really big application and all the ramifications it goes through starts to become really hard (of course, there are ways to plan ahead — e.g. the &lt;a href="https://www.milanjovanovic.tech/blog/what-is-a-modular-monolith" rel="noopener noreferrer"&gt;Modular Monolith&lt;/a&gt;, for example — for that, but, when you build fast, this generally are not thought through).&lt;/p&gt;

&lt;p&gt;The second one is scaling per se. Since the whole application is inside a single unit, specific usage-intensive points of your application will share the same resources as your whole app. This generally means that scaling things becomes a more complex task than just “pay more server power” or “rewrite that part in a different tech”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Microservices Architecture
&lt;/h2&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%2Fo36zk5b54blsd5s0cg75.gif" 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%2Fo36zk5b54blsd5s0cg75.gif" alt="https://media4.giphy.com/media/3o7TKzhPqGvUDm3pba/giphy.gif?cid=7941fdc6gzzw7dc1eobe4qlg3miho0oxvu4dt4ozve3x0bmc&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="540" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the general alternative to a Monolith is the Microservices architecture. It’s an approach to developing a single application as a suite of small services (that’s where the micro comes from), each running in its own process and communicating with lightweight mechanisms to keep it all running. They can usually be developed, deployed, and scaled separately. Each service typically has its own database and communicates with other services through well-defined APIs.&lt;/p&gt;

&lt;p&gt;It also has its own patterns of organization (which there are a ton of famous books about) where one of the most common ones is &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design#:~:text=Domain%2Ddriven%20design%20(DDD),which%20have%20their%20own%20model." rel="noopener noreferrer"&gt;DDD (Domain-Driven Design)&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;p&gt;The first and most obvious one is scale. Microservices can be scaled independently, allowing for more efficient resource utilization throughout the segments of your app. Since everything has to communicate as a black box, this architecture also provides flexibility in choosing technologies for different services.&lt;/p&gt;

&lt;p&gt;The second one is that when we are talking about really big apps, the complexity of the code of microservices is distributed between them. This generally means that, if a microservice has a bug, it’s simple to send a new engineer of the team to go take a look at it — there’s not that much space where this bug can exist anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;p&gt;The first one is that making all those things communicate and interact properly can be a real challenge. God only knows how much time an engineer is capable of spending trying to find why messages from Kafka are not arriving or any other weird problem that can happen. Managing all that, their infrastructure, and deployments can be hard.&lt;/p&gt;

&lt;p&gt;The second one is that the context is more segmented — this can be a good thing when we look at it coming from the point of view of learning the code base, but this can be a pain when looking at it as learning the product — it’s way easier to follow if your code goes through 5 files than 5 different apps.&lt;/p&gt;

&lt;p&gt;The last one is that microservices have a caveat which is &lt;strong&gt;Latency&lt;/strong&gt;. If they’re not designed properly, it’s quite possible that the separation of concerns and expected speed increase will not pay off since now you also added a bunch of different calls for them all to communicate.&lt;/p&gt;




&lt;p&gt;And sometimes, when people create new stuff, they try to fix part of those problems, which is part of the feature set of Encore, the sponsor of this article:&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%2F3ukalf9gco9fxdwater5.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%2F3ukalf9gco9fxdwater5.png" alt="Encore Logo" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A great standout feature for me is that you &lt;a href="https://encore.dev/docs/ts/primitives/api-calls" rel="noopener noreferrer"&gt;don’t need to worry about the communication between different microservices&lt;/a&gt; as much as you’d normally have to. It’s a really great idea — you have almost the same developer experience as when you’re working with a monolith, but, with all the scaling power of a microservice.&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%2Frh9lamz2gpldqdnkffby.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%2Frh9lamz2gpldqdnkffby.png" alt="Picture of an architectural flow" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;
In this case, for example, you can call a service from inside another one by simply importing it




&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%2Fo567j3c9n17t6tb7fctp.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%2Fo567j3c9n17t6tb7fctp.png" alt="Service call from inside of other service" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also a ton of features to make the &lt;a href="https://encore.dev/docs/platform/infrastructure/infra" rel="noopener noreferrer"&gt;deployment process of multiple services&lt;/a&gt; easier as well. They’re really trying hard to make that bridge of having the best of both worlds happen and it would be awesome if you could check them out and give them a star!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/encoredev/encore" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⚡ Star Encore ⚡&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing the Right Architecture
&lt;/h2&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%2Facmpmybod9sld8ymyyw0.gif" 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%2Facmpmybod9sld8ymyyw0.gif" alt="https://media3.giphy.com/media/3oKIPqsXYcdjcBcXL2/giphy.gif?cid=7941fdc66769jwvvnan2swwe8q12afmc8k5gdignwevs3s5i&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When deciding between architectures, you'll need to consider your application's growth potential, team size, and how complex your product actually is. &lt;/p&gt;

&lt;p&gt;The simpler your app is, the more you can benefit from a monolithic approach. If you’re in doubt, the safest choice is going with a monolith — you can always break things apart later, but, stitching things up is HARD (here’s a great source to read if you’re still in doubt: &lt;a href="https://martinfowler.com/bliki/MonolithFirst.html" rel="noopener noreferrer"&gt;Monolith First&lt;/a&gt;)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Architecture&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Key Benefit&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Key Disadvantage&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monolithic&lt;/td&gt;
&lt;td&gt;Simplified development, deployment and debugging&lt;/td&gt;
&lt;td&gt;Growing issues&lt;/td&gt;
&lt;td&gt;Small to normal-sized applications and MVPs (e.g. &lt;a href="https://github.com/forem/forem" rel="noopener noreferrer"&gt;DEV.to&lt;/a&gt; is a monolith!)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microservices&lt;/td&gt;
&lt;td&gt;Independent scaling of components&lt;/td&gt;
&lt;td&gt;Complex management&lt;/td&gt;
&lt;td&gt;Really large applications with multiple teams (e.g. &lt;a href="https://netflixtechblog.com/the-making-of-ves-the-cosmos-microservice-for-netflix-video-encoding-946b9b3cd300" rel="noopener noreferrer"&gt;Netflix&lt;/a&gt; uses a ton of microservices)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As complexity grows, you might want to consider breaking things apart, so, let’s talk a little bit about how can you convert a monolith into a series of microservices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Converting: How to migrate from monoliths to microservices.
&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%2Faqahwgb1eevzvof3x9an.gif" 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%2Faqahwgb1eevzvof3x9an.gif" alt="https://media2.giphy.com/media/26BGIqWh2R1fi6JDa/giphy.gif?cid=7941fdc6uggvsyc10h6vs8so9wj77mderowc1fc9f8ovssc4&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="500" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a few ways to migrate from a monolith into the microservice world. Let’s quickly go through them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Greenfield_project" rel="noopener noreferrer"&gt;Greenfield&lt;/a&gt; Replacement: Simply creating things from the ground up — not having constraints from prior work can be really beneficial in some cases. But, of course, we have a bunch of inherent possible problems here (how long will it take? how much time will users suffer? etc)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Brownfield_(software_development)" rel="noopener noreferrer"&gt;Brownfield&lt;/a&gt; Replacement: New architectures should coexist with live software. When we’re talking about brownfield replacement, there can be a lot of pain and headache in coexisting things with old/problematic software. An interesting approach to solve on how to tackle this problem is the &lt;a href="https://en.wikipedia.org/wiki/Strangler_fig_pattern" rel="noopener noreferrer"&gt;Strangler Fig pattern&lt;/a&gt;, where, we’ll generally wrap, little by little as a strangler fig, the old code and redirect it to newer code, eventually killing it. This makes the transition more smooth and also less risky.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generally, here are the steps we are going to take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify clear boundaries within the existing application.&lt;/li&gt;
&lt;li&gt;Gradually extract services, starting with less critical components.&lt;/li&gt;
&lt;li&gt;Implement new features as separate services&lt;/li&gt;
&lt;li&gt;Refactor the existing codebase to support the new architecture&lt;/li&gt;
&lt;li&gt;Ensure robust testing and monitoring throughout the migration process → Nothing is as hard as changing your application blindly&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&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%2Fh7k8o0gx9s32coqytkim.gif" 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%2Fh7k8o0gx9s32coqytkim.gif" alt="https://media0.giphy.com/media/T9JtEyoJ43gY4wLOqW/giphy.gif?cid=7941fdc6termxktyz4bgwbvc106kw8jauebencv8291a4w6m&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey! We've gone through quite a journey here. We talked about two main architectural approaches: the good old monolith (simple, and straightforward, but with growing challenges) and microservices (flexible, and scalable, but way more complex to manage). &lt;/p&gt;

&lt;p&gt;I hope that you’re now able to choose things (or at least have a great gut feeling) for the next choice you’re going to make, but, remember: there's no "one size fits all" - if you're starting something new, go with a monolith first if not, think it through!&lt;/p&gt;

&lt;p&gt;At the end of the day, what matters is picking the right tool for the job. Understanding these patterns will help you make better decisions for your specific needs. And remember: you can always change things later - just make sure you have a solid plan for that transition!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>Choosing the Right Tech Stack: A Developer's Decision-Making Guide</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Mon, 28 Oct 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/encore/choosing-the-right-tech-stack-a-developers-decision-making-guide-5gkd</link>
      <guid>https://forem.com/encore/choosing-the-right-tech-stack-a-developers-decision-making-guide-5gkd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&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%2F127okvyhyms5chq8cy6n.gif" 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%2F127okvyhyms5chq8cy6n.gif" alt="https://media3.giphy.com/media/JQ9Nwbtcn4PyLqgAS2/giphy.gif?cid=7941fdc6ths6zlk79k1t4i14mbza4yyg9ulg5yns1ucno0mn&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello there, dear reader! &lt;/p&gt;

&lt;p&gt;So, you’re at that spot, you’re beginning a new project and now, you have to choose which technology to go for. Do you go for the old and more reliable ones? Or you try out the new hot product on the market to see if it holds up to expectation?&lt;/p&gt;

&lt;p&gt;Well, it’s part of the engineering process to discover how to handle these situations, and, different engineers are going to have different takes on this — you’re probably even familiar with a bunch of opinions from different creators on which tech choices to use.&lt;/p&gt;

&lt;p&gt;The truth is that you have to discover what works best for you (and more specifically for the project), and, for me, there’s a 3-step process for you to choose things in a more assertive way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Evaluate the project requirements&lt;/li&gt;
&lt;li&gt;Evaluate the learning curve &amp;amp; tech characteristics&lt;/li&gt;
&lt;li&gt;Evaluate costs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this article, we’re going to go through examples of all scenarios, and, in the end, you’ll probably be able to choose by yourself and discover your own process in the middle of all that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluating the project requirements
&lt;/h2&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%2Fq9vkvl6e5aecdvw6wcuu.gif" 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%2Fq9vkvl6e5aecdvw6wcuu.gif" alt="https://media4.giphy.com/media/lPiubg7wdpSE5o2Ocg/giphy.gif?cid=7941fdc6ths6zlk79k1t4i14mbza4yyg9ulg5yns1ucno0mn&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While in my degree studies, I had a great professor who once said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The problem chooses the tooling, not you.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Are you creating a simple portfolio for yourself? A dog-pig identifier algorithm? A huge SaaS that will have to handle a ton of requests at the same time?&lt;/p&gt;

&lt;p&gt;All those cases impact heavily on the tooling you’ll choose. You can build a simple portfolio out of anything you want, even check out a bunch of cool stuff and random libraries, just for fun. That might not be necessarily compatible with the huge SaaS scenario though — so, here’s the first step catch.&lt;/p&gt;

&lt;p&gt;Before thinking too hard about what are the awesome stuff being released (being that new frameworks or just new releases of old frameworks), try to think in terms of exclusion by requirement: Is there any particular project requirement that might exclude a technology choice? If so, why? And please, try not to fall for imaginary problems made by fans of certain technologies — You’ll probably hear it all: X doesn’t scale, Y is better than Z, A is ugly (and to be fair, we all have our favorites). Your job here is to step aside, get your rational goggles on, and think rationally about your decision.&lt;/p&gt;

&lt;p&gt;Here are a few examples of solid tech choices that might suit some case for you:&lt;/p&gt;

&lt;h3&gt;
  
  
  Front-end
&lt;/h3&gt;

&lt;p&gt;I love front-end and one of the things that excites me the most is the amount of things being released into it. You might think that’s a burden and a problem, but, my take here is that whenever people create a new solution to a different problem, they push the bar further — making everyone along the way have to run to catch up. Here are a few front-end technologies worth exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kit.svelte.dev/" rel="noopener noreferrer"&gt;SvelteKit&lt;/a&gt;: Offers a compiler-based approach for building fast, efficient web apps&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://qwik.builder.io/" rel="noopener noreferrer"&gt;Qwik&lt;/a&gt;: Focuses on near-instant load times through resumability&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; (and other meta-frameworks like &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;): Known for its component-based architecture and virtual DOM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;: Offers a complete solution with two-way data binding&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; (and other meta-frameworks like &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;): Praised for its simplicity and gentle learning curve&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;htmx&lt;/a&gt;: Allows for dynamic content without heavy JavaScript frameworks&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jquery.com/" rel="noopener noreferrer"&gt;jQuery&lt;/a&gt;: Still relevant for quick DOM manipulations and AJAX calls (and for checking out some legacy systems)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Back-end/Full-stack
&lt;/h3&gt;

&lt;p&gt;On the back-end, there is a ton of great stuff being made, every iteration being more performant and even more focused on developer experience. Let’s check out a few projects worth checking out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;Ruby on Rails&lt;/a&gt;: Emphasizes convention over configuration&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://laravel.com/" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt;: PHP for Artisans&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt; (Java): Provides a robust ecosystem for enterprise applications&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;: Allows JavaScript on the server-side&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://deno.land/" rel="noopener noreferrer"&gt;Deno (v2)&lt;/a&gt;: A secure runtime for JavaScript and TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://encore.dev/" rel="noopener noreferrer"&gt;Encore&lt;/a&gt;: An open-source backend development platform that simplifies the entire backend development process, from API design to deployment.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hono.dev/" rel="noopener noreferrer"&gt;Hono&lt;/a&gt;: A small, simple, and ultrafast web framework for Deno, Bun, and Node.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important thing here is that: these projects exist for you to try out new things and fall in love. New solutions to old problems appear all the time, so, what you’re trying to catch is what they offer you — if you’re convinced some tech gives you enormous value, which generally comes in the format of performance and DX, you might consider learning it a little more deeper to solve the problem at hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluate the learning curve &amp;amp; tech characteristics
&lt;/h2&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%2Fdl8l3bev3wlpm54ksfma.gif" 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%2Fdl8l3bev3wlpm54ksfma.gif" alt="POV: You, learning a new tech for the first 11000 times." width="480" height="256"&gt;&lt;/a&gt;&lt;/p&gt;
POV: You, learning a new tech for the first 11000 times.



&lt;p&gt;The learning curve is a really important point to measure as well. How well do you or others on your team know certain technology? Are they familiar or have they just heard of it? &lt;/p&gt;

&lt;h3&gt;
  
  
  Short-term productivity
&lt;/h3&gt;

&lt;p&gt;You have to take that into account because it will directly impact your productivity, and, by a consequence, your deadlines. If you have a really tight deadline, it might not be the perfect time to test an entirely new tool you’re not sure will solve your problem, so, ask yourself: Is the learning curve of this tool a big impact on our dates? Do we already have knowledge in close spectrums?&lt;/p&gt;

&lt;p&gt;Questions like these might make you exclude a few other technologies based on time itself — you might have to pick up new stuff later, on a smaller project, and that’s okay. Remember that learning usually has a slow start and mastery takes time to get, but, it might pay off in scale and easiness of maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community Support
&lt;/h3&gt;

&lt;p&gt;Another important consideration when evaluating the learning curve is the availability of resources and community support for the technology you're considering. Established technologies often have extensive documentation, tutorials, and a large community of developers to turn to for help. Newer technologies, while potentially offering exciting features, may have more limited resources, which can impact the learning process and troubleshooting — it might be amazing at first until you have to code a full calendar by yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thinking long-term
&lt;/h3&gt;

&lt;p&gt;Lastly, consider also the long-term implications of your technology choice. My take on this is that you have to really be aware of stuff that has not released a stable version — things can change a lot and the last thing you want is having to write an entire project again just because all APIs changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considering the costs
&lt;/h2&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%2Fxc8a7k23hxkho5v877fl.gif" 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%2Fxc8a7k23hxkho5v877fl.gif" alt="https://media2.giphy.com/media/QC1ZO72PLaGFtRLTO7/giphy.gif?cid=7941fdc62ih188x01diozym9541wgr4nltfz608s1pvvd3bt&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another important aspect of the decision-making process is considering the costs. There is a lot of tooling out there that, although they might seem awesome, the infrastructure to host them easily might make you lose your mind.&lt;/p&gt;

&lt;p&gt;Try not to think here only in terms of monetary value too. If with one technology choice you might spend hours/days working on setting up the infra and with other is just commands, well, your (or your engineer’s) time is valuable and, every second you spend working on things that is not the product, is time flying by.&lt;/p&gt;




&lt;p&gt;For me, this is an awesome aspect of Encore, the sponsor of this article:&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%2Fhksrhy7flturtroouj16.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%2Fhksrhy7flturtroouj16.png" alt="Encore Logo" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of its standout features for me is the simplified infrastructure setup. Want to deploy things super quickly using their platform and paying something for it? The option is there. Want to self-host your docker images on your cheap 5$ VPS? There are docs on that too. &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%2Fttcym03bng6ovcwzh4hc.gif" 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%2Fttcym03bng6ovcwzh4hc.gif" alt="Encore platform GIF" width="480" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Easiness of deployment and separation of costs/concerns with clients are really important features (Encore sets up AWS/GCP infrastructure in your own — or your client's — account, for example), and, unfortunately, not every tech choice out there works on that, so, stay aware.&lt;/p&gt;

&lt;p&gt;A good rule of thumb on this is before coding and starting the project with a tech choice, give a quick overview of the deployment section (if it looks hard as hell, that might be a red flag).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/encoredev/encore" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⚡ Check out Encore ⚡&lt;/a&gt;
&lt;/p&gt;




&lt;p&gt;So yes, spare a thought on deployment and infrastructure costs and they might spare you a few pennies/dollars every month or so ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&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%2F2rvtbc9o9br0linoajw0.gif" 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%2F2rvtbc9o9br0linoajw0.gif" alt="https://media2.giphy.com/media/QuDkyRwpMt1o2KTojk/giphy.gif?cid=7941fdc6ths6zlk79k1t4i14mbza4yyg9ulg5yns1ucno0mn&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey! You got to the end!&lt;/p&gt;

&lt;p&gt;Well, I hope that you now find choosing the right tech stack a more exciting journey, and not an impossible task! Remember — it's all about finding what works best for you and your project. By evaluating your project requirements, considering the learning curve, and weighing the costs, you're well on your way to making an informed decision (which is the whole point here).&lt;/p&gt;

&lt;p&gt;Don't be afraid to explore new technologies, there’s a BUNCH of cool stuff being released every day for you to check out, but also don't underestimate the power of established tools listening to those same tech gurus that are not shipping software. If it delivers a good solution, matches you or your team's skills, and doesn’t cost you more than you can pay, you’re probably on the right path.&lt;/p&gt;

&lt;p&gt;So, roll up your sleeves, dive into the documentation, and start experimenting! Who knows? &lt;/p&gt;

&lt;p&gt;You might just find your new favorite tool or framework along the way.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>career</category>
    </item>
    <item>
      <title>30+ Awesome Repos For You To Start Contributing on Hacktoberfest</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Tue, 22 Oct 2024 07:01:00 +0000</pubDate>
      <link>https://forem.com/buildwebcrumbs/30-awesome-repos-for-you-to-start-contributing-on-hacktoberfest-3220</link>
      <guid>https://forem.com/buildwebcrumbs/30-awesome-repos-for-you-to-start-contributing-on-hacktoberfest-3220</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&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%2Fh0jknyuqtjl0mwcyurg0.gif" 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%2Fh0jknyuqtjl0mwcyurg0.gif" alt="https://media0.giphy.com/media/3ornk57KwDXf81rjWM/giphy.gif?cid=7941fdc64iasdz5i83kzutikn8gxt64tdeaz4zruoklijga7&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="453" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello there, dear reader! Before we begin, this article is largely inspired by the &lt;a href="https://github.com/MunGell/awesome-for-beginners" rel="noopener noreferrer"&gt;awesome-for-beginners&lt;/a&gt; repo and the &lt;a href="https://kentcdodds.com/blog/first-timers-only" rel="noopener noreferrer"&gt;first-timers-only&lt;/a&gt; blog post which are great sources to keep in mind too!&lt;/p&gt;

&lt;p&gt;Well, in the last few days, you might have seen a whole movement towards &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; contributions — an annual event that encourages developers worldwide to contribute to open-source projects throughout October — and I really think it’s an awesome way to get you going with a bunch of different things, from experience to best practices, and don’t worry: there’s still time to contribute! &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%2Fcukr1qi8aocygv4n9p98.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%2Fcukr1qi8aocygv4n9p98.png" alt="Hacktoberfest 2020 badge" width="772" height="288"&gt;&lt;/a&gt;&lt;/p&gt;
This was my first year contributing… I’ll probably write a little about my history with the event in other article though 👀



&lt;p&gt;In this article, we'll explore 30 awesome repositories — and I’ll choose one for you if you think &lt;a href="https://en.wikipedia.org/wiki/Analysis_paralysis" rel="noopener noreferrer"&gt;decision paralysis&lt;/a&gt; is taking the lead — that are perfect for contributing during this amazing event. Whether you're a seasoned developer or just starting out, there's something here for everyone and, to do that, I’ll try my best to sort those repos by interest! So, let’s dive in :)&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use This List &amp;amp; Tips for Successful Contributions
&lt;/h2&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%2Fumw0u0hus4r0doukj9m0.gif" 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%2Fumw0u0hus4r0doukj9m0.gif" alt="https://media0.giphy.com/media/8PBuys9pFhbQbd66xC/giphy.gif?cid=7941fdc6yz1bdj00d5my5p15jjt7r1cc30gs15ki6x3hj1si&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the past, I’ve also written an article on how to start contributing, in case you want a quick deep dive on it, you can find it &lt;a href="https://dev.to/wasp/contributing-to-tech-communities-how-open-source-can-land-you-a-job-and-get-you-out-of-the-skill-paradox-4ejh"&gt;here&lt;/a&gt;. But, here are the essential points to get successful contributions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Register yourself in Hacktoberfest:&lt;/strong&gt; It is &lt;strong&gt;a&lt;/strong&gt;lways important to remember to go to the &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; website and put your name up there 🚀&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read contribution and event guidelines:&lt;/strong&gt; Each project has its own set of guidelines (and so does &lt;a href="https://hacktoberfest.com/participation/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt;). Make sure to read and follow them carefully — in repos, they are generally in the README or CONTRIBUTING files, so, this is the first place to check!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with beginner-friendly issues:&lt;/strong&gt; Look for issues labeled as "good first issue" or "beginner-friendly" to get started and &lt;strong&gt;don't forget to comment/assign yourself to them&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write clear commit messages and communicate with project maintainers:&lt;/strong&gt; Your commit messages should clearly explain what changes you've made and why. A cool guide on that is &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt; (just in case the repo itself doesn’t have a convention regarding commit formatting). Unsure about how things work on the repo? Don't hesitate to ask questions!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create comprehensive pull requests:&lt;/strong&gt; When submitting a pull request, provide a clear description of your changes and any relevant context — always remember: there’s another human being on the other side of the screen and they have a ton of other Pull Requests to review, so, make it as easy as possible for them to go through your modifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, to use this list is a simple process: Go through the available categories, find one that you enjoy, follow the quick guide above, and go write some contributions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Paralyzed by too many decisions? I’ve chosen one for you.
&lt;/h2&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%2Ftr65jtl7ndvzhszsjl3b.gif" 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%2Ftr65jtl7ndvzhszsjl3b.gif" alt="Frontend AI" width="480" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, firstly, before we jump ahead in the categories itself, if you feel that you might get a little overwhelmed by all those repositories with different categories, I chose one for you to start contributing and overcoming the paralysis ;). It’s &lt;a href="https://tools.webcrumbs.org/frontend-ai" rel="noopener noreferrer"&gt;Frontend AI&lt;/a&gt; — a sponsor of this article, but also, a really really cool project and v0 alternative.&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%2Fa5s85ui2i6t8z9ez2t23.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%2Fa5s85ui2i6t8z9ez2t23.png" alt="How to Contribute" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s super simple to contribute, simply go to the &lt;a href="https://tools.webcrumbs.org/frontend-ai" rel="noopener noreferrer"&gt;Frontend AI&lt;/a&gt; page, build a quick template enjoying the help of AI-assisted code, submit it through the Hacktoberfest button, and wait for a review! &lt;/p&gt;

&lt;p&gt;The cool part here? You’re actually creating a reusable block of code that other people are going to be able to put on their websites with a simple click. To be fair, I still remember the proudness of delivering my first reusable component in a corporate environment and seeing it live, so, I hope you’d get the same feeling here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tools.webcrumbs.org/frontend-ai" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⚡ Check out Frontend AI ⚡&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  THE LIST:
&lt;/h2&gt;




&lt;p&gt;BTW, the really easy ones for you to start contributing are going to be marked with a ✅&lt;/p&gt;

&lt;h3&gt;
  
  
  Web Development
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/freeCodeCamp/freeCodeCamp" rel="noopener noreferrer"&gt;freeCodeCamp&lt;/a&gt;: An open-source codebase and curriculum for learning to code! What’s more delightful than contributing to learning? You can find more on &lt;a href="https://github.com/freeCodeCamp/freeCodeCamp/issues/56170" rel="noopener noreferrer"&gt;this issue&lt;/a&gt;. ✅&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/axios/axios" rel="noopener noreferrer"&gt;Axios&lt;/a&gt;: The old-school (but not so much) way of making requests.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/jestjs/jest" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;: Want to get your hand on the testing side of things? Check out Jest!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/strapi/strapi" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt;: Interested in Content Management Systems? This one is a beast!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/excalidraw/excalidraw" rel="noopener noreferrer"&gt;Excalidraw&lt;/a&gt;: Amazing project, I literally use this guy on an almost daily basis&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/you-dont-need/You-Dont-Need-JavaScript" rel="noopener noreferrer"&gt;You Don’t Need JavaScript&lt;/a&gt;: Great project to showcase the power of CSS by itself! Give it a look 😎&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/appwrite/appwrite" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt;: A really cool BaaS for you to go quickly on the backend side&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mobile Development
&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%2Fw0j8w88uz5q7hvh04qa5.gif" 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%2Fw0j8w88uz5q7hvh04qa5.gif" alt="https://media2.giphy.com/media/N9f6uA1nMWl3JFN5Oz/giphy.gif?cid=7941fdc6uh7fk7bxfcpkir84sxml7dw40w7364mk4fxoamwo&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/react-navigation/react-navigation" rel="noopener noreferrer"&gt;React Navigation&lt;/a&gt;: Routing and navigation for your React Native apps&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/openfoodfacts/smooth-app" rel="noopener noreferrer"&gt;Open Food Facts&lt;/a&gt;: Scan food products or their barcode to obtain data on ingredients, additives, and nutrition facts (this one hits home for me — I’m celiac, so it's super useful!) ✅&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fastlane/fastlane" rel="noopener noreferrer"&gt;Fastlane&lt;/a&gt;: App (iOS and Android) releases made easy.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/termux/termux-app" rel="noopener noreferrer"&gt;Termux&lt;/a&gt;: a terminal emulator application for Android OS extendible by a variety of packages.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NativeScript/NativeScript" rel="noopener noreferrer"&gt;NativeScript&lt;/a&gt;: Empowering JavaScript with native platform APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Science and Machine Learning
&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%2Fw1w1aat11cvvhqy5hk0b.gif" 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%2Fw1w1aat11cvvhqy5hk0b.gif" alt="https://media2.giphy.com/media/iPj5oRtJzQGxwzuCKV/giphy.gif?cid=7941fdc69qxx7ifmh8hndf5phit41kr9oyjovdue2ex4zs58&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/huggingface/transformers" rel="noopener noreferrer"&gt;Hugging Face&lt;/a&gt;: Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/JuliaLang/julia" rel="noopener noreferrer"&gt;Julia&lt;/a&gt;: The Julia programming language!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/gradio-app/gradio" rel="noopener noreferrer"&gt;Gradio&lt;/a&gt;: Build and share delightful machine-learning apps, all in Python. ✅&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/OpenBB-finance/OpenBB" rel="noopener noreferrer"&gt;OpenBB&lt;/a&gt;: Investment Research for Everyone, Everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/scrapy/scrapy" rel="noopener noreferrer"&gt;scrapi&lt;/a&gt;: This one doesn’t necessarily relate to data science and all, but, since scraping things is often a middle step, I think you might find it important too!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DevOps and Infrastructure
&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%2Fl0f2rt1rav0wp8pju4qh.gif" 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%2Fl0f2rt1rav0wp8pju4qh.gif" alt="https://media4.giphy.com/media/0T0FUiZl51VPCLsqLR/giphy.gif?cid=7941fdc6qyf6mer6tijekbftthsxw7xsue6mcgyv30bgs1om&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/kubernetes/kubernetes" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;: Production-Grade Container Scheduling and Management — one of the greatest communities out there ;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/grafana/grafana" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt;: Because Infrastructure needs observability ✅&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/go-gitea/gitea" rel="noopener noreferrer"&gt;Gitea&lt;/a&gt;: Self-hosted git, amazing project.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/external-secrets/external-secrets" rel="noopener noreferrer"&gt;external-secrets&lt;/a&gt;: reads information from a third-party service like AWS Secrets Manager and automatically injects the values as Kubernetes Secrets.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/prometheus/prometheus" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt;: The Prometheus monitoring system and time series database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Miscellaneous/Cross-platform
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/anuraghazra/github-readme-stats" rel="noopener noreferrer"&gt;GitHub Readme Stats&lt;/a&gt;: A cool and awesome way to make your README look great!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/auth0" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;: Interested in authentication? Auth0 is a beast.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/home-assistant/core" rel="noopener noreferrer"&gt;Home Assistant&lt;/a&gt;: Open-source home automation that puts local control and privacy first.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/EbookFoundation/free-programming-books" rel="noopener noreferrer"&gt;Free Programming Books&lt;/a&gt;: Freely available books! ✅&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Cockatrice/Cockatrice" rel="noopener noreferrer"&gt;Cockatrice&lt;/a&gt;: Cross-platform virtual tabletop! Couldn’t make a list without a game related thing ;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/kamranahmedse/developer-roadmap" rel="noopener noreferrer"&gt;Developer Roadmap&lt;/a&gt;: Making a career path is hard, this, makes you easily navigate them.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/JollyJolli/HacktoberWall" rel="noopener noreferrer"&gt;HacktoberWall&lt;/a&gt;: A simple webpage, for you to put your name on and make a quick win! ✅&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hoppscotch/hoppscotch" rel="noopener noreferrer"&gt;hoppscotch&lt;/a&gt;: An open-source alternative to Postman and Insomnia!&lt;/li&gt;
&lt;li&gt;Awesomes: This one is a general idea — have a cool resource of some language? Share it in the awesome , e.g. &lt;a href="https://github.com/avelino/awesome-go" rel="noopener noreferrer"&gt;Awesome Go&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&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%2Fdzsyiowyc9bf7i4tbg0w.gif" 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%2Fdzsyiowyc9bf7i4tbg0w.gif" alt="https://media4.giphy.com/media/NxckxXIAzumvCP1mUj/giphy.gif?cid=7941fdc6fdvps91whqxdotdtsie88eakrwx1cp7skug6m67e&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey! You managed to get to the end and I hope that you found a cool/or a few cool repos to contribute to! It’s an awesome way to give a little something back to the community and feel free to make that Holopin that you’ll get shine!&lt;/p&gt;

&lt;p&gt;Remember, open-source contributions are not just about code. They're about collaboration, learning, and making a positive impact on the global developer community — so please, take your time to grow and collaborate, showcase your work, and fly up high.&lt;/p&gt;

&lt;p&gt;So there’s that. Take this to inspire you to, while we are at the end of October, get those last days to give those repos some love and make the world a cooler place!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Beginner’s Guide to Freelancing</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Tue, 10 Sep 2024 19:24:43 +0000</pubDate>
      <link>https://forem.com/llxd/beginners-guide-to-freelancing-3m5i</link>
      <guid>https://forem.com/llxd/beginners-guide-to-freelancing-3m5i</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&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%2Fedlu8wfvupzd4cmj3463.gif" 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%2Fedlu8wfvupzd4cmj3463.gif" alt="https://media2.giphy.com/media/7GkvffN8RiThRLXDSP/giphy.gif?cid=7941fdc6jkqpn6c7ctkh725p0echmou2ujrpnyazxcnow4h3&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello there!&lt;/p&gt;

&lt;p&gt;If you’re reading this, I assume that: you’re beginning to freelance (or want to) or you’re just looking for some tips in the process itself. Currently, I’m sitting at 6+ years of freelancing, and the intent of this article is to try to guide you through the different learnings I gained throughout those years.&lt;/p&gt;

&lt;p&gt;Honestly, I can’t complain about the things I gained throughout those years — I started mostly for the experience (but, I’m not gonna lie that the extra cash always felt great) and I ended up with a bunch of different learnings besides sole experience: From developing a bunch of different ideas to communicating better with customers and even learning things I didn’t had an opportunity to put in practice.&lt;/p&gt;

&lt;p&gt;These for me, are the greatest selling points for freelancing.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Getting Started: Customers
&lt;/h2&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%2Fyb9pyfamg5xg2zsfcg3j.gif" 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%2Fyb9pyfamg5xg2zsfcg3j.gif" alt="Literally the description the average customer is going to give you about what they want" width="480" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

Literally the description the average customer is going to give you about what they want




&lt;p&gt;First of all, we have to learn a little bit about customers. Here, we have 3 important topics to cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finding and Securing&lt;/li&gt;
&lt;li&gt;Negotiating&lt;/li&gt;
&lt;li&gt;Legal stuff&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Finding and Securing Clients
&lt;/h3&gt;

&lt;p&gt;Let’s start by going over the first one: Finding and Securing Clients. This can actually be pretty hard — when I started freelancing I didn’t have a clue on where to actually find a customer, so, I started going into websites like &lt;a href="https://www.workana.com/pt" rel="noopener noreferrer"&gt;Workana&lt;/a&gt; and &lt;a href="https://fiverr.com/" rel="noopener noreferrer"&gt;Fiverr&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Did it work? No. Not only did I never get a client from those types of websites, but, to be honest with you here, that type of website always made me feel that the work I was doing creating software was cheap and disposable. To be fair, there are a bunch of developers out there who actually make money on this, so, maybe, it was only a misfortune on my end.&lt;/p&gt;

&lt;p&gt;After that, I started to go through my friends to see if anyone knew someone who was looking for a developer, and in less than 2 days I had my first customer asking for a website, not a direct friend, but a friend of a friend. After finishing the work with this first client, he felt that the work was really good and spread the word — ever since I’ve never been without a freelance gig.&lt;/p&gt;

&lt;p&gt;Here’s my first tip for you then: Don’t ignore mouth-to-mouth and organic reach. It’s tremendously powerful and can get you a long way! Ask your network and soon enough, people will start finding you. Don’t have a network? &lt;strong&gt;Start to build one&lt;/strong&gt; (&lt;a href="https://dev.to/buildwebcrumbs/creating-a-personal-brand-how-to-sell-yourself-as-a-developer-52po"&gt;here’s a reference&lt;/a&gt; for you to start and you can try those websites while that isn’t ready).&lt;/p&gt;

&lt;p&gt;A second tip? Don't necessarily accept your client's idea. They think they'd like an app, but maybe, the person would be better suited with a web application. You're the specialist, use your expertise (or reach out to others to better determine this) what is the best course here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Negotiating
&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%2F8j5mnko1zrh74u3mdq78.gif" 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%2F8j5mnko1zrh74u3mdq78.gif" alt="https://media0.giphy.com/media/xT1Ra159XCvq33VvqM/giphy.gif?cid=7941fdc621npdwvr7ffzgspmxdyjhnjgwtp4jvh0yr5zxc44&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It finally happened, you found a client and they want software from you! Congrats! Now we jump to the second part which is negotiating. This is a crucial skill for you to gain as a software engineer (if you’d like to learn more, you can find more content about communication &lt;a href="https://dev.to/llxd/how-to-deal-with-people-communication-5gef"&gt;here&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Every single deadline you’re going to have is impacted by the capacity of negotiation of yourself and the people above you, in a corporate world.&lt;/p&gt;

&lt;p&gt;Usually, when you talk to a client, they want a budget idea from you as quickly as possible — and here’s where things go bad, software time is HARD to estimate, so, if you rush things out here, there are only two possible outcomes: you overbudget it, and the client won’t like it or you underbudget it and you’re going to work for free. &lt;/p&gt;

&lt;p&gt;Besides budget, they also want to know dates and time ideas, because they don’t have a clue if their project is going to take a week or a year and the cycle repeats, only two possible outcomes, or you’re going to cut short, having to work way more than intended or you’re going to put too much time for the client to be comfortable with.&lt;/p&gt;

&lt;p&gt;Your job here is one: simply calm the heck out of this other anxious person you’re dealing with. They want to know things, and they want to know them fast, you just have to remind them that this is an engineering process and you’ll have to make some refinements before coming to the budgets and dates with precision.&lt;/p&gt;

&lt;p&gt;Sometimes, you’ll find some clients that are especially anxious about wanting to know things, here, if you have done some freelancing before, you can try to eyeball a range to make them more calm. If you’ve never made freelancing and you feel that this client is this edge case, ask someone with freelancing experience how much you should charge and they’ll help you out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Legal Stuff
&lt;/h3&gt;

&lt;p&gt;Here’s a good thing if your customer is acquainted with you in some manner: you’re probably not going to go deep into the legal stuff! But, honestly, at least some contractual idea is generally necessary — everyone is great at demanding stuff, but not everyone is great at paying for the stuff they demand. Haven’t made a contract and your money didn’t arrive? Well, that’s bad — at least you learned something. The funniest implementation of a solution to this problem in my opinion is this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kleampa/not-paid" rel="noopener noreferrer"&gt;kleampa/not-paid: Client did not pay? Add opacity to the body tag and decrease it every day until their site completely fades away (github.com)&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It’s important for you to get some sense into your country's regulations for taxes and informal jobs like this too. You don’t have to dig deep initially, but just learn a little bit about how things work and which taxes if any you should pay for.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Project Management and Engineering
&lt;/h2&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%2Fazawtjhdh41xtd0d3ik6.gif" 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%2Fazawtjhdh41xtd0d3ik6.gif" alt="https://media1.giphy.com/media/gQm37vKLwkUVjOvVmp/giphy.gif?cid=7941fdc6f9hhprin3ago5fzqxpvkvbcaeooimygscgg2dxr6&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we've covered the basics of finding clients and handling the business side of freelancing, let's dive into the core of what makes a successful freelance software engineer: effective project management and engineering practices. As a freelancer, you're not just responsible for writing code; you're also in charge of managing the entire project lifecycle. This includes several key aspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding and defining project requirements&lt;/li&gt;
&lt;li&gt;Creating accurate time and cost estimations&lt;/li&gt;
&lt;li&gt;Breaking down projects into manageable tasks&lt;/li&gt;
&lt;li&gt;Using project management tools and methodologies&lt;/li&gt;
&lt;li&gt;Show the progress weekly or recurrently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usually, while in university, we have a whole 6-month discipline to learn about software engineering processes and how to do precisely that. Don’t have 6 months? Here’s the small version:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Divide the whole project into a set of major milestones&lt;/li&gt;
&lt;li&gt;Break those milestones into features to make those milestones possible&lt;/li&gt;
&lt;li&gt;Go deep into those features and learn what your client wants&lt;/li&gt;
&lt;li&gt;Try to estimate those features in hours/days of work&lt;/li&gt;
&lt;li&gt;If you have some experienced people nearby, ask them to make revisions in your estimations considering YOUR skill level&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;PLEASE, plan things out. A &lt;a href="https://www.engprax.com/post/268-higher-failure-rates-for-agile-software-projects-study-finds" rel="noopener noreferrer"&gt;recent study&lt;/a&gt; found that projects that had requirements clear before development started were 97% more likely to succeed than those that didn’t.&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%2Fwxoms8d2hzct1uin3wwk.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%2Fwxoms8d2hzct1uin3wwk.png" alt="Engineer Reference" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After estimating the features, add some extra time for the chaos of the world, bugs, or revisions. This practice helps manage client expectations and ensures you have room to deliver high-quality work — this is the goal since this is what is going to propel your organic reach. &lt;/p&gt;

&lt;p&gt;Remember: it's always better to under-promise and over-deliver. Not the other way around.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. I made a tool to help: Founders Kit
&lt;/h2&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%2F12w9xi3r14cw9qkrk7qg.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%2F12w9xi3r14cw9qkrk7qg.png" alt="Founders Kit" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Throughout the years of freelancing, I tried a bunch of different tools to help me actually organize my process. It took a lot of trial and error only to realize that no tool perfectly fit my needs — in some cases, they were too complex, bringing tons of functionalities that I didn’t use, in others, they didn’t have some essential stuff. &lt;/p&gt;

&lt;p&gt;The great part of this is that I’m an engineer! So, throughout the past month, I worked hard to create a solution to help manage the business side of this. It’s called Founders Kit and I’d love it if you could help us on &lt;a href="https://www.producthunt.com/posts/founderskit-2" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; and check it out ;D&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Conclusion
&lt;/h2&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%2Fts4gr3bb0u4c5h6rzn2u.gif" 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%2Fts4gr3bb0u4c5h6rzn2u.gif" alt="https://media1.giphy.com/media/VFMIvNlKndpf2gO5Xp/giphy.gif?cid=7941fdc6susv7t2js3spr3lrn9qf558a61mp3y2v33loioim&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="478" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey! You made it to the end. I hope that you have started to realize how freelancing in software engineering can be a rewarding and challenging career path, which can earn you some extra money and grant you some really cool experiences. &lt;/p&gt;

&lt;p&gt;By following the guidelines outlined in this guide - from finding and securing clients, to negotiating effectively, managing projects, and utilizing tools like Founders Kit - you'll be well-equipped to start your freelancing journey.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How To Add Auth With Lucia To Your React/Next.js App - A Step By Step Guide</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Tue, 20 Aug 2024 12:11:19 +0000</pubDate>
      <link>https://forem.com/wasp/how-to-add-auth-with-lucia-to-your-reactnextjs-app-a-step-by-step-guide-114e</link>
      <guid>https://forem.com/wasp/how-to-add-auth-with-lucia-to-your-reactnextjs-app-a-step-by-step-guide-114e</guid>
      <description>&lt;p&gt;Although authentication is one of the most common web app features, there are so many different ways to go about it, which makes it a very non-trivial task. In this post, I will share my personal experience using Lucia - a modern, framework-agnostic authentication library that has been getting, deservedly so, a lot of love from the community in recent months.&lt;/p&gt;

&lt;p&gt;First, I will demonstrate how you can implement it within your Next.js application through a step-by-step guide you can follow. It will require a fair amount of code and configuration, but the process itself is quite straightforward.&lt;/p&gt;

&lt;p&gt;Secondly, we’ll see how to achieve the same with &lt;a href="https://wasp-lang.dev/" rel="noopener noreferrer"&gt;Wasp&lt;/a&gt; in just a few lines of code. Wasp is a batteries-included, full-stack framework for React &amp;amp; Node.js that uses Lucia under the hood to implement authentication. It runs fully on your infrastructure and is 100% open-source and free.&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%2Fb2qpg6praoxnbfreg2k5.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%2Fb2qpg6praoxnbfreg2k5.png" alt="Wasp Auth" width="612" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Lucia?
&lt;/h2&gt;

&lt;p&gt;When it comes to adding authentication to your applications, there are several popular solutions available. For instance, &lt;a href="https://clerk.com/" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; offers a paid service, while &lt;a href="https://next-auth.js.org/" rel="noopener noreferrer"&gt;NextAuth.js&lt;/a&gt; is an open-source solution alongside &lt;a href="https://lucia-auth.com/" rel="noopener noreferrer"&gt;Lucia&lt;/a&gt;, which has become quite popular recently. &lt;/p&gt;

&lt;p&gt;These tools provide robust features, but committing to third-party services — which not only adds another layer of complexity but also have paid tiers you have to keep an eye on — might be an overkill for a small project. In-house solutions keep things centralized but leave it to a developer to implement some of the mentioned features.&lt;/p&gt;

&lt;p&gt;In our case, Lucia has proved to be a perfect middle ground - it’s not a third-party service and does not require a dedicated infrastructure, but it also provides a very solid foundation that’s easy to build upon.&lt;/p&gt;

&lt;p&gt;Now, let’s dive into a step-by-step guide on how to implement your own authentication with Next.js and Lucia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setting up Next.js
&lt;/h3&gt;

&lt;p&gt;First, create a new Next.js project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest my-nextjs-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-nextjs-app
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Install Lucia
&lt;/h3&gt;

&lt;p&gt;Next, install Lucia:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;lucia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Set up Authentication
&lt;/h3&gt;

&lt;p&gt;Create an &lt;code&gt;auth&lt;/code&gt; file in your project and add the necessary files for Lucia to be imported and initialized. It has a bunch of adapters for different databases, and you can check them all &lt;a href="https://lucia-auth.com/database/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In this example, we’re going to use SQLite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/auth.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;Lucia&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="s2"&gt;lucia&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;BetterSqlite3Adapter&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="s2"&gt;@lucia-auth/adapter-sqlite&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;adapter&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;BetterSQLite3Adapter&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="c1"&gt;// your adapter&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lucia&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;Lucia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this sets cookies with super long expiration&lt;/span&gt;
    &lt;span class="c1"&gt;// since Next.js doesn't allow Lucia to extend cookie expiration when rendering pages&lt;/span&gt;
    &lt;span class="na"&gt;expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// set to `true` when using HTTPS&lt;/span&gt;
      &lt;span class="na"&gt;secure&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&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;span class="c1"&gt;// To get some good Typescript support, add this!&lt;/span&gt;
&lt;span class="nx"&gt;declare&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lucia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Register&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;Lucia&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;lucia&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;
  
  
  Step 4: Add User to DB
&lt;/h3&gt;

&lt;p&gt;Let’s add a database file to contain our schemas for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/db.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sqlite&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;better-sqlite3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sqlite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main.db&lt;/span&gt;&lt;span class="dl"&gt;"&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;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`CREATE TABLE IF NOT EXISTS user (
    id TEXT NOT NULL PRIMARY KEY,
    github_id INTEGER UNIQUE,
    username TEXT NOT NULL
)`&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;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`CREATE TABLE IF NOT EXISTS session (
    id TEXT NOT NULL PRIMARY KEY,
    expires_at INTEGER NOT NULL,
    user_id TEXT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES user(id)
)`&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;DatabaseUser&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;username&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;github_id&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Implement Login and Signup
&lt;/h3&gt;

&lt;p&gt;To make this happen, we firstly have to create a GitHub OAuth app. This is relatively simple, you create it, add the necessary ENVs and callback URLs into your application and you’re good to go. You can &lt;a href="https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app" rel="noopener noreferrer"&gt;follow GitHub docs&lt;/a&gt; to check how to do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//.env.local&lt;/span&gt;
&lt;span class="nx"&gt;GITHUB_CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;github&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="nx"&gt;GITHUB_CLIENT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;github&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, it’s a matter of adding login and signup functionalities to your pages, so, let’s do that real quick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// login/page.tsx&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;validateRequest&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="s2"&gt;@/lib/auth&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;redirect&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="s2"&gt;next/navigation&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="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;Page&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;user&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="nf"&gt;validateRequest&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;user&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="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign in&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/login/github"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign in with GitHub&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;p&gt;After adding the page, we also have to add the login redirect to GitHub and the callback that’s going to be called. Let’s first add the login redirect with the authorization URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// login/github/route.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;generateState&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="s2"&gt;arctic&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;github&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="s2"&gt;../../../lib/auth&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;cookies&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="s2"&gt;next/headers&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&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;Response&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateState&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;url&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;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createAuthorizationURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;cookies&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;github_oauth_state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;secure&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lax&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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;And finally, the callback (which is what we actually add in GitHub OAuth):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// login/github/callback/route.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;github&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lucia&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="s2"&gt;@/lib/auth&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;db&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="s2"&gt;@/lib/db&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;cookies&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="s2"&gt;next/headers&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;OAuth2RequestError&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="s2"&gt;arctic&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;generateId&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="s2"&gt;lucia&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DatabaseUser&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="s2"&gt;@/lib/db&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&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;Response&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;url&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&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;storedState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;github_oauth_state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&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;code&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;storedState&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;storedState&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokens&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;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validateAuthorizationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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;githubUserResponse&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/user&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="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="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accessToken&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="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;githubUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GitHubUser&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;githubUserResponse&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingUser&lt;/span&gt; &lt;span class="o"&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;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM user WHERE github_id = ?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;githubUser&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;as&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;DatabaseUser&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;existingUser&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;session&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;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingUser&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSessionCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&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="nf"&gt;cookies&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;sessionCookie&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;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&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;new&lt;/span&gt; &lt;span class="nc"&gt;Response&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;302&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="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&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;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT INTO user (id, github_id, username) VALUES (?, ?, ?)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;githubUser&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;githubUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&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;session&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;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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;sessionCookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSessionCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&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="nf"&gt;cookies&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;sessionCookie&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;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&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;new&lt;/span&gt; &lt;span class="nc"&gt;Response&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;302&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="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;OAuth2RequestError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bad_verification_code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// invalid code&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;GitHubUser&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;login&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other important thing here is that, now, we’re going with GitHub OAuth, but, generally, these libraries contain a bunch of different login providers (including simple username and password), so it’s usually just a pick and choose if you want to add other providers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/auth.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;Lucia&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="s2"&gt;lucia&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;BetterSqlite3Adapter&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="s2"&gt;@lucia-auth/adapter-sqlite&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;db&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="s2"&gt;./db&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;cookies&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="s2"&gt;next/headers&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;cache&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="s2"&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;GitHub&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="s2"&gt;arctic&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&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="s2"&gt;lucia&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DatabaseUser&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="s2"&gt;./db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// these two lines here might be important if you have node.js 18 or lower. &lt;/span&gt;
&lt;span class="c1"&gt;// you can check Lucia's documentation in more detail if that's the case &lt;/span&gt;
&lt;span class="c1"&gt;// (https://lucia-auth.com/getting-started/nextjs-app#polyfill)&lt;/span&gt;
&lt;span class="c1"&gt;// import { webcrypto } from "crypto";&lt;/span&gt;
&lt;span class="c1"&gt;// globalThis.crypto = webcrypto as Crypto;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&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;BetterSqlite3Adapter&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lucia&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;Lucia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;secure&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&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="na"&gt;getUserAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;githubId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;github_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&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="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lucia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Register&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;Lucia&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;DatabaseUserAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DatabaseUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&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="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;const&lt;/span&gt; &lt;span class="nx"&gt;validateRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&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="nl"&gt;session&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="o"&gt;&amp;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sessionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionCookieName&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&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;sessionId&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;user&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="na"&gt;session&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validateSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// next.js throws when you attempt to set cookie when rendering page&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fresh&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;sessionCookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSessionCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&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="nf"&gt;cookies&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;sessionCookie&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;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&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;sessionCookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createBlankSessionCookie&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;cookies&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;sessionCookie&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;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&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;catch&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;result&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;github&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;GitHub&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;GITHUB_CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_CLIENT_SECRET&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Protect Routes
&lt;/h3&gt;

&lt;p&gt;After adding all that stuff to make the login properly work, we just have to ensure that routes are protected by checking authentication status — in this case, this is a simple page that shows username, id and a button in case signed in, and redirects to /login, where the user will complete the login above through a form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validateRequest&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="s2"&gt;@/lib/auth&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;redirect&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="s2"&gt;next/navigation&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;cookies&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="s2"&gt;next/headers&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="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;Page&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;user&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="nf"&gt;validateRequest&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;user&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="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hi, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Your user ID is &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign out&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logout&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;ActionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;session&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="nf"&gt;validateRequest&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;session&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;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unauthorized&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="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lucia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createBlankSessionCookie&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;cookies&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;sessionCookie&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;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sessionCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ActionResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Piece of cake, isn’t it? Well, not really. &lt;/p&gt;

&lt;p&gt;Let’s recap which steps were necessary to actually make this happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up your app.&lt;/li&gt;
&lt;li&gt;Add Lucia.&lt;/li&gt;
&lt;li&gt;Set up authentication.&lt;/li&gt;
&lt;li&gt;Add User to DB.&lt;/li&gt;
&lt;li&gt;Obtain GitHub OAuth credentials and configure your environment variables.&lt;/li&gt;
&lt;li&gt;Create some util functions.&lt;/li&gt;
&lt;li&gt;Add Login and Sign up routes, with custom made components.&lt;/li&gt;
&lt;li&gt;Finally, create a protected route.&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%2F0g3lx0fsxqvqx3ygacxs.gif" 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%2F0g3lx0fsxqvqx3ygacxs.gif" alt="https://media2.giphy.com/media/3ofSBnYbEPePeigIMg/giphy.gif?cid=7941fdc6x77sivlvr6hs2yu5aztvwjvhgugv6b718mjanr2h&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Honestly, when trying to create something cool &lt;strong&gt;FAST&lt;/strong&gt;, repeating these steps and debugging a few logical problems here and there that always occur can feel a little bit frustrating. Soon, we’ll take a look at Wasp’s approach to solving that same problem and we’ll be able to compare how much easier Wasp’s auth implementation process is.&lt;/p&gt;

&lt;p&gt;In case you want to check the whole code for this part, &lt;a href="https://github.com/lucia-auth/examples/tree/main/nextjs-app/github-oauth" rel="noopener noreferrer"&gt;Lucia has an example repo&lt;/a&gt; (that is the source of most of the code shown), so, you can check it out if you’d like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wasp Implementation
&lt;/h2&gt;

&lt;p&gt;Now, let’s go through how we can achieve the same things with Wasp 🐝. Although it still uses Lucia in the background, Wasp takes care of all the heavy-lifting for you, making the process much quicker and simpler. Let’s check out the developer experience for ourselves.&lt;/p&gt;

&lt;p&gt;Before we just into it, in case you’re more of a visual learner, here’s a 1-minute video showcasing auth with Wasp.&lt;/p&gt;

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

&lt;p&gt;As seen in the video, Wasp is a framework for building apps with the benefits of using a configuration file to make development easier. It handles many repetitive tasks, allowing you to focus on creating unique features. In this tutorial, we’ll also learn more about the Wasp config file and see how it makes setting up authentication simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Wasp Project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://get.wasp-lang.dev/installer.sh | sh
wasp new my-wasp-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-wasp-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Add the User entity into our DB
&lt;/h3&gt;

&lt;p&gt;As simple as defining the &lt;code&gt;app.auth.userEntity&lt;/code&gt; entity in the &lt;code&gt;schema.prisma&lt;/code&gt; file and running some migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;id&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoincrement&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;   &lt;span class="nb"&gt;String&lt;/span&gt;   &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;unique&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
  &lt;span class="c1"&gt;// Add your own fields below&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Define Authentication
&lt;/h3&gt;

&lt;p&gt;In your main Wasp configuration, add the authentication provider you want for your app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//main.wasp&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="nx"&gt;myApp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;wasp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^0.14.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;userEntity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 2. Enable Github Auth&lt;/span&gt;
      &lt;span class="nl"&gt;gitHub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;onAuthFailedRedirectTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after that, just run in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wasp db migrate-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Get your GitHub OAuth credentials and app running
&lt;/h3&gt;

&lt;p&gt;This part is similar for both frameworks, you can follow the documentation GitHub provides here to do so: &lt;a href="https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app" rel="noopener noreferrer"&gt;Creating an OAuth app - GitHub Docs&lt;/a&gt;. For wasp app, the callback urls are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;While developing: &lt;code&gt;http://localhost:3001/auth/github/callback&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;After deploying: &lt;code&gt;https://your-server-url.com/auth/github/callback&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that, get your secrets and add it to the env file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//.env.server&lt;/span&gt;
&lt;span class="nx"&gt;GITHUB_CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;github&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="nx"&gt;GITHUB_CLIENT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;github&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Add the routes and pages
&lt;/h3&gt;

&lt;p&gt;Now, let’s simply add some routing and the page necessary for login — the process is way easier since Wasp has pre-built Login and Signup Forms, we can simply add those directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.wasp&lt;/span&gt;

&lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="nx"&gt;SignupRoute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SignupPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="nx"&gt;SignupPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;component&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;SignupPage&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="s2"&gt;@src/SignupPage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="nx"&gt;LoginRoute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoginPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="nx"&gt;LoginPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;component&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;LoginPage&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="s2"&gt;@src/LoginPage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/LoginPage.jsx&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;Link&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-router-dom&lt;/span&gt;&lt;span class="dl"&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;LoginForm&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;wasp/client/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoginPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;400px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoginForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        I don't have an account yet (&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/signup"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;go to signup&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;).
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/SignupPage.jsx&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;Link&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-router-dom&lt;/span&gt;&lt;span class="dl"&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;SignupForm&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;wasp/client/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SignupPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;400px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SignupForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        I already have an account (&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;go to login&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;).
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;p&gt;And finally, for protecting routes, is as simple as changing it in &lt;code&gt;main.wasp&lt;/code&gt; adding &lt;strong&gt;&lt;code&gt;authRequired: true&lt;/code&gt;&lt;/strong&gt; , so, we can simply add it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.wasp&lt;/span&gt;
&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="nx"&gt;MainPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@src/pages/Main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;authRequired&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’d like to check this example in more depth, feel free to check this repo here: &lt;a href="https://github.com/wasp-lang/wasp/tree/release/examples/todo-typescript" rel="noopener noreferrer"&gt;wasp/examples/todo-typescript at release · wasp-lang/wasp (github.com)&lt;/a&gt;.&lt;br&gt;
Other great place to check is their documentation, which can be found &lt;a href="https://wasp-lang.dev/docs/auth/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;. It covers most of what I said here, and even more (e.g. the awesome new &lt;a href="https://wasp-lang.dev/docs/auth/auth-hooks" rel="noopener noreferrer"&gt;hooks&lt;/a&gt; that came with Wasp v0.14)&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%2Ffpbyr7cyxoz6rtfbcpjx.gif" 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%2Ffpbyr7cyxoz6rtfbcpjx.gif" alt="https://media4.giphy.com/media/nDSlfqf0gn5g4/giphy.gif?cid=7941fdc6oxsddr7p8rjsuavcyq7ugiad8iqdu1ei25urcge4&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="500" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Way easier, isn’t it? Let’s review the steps we took to get here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up the project.&lt;/li&gt;
&lt;li&gt;Add the User entity to the database.&lt;/li&gt;
&lt;li&gt;Define authentication in the main Wasp configuration.&lt;/li&gt;
&lt;li&gt;Obtain GitHub OAuth credentials and configure your environment variables.&lt;/li&gt;
&lt;li&gt;Add routes and pages for login and signup with pre-built, easy-to-use components.&lt;/li&gt;
&lt;li&gt;Protect routes by specifying &lt;code&gt;authRequired&lt;/code&gt; in your configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Customizing Wasp Auth
&lt;/h3&gt;

&lt;p&gt;If you need more control and customization over the authentication flow, Wasp provides Auth hooks that allow you to tailor the experience to your app's specific needs. These hooks enable you to execute custom code during various stages of the authentication process, ensuring that you can implement any required custom behavior.&lt;/p&gt;

&lt;p&gt;For more detailed information on using Auth hooks with Wasp, visit the &lt;a href="https://wasp-lang.dev/docs/auth/auth-hooks" rel="noopener noreferrer"&gt;Wasp documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bonus Section: Adding Email/Password Login with Wasp and Customizing Auth
&lt;/h3&gt;

&lt;p&gt;Now let’s imagine we want to add email and password authentication — with all the usual features we’d expect that would follow this login method (e.g. reset password, email verification, etc.). &lt;/p&gt;

&lt;p&gt;With Wasp, all we have to do is add a few lines to your main.wasp file, so, simply updating your Wasp configuration to include email/password authentication makes it work straight out of the box!&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%2Fxd1h9dqiqwoplsjv5fmu.gif" 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%2Fxd1h9dqiqwoplsjv5fmu.gif" alt="https://wasp-lang.dev/img/auth-ui/auth-demo-compiler.gif" width="1028" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wasp will handle the rest, also updating UI components and ensuring a smooth and secure authentication flow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//main.wasp&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="nx"&gt;myApp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;wasp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^0.14.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Specify the User entity&lt;/span&gt;
    &lt;span class="nl"&gt;userEntity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 2. Enable Github Auth&lt;/span&gt;
      &lt;span class="nl"&gt;gitHub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 3. Specify the email from field&lt;/span&gt;
        &lt;span class="nl"&gt;fromField&lt;/span&gt;&lt;span class="p"&gt;:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My App Postman&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello@itsme.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// 4. Specify the email verification and password reset options&lt;/span&gt;
        &lt;span class="nx"&gt;emailVerification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;clientRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmailVerificationRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//this route/page should be created&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;passwordReset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;clientRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PasswordResetRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//this route/page should be created&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// Add an emailSender -- Dummy just logs to console for dev purposes&lt;/span&gt;
        &lt;span class="c1"&gt;// but there are a ton of supported providers :D&lt;/span&gt;
        &lt;span class="nx"&gt;emailSender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Dummy&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="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;onAuthFailedRedirectTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementing this in Next.js with Lucia would take a lot more work, involving a bunch of different stuff from actually sending the emails, to generating the verification tokens and more. They reference this &lt;a href="https://lucia-auth.com/guides/email-and-password/email-verification-links" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but again, Wasp’s Auth makes the whole process way easier, handling a bunch of the complexity for us while also giving a bunch of other UI components, ready to use, to ease the UI details (e.g. &lt;code&gt;VerifyEmailForm&lt;/code&gt;, &lt;code&gt;ForgotPasswordForm&lt;/code&gt; and, &lt;code&gt;ResetPasswordForm&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The whole point here is the difference in time and developer experience in order to implement the same scenarios. For the Next.js project with Lucia, you will spend at least a few hours implementing everything if you’re going all by yourself. That same experience translates to no more than 1 hour with Wasp. What to do with the rest of the time? &lt;strong&gt;Implement the important stuff your particular business requires!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Can you show us your support?
&lt;/h2&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%2Fhi2rljztbt9xp8ldhzbw.gif" 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%2Fhi2rljztbt9xp8ldhzbw.gif" alt="https://media2.giphy.com/media/l0MYAs5E2oIDCq9So/giphy.gif?cid=7941fdc6l6i66eq1dc7i5rz05nkl4mgjltyv206syb0o304g&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="500" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you interested in more content like this? Sign up for &lt;a href="https://wasp-lang.dev/#signup" rel="noopener noreferrer"&gt;our newsletter&lt;/a&gt; and give us &lt;a href="https://www.github.com/wasp-lang/wasp" rel="noopener noreferrer"&gt;a star on GitHub&lt;/a&gt;! We need your support to keep pushing our projects forward 😀&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&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%2Fjw98bimx9effqyhr8h7t.gif" 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%2Fjw98bimx9effqyhr8h7t.gif" alt="https://media2.giphy.com/media/l1AsKaVNyNXHKUkUw/giphy.gif?cid=7941fdc6u6vp4j2gpjfuizupxlvfdzskl03ncci2e7jq17zr&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think that if you’re a developer who wants to get things done, you probably noted the significant difference in complexity levels of both of those implementations. &lt;/p&gt;

&lt;p&gt;By reducing boilerplate and abstracting repetitive tasks, Wasp allows developers to focus more on building unique features rather than getting bogged down by authentication details. This can be especially beneficial for small teams or individual developers aiming to launch products quickly.&lt;/p&gt;

&lt;p&gt;Of course, generally when we talk abstractions, it always comes with the downside of losing the finesse of a more personal implementation. In this case, Wasp provides a bunch of stuff for you to implement around and uses Lucia on the background, so the scenario where there’s a mismatch of content implementation is highly unlikable to happen.&lt;/p&gt;

&lt;p&gt;In summary, while implementing your own authentication with Next.js and Lucia provides complete control and customization, it can be complex and time-consuming. On the other hand, using a solution like Wasp simplifies the process, reduces code length, and speeds up development. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>7 Steps To Become A Prompt Engineer</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Wed, 14 Aug 2024 09:40:42 +0000</pubDate>
      <link>https://forem.com/latitude/7-steps-to-become-a-prompt-engineer-4am8</link>
      <guid>https://forem.com/latitude/7-steps-to-become-a-prompt-engineer-4am8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello there, dear reader! If you’re looking for an article where you’ll actually find a DOABLE guide for getting somewhere with prompt engineering, you’ve come to the right place!&lt;/p&gt;

&lt;p&gt;My name is Lucas and I’ve been a software engineer for over 5 years now.&lt;/p&gt;

&lt;p&gt;My journey into the world of software and AI began during my university studies at UFU (Universidade Federal de Uberlândia), where I pursued a Bachelor's Degree in Computer Engineering and actually took part in a Robotics Team called Roboforge — you should probably know that robotics and AI are kind of close fields too — where we actually got first place while competing in one of Latin America’s biggest competition: &lt;a href="https://robotica.robocup.org.br/" rel="noopener noreferrer"&gt;LARC&lt;/a&gt; (which stands for Latin America Robotics Competition, not that creative, I have to say).&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%2Fq4mqw8n1hzxzm4zy0pw9.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%2Fq4mqw8n1hzxzm4zy0pw9.png" alt="Literally me, programming at the competition" width="484" height="712"&gt;&lt;/a&gt;&lt;/p&gt;

Literally me, programming at the competition




&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%2F0otf5mqbyky6mzrpumq4.gif" 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%2F0otf5mqbyky6mzrpumq4.gif" alt="Some really awesome robots that were playing soccer (fully autonomous)" width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

Some really awesome robots that were playing soccer there (fully autonomous)




&lt;p&gt; &lt;/p&gt;

&lt;p&gt;And in this guide, I’ll give my best shot at taking you step-by-step through what you should learn to get a position as a prompt engineer!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Understanding the Basics of LLMs
&lt;/h2&gt;

&lt;p&gt;Before diving into prompt engineering in particular, it's important to have a solid foundation in AI. You know it already — first, you have to learn to walk before you learn to run.&lt;/p&gt;

&lt;p&gt;So, explore a little bit and understand how LLMs work. You don’t have to know everything, though, but, try to answer at least 3 questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the hell is an LLM?&lt;/li&gt;
&lt;li&gt;What types of LLM exist out there?&lt;/li&gt;
&lt;li&gt;How do I build an LLM? (&lt;strong&gt;You don’t have to build one!&lt;/strong&gt; Just learn the basics on how it’s done)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Answering these 3 questions above, you’ll probably find yourself with a bunch of new terms added to your vocabulary and, even more than that, with a bunch of new knowledge added to your toolkit.&lt;/p&gt;

&lt;p&gt;It also can be motivating to actually see the requirements of a few prompt engineering positions and Latitude has created a platform for you to see those positions easily. You can check that out here:&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%2F15cjqdcryru4wxvj7r0w.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%2F15cjqdcryru4wxvj7r0w.png" alt=" " width="800" height="523"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://promptengineerjobs.io/" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Prompt Engineering Jobs by Latitude ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Learn by Doing: Craft a few prompts
&lt;/h2&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%2Fd1cyeij9ilpxa4ga3szw.gif" 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%2Fd1cyeij9ilpxa4ga3szw.gif" alt="https://media2.giphy.com/media/Lny6Rw04nsOOc/giphy.gif?cid=7941fdc6i5g02pksdhbmzgixxrd3gupxpvcqzv70dgx7xddd&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Crafting prompts is an iterative process that involves trial and error. Start by experimenting with simple prompts for personal projects and use cases while gradually moving on to more complex ones. This hands-on approach — which we usually call project-based learning, a really interesting way to learn, which usually leads to ~23% increase in student achievement —  will help you understand how AI models interpret and respond to different inputs&lt;/p&gt;

&lt;p&gt;No ideas on how to start prompting? No worries, I’ve got you covered! Let’s check a few examples:&lt;/p&gt;

&lt;p&gt;Hop on your favorite LLM (and if you don’t have one, feel free to check our &lt;a href="https://dev.to/latitude/the-ultimate-llm-leaderboard-ranking-the-best-language-models-2a67"&gt;comparison guide&lt;/a&gt;) and start with a few basic prompts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Long article text here .............
....................................

Summarize the above article for me.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, another useful example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Interesting topic title you found somewhere

Translate the above topic title to French.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of those examples can show how simple and powerful prompt engineering can really be! Feel free to try those out or any others that might suit you.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Learn Some Programming Basics
&lt;/h2&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%2Fzsws2yiwf1g9beprhho2.gif" 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%2Fzsws2yiwf1g9beprhho2.gif" alt="https://media1.giphy.com/media/scZPhLqaVOM1qG4lT9/giphy.gif?cid=7941fdc62sk1u4dv8b8kv77toibcfqsi0hskna3vpwcry9py&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="220" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Programming is a critical skill for any AI professional. To become a proficient prompt engineer, you should learn at least the basics of one programming language such as Python or R, that are really relevant to the field.&lt;/p&gt;

&lt;p&gt;Besides that, there are numerous benefits that coding skills will give you: from implementing and testing your prompts programmatically to manipulating data effectively. There are numerous online resources and courses available to help you get started with programming (e.g. &lt;a href="https://roadmap.sh/python" rel="noopener noreferrer"&gt;Python Roadmap&lt;/a&gt; — an awesome roadmap to guide you through your journey, or &lt;a href="https://github.com/practical-tutorials/project-based-learning?tab=readme-ov-file#python" rel="noopener noreferrer"&gt;Python Project Ideas&lt;/a&gt; for you to learn by doing).&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Applying prompt engineering to real-world examples
&lt;/h2&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%2Fdguesbjlv5enkrtavz1u.gif" 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%2Fdguesbjlv5enkrtavz1u.gif" alt="https://media4.giphy.com/media/T1A5qkSgZ2p24aOWQc/giphy.gif?cid=7941fdc6lq89yghhfrxjcj2zhr6huxeim93wvgxmq7monsf0&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome, so, now, you already know how to create basic prompts and how to code a little. A really good next step would probably be to start checking some real-world scenarios and how they are being handled while retaining information about the users too!&lt;/p&gt;

&lt;p&gt;Let’s check one example here as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start by imaging a scenario where the company you’re working for has an e-commerce application.&lt;/li&gt;
&lt;li&gt;They’re implementing a new search mechanism with AI in order that users can search with natural language&lt;/li&gt;
&lt;li&gt;The AI here should return a JSON with the characteristics the user asked for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re running an e-commerce for clothing, you’ll probably want to search for relevant information to that sector — like the age, in years. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# If the user says:
# Birthday gift for my 18 months old daughter
&lt;/span&gt;
&lt;span class="c1"&gt;# Maybe a good return would be:
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gender&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;female&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;occasion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;birthday&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age_years&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s run this same scenario working for an e-commerce for sports clothing. Now, searching for the same elements might not be adequate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# If the user says:
# Birthday gift for my 10 years old daughter, she loves skateboarding
&lt;/span&gt;
&lt;span class="c1"&gt;# Maybe a better return would be:
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gender&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;female&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;occasion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;birthday&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sport_suggestion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age_years&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While creating software, the user is always the most important role in the play — from e-commerces to emails, to study companions and code assistants. He is the one who actually pays you, so, always remember to keep that in mind while studying other real-world scenarios.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Learn where things go wrong
&lt;/h2&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%2F731udp8dpj9qrttsmn0w.gif" 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%2F731udp8dpj9qrttsmn0w.gif" alt="https://media3.giphy.com/media/QMHoU66sBXqqLqYvGO/giphy.gif?cid=7941fdc6brnz477ztjtc3m8w1a3qrxkkso9x9w4wc5pfdt88&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you got here, you probably faced a few problems here and there while playing with prompting. From math to sources, to hallucination, there are literally tons of different pitfalls you can end up into if you’re not carefully creating your prompt. &lt;/p&gt;

&lt;p&gt;This step here is actually learned by failing, and then, learning (based on how inaccurate the result was) what you can do differently to improve your prompt.&lt;/p&gt;

&lt;p&gt;Want source citations and your LLM is generating people and articles on the fly? Try RAG (Retrieval Augmented Generation — that you can learn more about &lt;a href="https://cloud.google.com/use-cases/retrieval-augmented-generation?hl=en" rel="noopener noreferrer"&gt;here&lt;/a&gt; — and LLMs with access to the internet! They will surely be more precise.&lt;/p&gt;

&lt;p&gt;Some really bizarre math is showing up mid-calculation? Honestly, LLMs kind of suck at math (which I, personally, find ironically funny). Maybe you can try out some different LLMs — with more focus on the math side — or a different approach to solving the same problem, running things step-by-step or skipping calculations with LLMs and using general programming to solve that instead.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Get Some Fine-Tuning Skills and Improve Reliability
&lt;/h2&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%2F0q83n7qk9woxic2alt7k.gif" 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%2F0q83n7qk9woxic2alt7k.gif" alt="https://media1.giphy.com/media/3oKHWCVJHorZfXrUTm/giphy.gif?cid=7941fdc6njrmil1gz9mvzkf30adm4fo6xwbye7f41gji7742&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok. At this point, you probably know your way around prompting for most of the scenarios you’ll find out there. Unfortunately, as you’ll eventually realize, LLMs tend to be extremely chaotic when not fine-tuned properly, creating varying degrees of “creativity” in your responses.&lt;/p&gt;

&lt;p&gt;This could not be a problem, but, generally, it is. Whenever you’re working with responses, we generally want the AI to have a limited range of variance and bias so that we can constrain our answers between the confinement of accepted answers. &lt;/p&gt;

&lt;p&gt;If you’re in this step, I recommend you take a look at how LLMs are actually configured, check out &lt;a href="https://thenewstack.io/what-temperature-means-in-natural-language-processing-and-ai/" rel="noopener noreferrer"&gt;temperature&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Top-p_sampling" rel="noopener noreferrer"&gt;Top P sampling&lt;/a&gt;, and check for yourself how changing those values and percentages can alter the variance obtained for your prompts. &lt;/p&gt;

&lt;p&gt;Ready to build, test, and deploy some of those prompts? A really cool platform for this is Latitude’s new product, which is currently in early access! Whenever it’s released, I’m sure you’ll find a bunch of cool stuff there that will actually help you in your journey, so check it out!&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%2Fyfa1j029u6zv64gydhci.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%2Fyfa1j029u6zv64gydhci.png" alt="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfa1j029u6zv64gydhci.png" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.latitude.so/" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Enter the Waitlist! ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Showcase your work and Start Applying
&lt;/h2&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%2F4x5uo4y97ettazrq7sok.gif" 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%2F4x5uo4y97ettazrq7sok.gif" alt="https://media0.giphy.com/media/t8QNJ2LngI5OJQN3FP/giphy.gif?cid=7941fdc65kjgm7mma80ge5wcotgj6yh3untmlnu9ze1s9cp5&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hands-on experience is invaluable in the field of prompt engineering and hey, if you’re following along, I’m sure you have tons of that, so, it’s just the time to showcase it to the world!&lt;/p&gt;

&lt;p&gt;Don’t forget to make your work tangible to HR persons! They are the ones recruiting and looking for people, so, show both scenarios: technical for the technical people and non-technical for the non-technical people — this means basically: including a variety of prompts and the corresponding AI responses to demonstrate your expertise, translating that response to non-technical terms when needed. &lt;/p&gt;

&lt;p&gt;Once you have a solid way to showcase things -- being that from just posts or a portfolio, start applying for prompt engineering positions and it’s just a matter of waiting until you find an awesome place to work.&lt;/p&gt;

&lt;p&gt;Kind of lost on where to apply? Latitude’s come to the rescue again — yes, they truly built a whole platform for you to check prompt engineering jobs out, so please, take a look:&lt;br&gt;
&lt;a href="https://promptengineerjobs.io/" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Prompt Engineering Jobs by Latitude ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&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%2Fliu0r6rid0q9wzjj5u7j.gif" 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%2Fliu0r6rid0q9wzjj5u7j.gif" alt="https://media4.giphy.com/media/lD76yTC5zxZPG/giphy.gif?cid=7941fdc6x0r5nlmgaz9pvradu7dqz9yfck7uip2x4t5ybzgm&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="499" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey! I’m glad that you got here!&lt;/p&gt;

&lt;p&gt;Becoming an engineer is a rewarding journey that involves mastering fundamentals, honing your skills, understanding user needs, and crafting effective products — and this goes for any engineering, from software to prompting. &lt;/p&gt;

&lt;p&gt;If you follow those steps, you'll be REALLY well-equipped to enter this exciting field and honestly, we'd love to hear your thoughts and experiences as you embark on this path. Feel free to share your insights in the comments below and don't forget to check out Latitude's new product to further enhance your skills!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>ai</category>
      <category>promptengineering</category>
      <category>career</category>
    </item>
    <item>
      <title>Creating a personal brand: How to sell yourself as a developer</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Tue, 06 Aug 2024 07:01:00 +0000</pubDate>
      <link>https://forem.com/buildwebcrumbs/creating-a-personal-brand-how-to-sell-yourself-as-a-developer-52po</link>
      <guid>https://forem.com/buildwebcrumbs/creating-a-personal-brand-how-to-sell-yourself-as-a-developer-52po</guid>
      <description>&lt;p&gt;Everything changes so fast these days that, standing out as a developer is more important than ever. As much as your technical skills matter, in this sea of programmers, it's your personal touch that can truly set you apart. &lt;/p&gt;

&lt;p&gt;But how can you create your personal brand? How to apply your personal brand to your presentations and public persona? In this article, we'll walk you through the process of creating a personal brand, showcasing yourself to the public, and leaving a long-lasting mark in the developer community.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what’s branding actually?
&lt;/h2&gt;

&lt;p&gt;Branding, in the context of personal branding, is all about creating a unique identity that encapsulates your skills, experiences, and values. It's how you present yourself to the world. It doesn’t always need to be related to you as a person though — there are numerous branding guides for companies and how they present themselves too!&lt;/p&gt;

&lt;p&gt;When it comes to personal branding, consistency is essential. Your brand should be an authentic representation of who you are, and it should remain consistent across different platforms and interactions. This means that the way you present yourself in your portfolio, on your social media platforms, and in person should all align with your personal brand. Besides that, your brand is not just about how you present yourself, but also how others perceive you. This includes the quality of your work, your work ethic, your communication style, and even your personality traits.&lt;/p&gt;

&lt;p&gt;Now, let me show you an example of how I sell my image, and let’s start breaking down everything you need to know on how to do it too!&lt;/p&gt;

&lt;h3&gt;
  
  
  First of all, the theme
&lt;/h3&gt;

&lt;p&gt;Here’s a GIF of my portfolio (and you can find it &lt;a href="https://www.llxd.eu" rel="noopener noreferrer"&gt;here&lt;/a&gt; in case you want to check it for yourself). So, first of all, let’s see if we can spot a clear theme:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjx6aj5so1fdylnsqhd4b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjx6aj5so1fdylnsqhd4b.gif" alt="Portfolio" width="600" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bright contrast in the colors, the 8-bit font, the big buttons, writing animations, and a simple avatar image. The theme is clear: Games!&lt;/p&gt;

&lt;p&gt;Besides that, the first initial phrase “Welcome adventurer” is a classical phrase for a specific genre of games: &lt;strong&gt;RPG/Medieval Games&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Great! Now, why did I choose this theme? Randomly? When the user checks the about me section, he’ll discover:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrdtejc35czpew8ghh01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrdtejc35czpew8ghh01.png" alt="About me section" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So there we go! The theme is not only consistent on all the UI, but it also contains a fragment of my personality — being a tabletop RPG Dungeon Master — on it. Defining a theme for yourself can be hard, but, starting to think about the hobbies and things that you enjoy in your personal life can give a great personal touch to your brand!&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Your Personal Brand
&lt;/h2&gt;

&lt;p&gt;Now that we have a clear understanding of what personal branding is, let's move on to the next step - building your personal brand. This process involves identifying your unique strengths and skills, defining your target audience, and finally, crafting your brand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Identifying Your Unique Strengths and Skills
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6h5xwcae7llprx2vjjt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6h5xwcae7llprx2vjjt.png" alt="SWOT matrix" width="735" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To begin with, it’s a good idea to try to identify what makes you unique as a developer. A helpful tool for this is a SWOT matrix, where you list your Strengths, Weaknesses, Opportunities, and Threats. &lt;strong&gt;Strengths&lt;/strong&gt; could be your technical abilities or soft skills like communication and other ways you approach problems on a day-to-day basis. &lt;strong&gt;Weaknesses&lt;/strong&gt; are areas where you could improve. &lt;strong&gt;Opportunities&lt;/strong&gt; could be networking, open-source contributions, or learning new technologies and &lt;strong&gt;Threats&lt;/strong&gt; could be things like a highly competitive job market or the rapid pace of technological change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Your Target Audience
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--veKOjZjA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media4.giphy.com/media/If41tmxk7e0ys6c22U/giphy.gif%3Fcid%3D7941fdc65pqx75lcsnh5km4kesp010ae6wx2qklybg7iq2hi%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--veKOjZjA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media4.giphy.com/media/If41tmxk7e0ys6c22U/giphy.gif%3Fcid%3D7941fdc65pqx75lcsnh5km4kesp010ae6wx2qklybg7iq2hi%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" alt="https://media4.giphy.com/media/If41tmxk7e0ys6c22U/giphy.gif?cid=7941fdc65pqx75lcsnh5km4kesp010ae6wx2qklybg7iq2hi&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you need to define who your target audience is. These are the people you want to reach with your personal brand - potential employers, colleagues, or the broader developer community. Having a clear understanding of your target audience will help you tailor your brand to appeal to them. In the case of my portfolio, for example, it’s clearly tailored to potential employers!&lt;/p&gt;

&lt;h3&gt;
  
  
  Crafting Your Personal Brand
&lt;/h3&gt;

&lt;p&gt;Once you've identified your strengths and skills and defined your target audience, you can begin crafting your personal brand. This involves deciding on a consistent image or theme (like the game theme I showed above) and communicating your values and skills. &lt;/p&gt;

&lt;p&gt;This is also usable in the context of new brands and ideas! For example, at &lt;a href="https://www.webcrumbs.org/open-source" rel="noopener noreferrer"&gt;Webcrumbs&lt;/a&gt; — a great OSS plugin system, that can really streamline your development process — they started from zero and have now reached a point where the brand stands on solid ground with colors, icons, and themes that certainly cuts an impression (and even more than that, makes them memorable)!&lt;/p&gt;

&lt;h2&gt;
  
  
  Showcasing Yourself to the Public
&lt;/h2&gt;

&lt;p&gt;Having crafted your personal brand, the next step is to showcase it to the public. This involves creating an online presence that aligns with your brand. Honestly, this can be achieved in a bunch of different ways: e.g. building a portfolio website that highlights your work and skills, or even leveraging social media platforms and GitHub to reach a wider audience.&lt;/p&gt;

&lt;p&gt;Just make sure that, whenever you’re using a brand as a communication focus, keep the same communication tone and other aspects throughout different platforms. If you’re funny and casual everywhere, it’s not because you’re on LinkedIn that you’re not going to be casual anymore. Retain some professionalism (which is LinkedIn’s case in the general tone that exists there), but try to be as much casual as you’d be in your portfolio communications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking for a showcase example?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc3vve6wk7qoo8kzwuhl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc3vve6wk7qoo8kzwuhl.gif" alt="Frontend AI Release" width="600" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’re actually launching a new product here at Webcrumbs: &lt;a href="https://www.producthunt.com/posts/frontendai-by-webcrumbs" rel="noopener noreferrer"&gt;FrontendAI&lt;/a&gt;! An awesome code generator for your front-end UI! &lt;br&gt;
It takes you from prompt to product in seconds and it would be awesome if you could check it out! It’s totally free and can really speed things up in your development process!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.producthunt.com/posts/frontendai-by-webcrumbs" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;🚀 Check FrontendAI at Product Hunt 🚀&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Leaving a Mark in the Developer Community
&lt;/h2&gt;

&lt;p&gt;There are other forms that you can create a personal brand, and, one of the bigger ones is leaving a mark in our community. This can be achieved through a variety of different ways, from networking to contributing to open-source projects, and even just sharing your knowledge with others! All those ideas present an opportunity for you to showcase your work and skills, and even more than that, your personal self to others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking and Building Connections
&lt;/h3&gt;

&lt;p&gt;Networking is a crucial part of building your brand. Try to attend industry events, join online forums/Reddit, and participate in developer communities. Introduce yourself, share your work, and engage with others. Building genuine relationships can help you establish a strong reputation and open up new opportunities — to be honest with you, a bunch of different projects I’ve participated in became opportunities just because I had good connections, formed throughout the daily work with the people making it, so, I can’t stress enough how important this is!&lt;/p&gt;

&lt;h3&gt;
  
  
  Contributing to Open-Source Projects
&lt;/h3&gt;

&lt;p&gt;Another really cool way to create your brand is to contribute to open-source projects. It is a great way to showcase your skills and give back to the community on things you enjoy while also providing an excellent opportunity to collaborate with other developers and learn from them. &lt;/p&gt;

&lt;p&gt;Your contributions can serve as a testament to your expertise and dedication, enhancing your brand and serving as proof of trust about the quality of your work — a few positions even ask for your personal contributions while in the interview.&lt;/p&gt;

&lt;p&gt;Here at &lt;a href="https://www.webcrumbs.org/open-source" rel="noopener noreferrer"&gt;Webcrumbs&lt;/a&gt;, we’re actually Open-Source, so if you’re looking somewhere to start contributing to and you’re looking for places that you can have a lot of impact, feel free to &lt;a href="https://github.com/webcrumbs-community/webcrumbs" rel="noopener noreferrer"&gt;star&lt;/a&gt; us and check our issues! Also, in case you haven't checked out the launch, here's a quick link for it:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.producthunt.com/posts/frontend-ai" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--acEz1vQX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ph-files.imgix.net/3581b7da-0857-4bfe-8920-db385320088e.png%3Fauto%3Dformat%26fit%3Dcrop%26frame%3D1%26h%3D512%26w%3D1024" height="400" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.producthunt.com/posts/frontend-ai" rel="noopener noreferrer" class="c-link"&gt;
           Frontend AI - Your UI generated from prompts or images | Product Hunt
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Want to speed up your frontend? Meet Frontend AI. Simply write what you want or paste an image, preview your component and get your code. Try it out—no login required! 🧙 Tips: Try it with their suggested prompts or an image from Figma or your favorite app.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--cmeqGyAO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ph-static.imgix.net/ph-favicon-coral.ico" width="240" height="240"&gt;
        producthunt.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Sharing Knowledge Through Blogging and Journaling
&lt;/h3&gt;

&lt;p&gt;Sharing your knowledge through blogging or vlogging can position you as a thought leader in your field. Write about your experiences, share tutorials, or discuss industry trends. This not only helps others but also reinforces your expertise and passion for your work. Consistently producing quality content can significantly boost your personal brand.&lt;/p&gt;

&lt;p&gt;This was part of the reason I’ve actually begun to write here. After receiving some great feedback at work, I started to think of ways that I could share my knowledge with other people and show a few opinions and takes I had in software engineering. I can’t recommend enough how journaling your journey can impact your life — it’s a really powerful and yet simple habit.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kCi_NI7T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media2.giphy.com/media/1eUtR2Fc4lLpJcEyqe/giphy.gif%3Fcid%3D7941fdc69aq540g720nsfsoduzaxo4jpuud2hawg65fp3plm%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kCi_NI7T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media2.giphy.com/media/1eUtR2Fc4lLpJcEyqe/giphy.gif%3Fcid%3D7941fdc69aq540g720nsfsoduzaxo4jpuud2hawg65fp3plm%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" alt="https://media2.giphy.com/media/1eUtR2Fc4lLpJcEyqe/giphy.gif?cid=7941fdc69aq540g720nsfsoduzaxo4jpuud2hawg65fp3plm&amp;amp;ep=v1_gifs_search&amp;amp;rid=giphy.gif&amp;amp;ct=g" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In summary, creating a personal brand as a developer is a multifaceted process that involves identifying your unique strengths, defining your target audience, and showcasing your skills and personality through various platforms. By building a consistent and authentic brand, you can stand out in the competitive tech industry and leave a lasting impression in the developer community. &lt;/p&gt;

&lt;p&gt;Don't forget to network, contribute to open-source projects, and share your knowledge to further solidify your brand. We'd love to hear your thoughts and experiences on personal branding, so feel free to leave a comment below. Also, be sure to check out &lt;a href="https://www.webcrumbs.org/open-source" rel="noopener noreferrer"&gt;WebCrumbs&lt;/a&gt; for some exciting tools and opportunities to contribute to open-source projects!&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>The Ultimate LLM Leaderboard: Ranking the Best Language Models</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Wed, 24 Jul 2024 12:30:00 +0000</pubDate>
      <link>https://forem.com/latitude/the-ultimate-llm-leaderboard-ranking-the-best-language-models-2a67</link>
      <guid>https://forem.com/latitude/the-ultimate-llm-leaderboard-ranking-the-best-language-models-2a67</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&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%2F1l3974ijka06wgvsg3nw.gif" 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%2F1l3974ijka06wgvsg3nw.gif" alt="Gif of person scrolling through social media" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’re there, casually scrolling your timeline as a subtle vibration from your phone catches your attention. Another AI LLM is reaching the market and is the new best toy in town that everyone should check.&lt;/p&gt;

&lt;p&gt;The first time that happened, you were probably actually intrigued and maybe even went to check it out, but, by the fourth and even fifth time, checking new LLMs and AIs started to become a little tiring.&lt;/p&gt;

&lt;p&gt;Want to check which are the best LLMs for each case (API, personal use/prompting, etc), ranked, without having to spend hours searching and comparing each one? This article is for you, then.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criteria for Ranking
&lt;/h2&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%2Fwfyu3cztn417y7bxmf3h.gif" 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%2Fwfyu3cztn417y7bxmf3h.gif" alt="Stonks" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ranking of language models in this leaderboard is based on a list of criteria made by me, designed to evaluate their overall performance and applicability. These criteria include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overview:&lt;/strong&gt; A small resume about who is the creator of the LLM (and maybe even some polemics you should learn about)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strengths:&lt;/strong&gt; Where and in which cases the LLM excels at&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: The model's capacity to handle increasing amounts of data and user interactions along with how much would that cost you. Generally, this uses &lt;strong&gt;tokens&lt;/strong&gt; for measurement. Not sure what a token is and how it’s calculated? You can consider it equal to ~4 characters of text for common English.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration/Community Support&lt;/strong&gt;: How easily the model can be integrated into existing systems and workflows and the availability of resources, documentation, and community engagement to assist us with implementation and usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  LLM Setup - The quick and easy route
&lt;/h2&gt;

&lt;p&gt;HOLD FAST! Before we continue, if you’d prefer to learn by doing and using those powerful LLMs we have something exciting for you!&lt;/p&gt;

&lt;p&gt;Join our waitlist for early access to Latitude’s new platform. It's designed to help LLM developers streamline their work and bring ideas to life with confidence, helping a ton in the measurement process I mentioned above.&lt;/p&gt;

&lt;p&gt;We're honestly truly excited about this platform and can't wait to see what you create with it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfa1j029u6zv64gydhci.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%2Fyfa1j029u6zv64gydhci.png" alt="LLM Latitude's platform" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't miss out! Click the link below to join our waitlist 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.latitude.so/" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Enter the Waitlist! ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Top Language Models
&lt;/h2&gt;

&lt;p&gt;Now, let’s jump right into the LLMs that are most famous today. Of course, I wouldn’t be able to actually review every single one (there are literally thousands of models out there) but, here we’ll check: GPT, Gemini, LLaMA, Claude, and Copilot.&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%2Ff4r4oot8ngbsk9us2qpz.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%2Ff4r4oot8ngbsk9us2qpz.png" alt="GPT Logo" width="225" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;: GPT (Generative Pre-trained Transformer) is one of the most well-known language models developed by OpenAI. It has a ton of models: 3.5-turbo, 4, 4o (the most recent), and more. In terms of polemics, it’s involved in kind a few of them (e.g. &lt;a href="https://www.npr.org/2024/05/31/g-s1-2263/voice-lab-analysis-striking-similarity-scarlett-johansson-chatgpt-sky-openai" rel="noopener noreferrer"&gt;ChatGPT's voice closely resembles Scarlett Johnasson's, says lab analysis : NPR&lt;/a&gt;), so, you can also take that into consideration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Exceptional accuracy and versatility in generating human-like text. It has some great API documentation and integration also, while still maintaining a good interface for human interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prices&lt;/strong&gt;: Varies depending on usage and subscription plans, the better trained the model, the more expensive it becomes, ranging from $0.5/1M tokens to $5/1M tokens on the most recent model. You can check them all here: &lt;a href="https://openai.com/api/pricing/" rel="noopener noreferrer"&gt;Pricing | OpenAI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking for image models? It also has, with prices ranging from $0.016/image to $0.040/image. If you’re interested in using it for prompting and normal use instead of integration, it has both a free plan and a Plus plan with different models, image generation, and a price of $20/month.&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%2Fhc8alczutjrtdp514o7p.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%2Fhc8alczutjrtdp514o7p.png" alt="Personal GPT Plan" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff370srel4bb55bjvx6zb.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%2Ff370srel4bb55bjvx6zb.png" alt="API GPT Plans" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemini
&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%2Ftpre3nme34yalvb1zzfl.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%2Ftpre3nme34yalvb1zzfl.png" alt="Gemini's Logo" width="344" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;: Gemini is a robust language model known for its efficiency and scalability. It’s made by Google and recently had some really awesome announcements at &lt;a href="https://blog.google/technology/ai/google-io-2024-100-announcements/" rel="noopener noreferrer"&gt;I/O&lt;/a&gt; (a conference made by Google to showcase new stuff). It’s also mentioned in a few polemics (e.g &lt;a href="https://www.axios.com/2024/02/23/google-gemini-images-stereotypes-controversy" rel="noopener noreferrer"&gt;Google pauses Gemini's AI image generation after diversity controversies&lt;/a&gt;) that you can take into consideration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Amazing context window (this basically means it can use more data as the font of a single response), great language proficiency too!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.google.dev/pricing" rel="noopener noreferrer"&gt;&lt;strong&gt;Prices&lt;/strong&gt;&lt;/a&gt;: For APIs, pricing based on usage too, having a free tier with low requests number and $0.35 / million tokens, later on. For personal use, Gemini Code Assist, for example, costs $19 per user, per month.&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%2Fymtijzyxoohxt55z3vtv.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%2Fymtijzyxoohxt55z3vtv.png" alt="Gemini's Personal Plan" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjm64gxttoql4plhqrmgi.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%2Fjm64gxttoql4plhqrmgi.png" alt="Gemini's API Plan" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  LLaMA
&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%2Fn3cqcuraahauou55ywvq.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%2Fn3cqcuraahauou55ywvq.png" alt="Llama 2 logo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;: LLaMA (Large Language Model Meta AI) is designed to be less resource-intensive than other models, it has a different license scheme, which means that this resembles “something open source” and as the other ones, also has a few polemics in its name (e.g. &lt;a href="https://www.businessinsider.com/meta-llama-2-data-train-ai-models-2023-7" rel="noopener noreferrer"&gt;Meta Stops Disclosing the Data It Uses to Train AI Models Like Llama 2 - Business Insider&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: They &lt;strong&gt;try&lt;/strong&gt; to follow guidelines for &lt;a href="https://ai.meta.com/responsible-ai/" rel="noopener noreferrer"&gt;responsible AI&lt;/a&gt; creation and innovation. It also has different models specific for different scenarios like Code LLaMA, for code generation, for example. It’s great for research and English-focused applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prices&lt;/strong&gt;: Basically free while using Meta AI or downloading and running it locally/self-host. You can also check out services for using as API, that for example can generate API keys for using LLaMA.&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%2F5oy12s4mj9cw4vn2ix85.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%2F5oy12s4mj9cw4vn2ix85.png" alt="LLama Landing Page" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude
&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%2Fd7kogjnwnjrd1fmdqkql.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%2Fd7kogjnwnjrd1fmdqkql.png" alt="Claude Logo" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;: Claude is a versatile language model that excels in understanding and generating natural language. It’s a really interesting alternative to GPT, honestly — and, for the first time, I couldn’t find some polemics including it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Seems to perform better than GPT mostly &lt;a href="https://claude101.com/claude-3-vs-gpt-4o/" rel="noopener noreferrer"&gt;regarding speed and prices&lt;/a&gt;, but tries to reach the same strengths, like conversational AI, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.anthropic.com/pricing" rel="noopener noreferrer"&gt;&lt;strong&gt;Prices&lt;/strong&gt;&lt;/a&gt;: For personal use, it starts out free and grows up to $20 for pro or $30 for teams. For APIs, costs $3/M tokens for input and $15 for output on their most intelligent model to date.&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%2Fxiqvnzckwu3xch5y34kk.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%2Fxiqvnzckwu3xch5y34kk.png" alt="Personal Claude's Plan" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo3lqxqxbd627b1cvgq2.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%2Fbo3lqxqxbd627b1cvgq2.png" alt="Claude's API Plan" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Copilot
&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%2Fdfuafw0l6emrsveg6nav.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%2Fdfuafw0l6emrsveg6nav.png" alt="Copilot Logo" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;: Microsoft Copilot (here, I’ll evaluate both Copilot for Microsoft 365 and GitHub Copilot) and, although this one is not necessarily an LLM, it’s been publicly known that Microsoft is developing an in-house AI LLM — that is probably going to be connected to these products in the future, and, since &lt;a href="https://www.theverge.com/2024/7/19/24201864/crowdstrike-outage-explained-microsoft-windows-bsod" rel="noopener noreferrer"&gt;Windows is used by a ton of people&lt;/a&gt;, I’ll also leave my review of them here. And let’s not forget some polemics here too (e.g. &lt;a href="https://news.sky.com/story/controversial-microsoft-ai-screenshot-feature-delayed-over-security-concerns-13152918" rel="noopener noreferrer"&gt;Controversial Microsoft AI screenshot feature delayed over security concerns | Science &amp;amp; Tech News | Sky News&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Aims to be the best in aiding people on the daily life, from help with emails, to Excel, to code with GitHub Copilot’s suggestions and autocomplete. The strong side here is obviously if you/your company use Microsoft’s services. Outlook, Excel, Word, Teams, and all other products can benefit from here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prices&lt;/strong&gt;: You'll actually find a really cool free tier here for consumption (prompting and images , but not code). But, if you want more of that uniqueness of integrating all Microsoft's products with AI, it's a subscription-based model with various tiers. You can check them all here: &lt;a href="https://github.com/features/copilot#pricing" rel="noopener noreferrer"&gt;GitHub Copilot · Your AI pair programmer&lt;/a&gt; and &lt;a href="https://www.microsoft.com/en-us/microsoft-365/enterprise/copilot-for-microsoft-365#Pricing" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Honestly, they both seem kind of expensive with GitHub Copilot seeming a little bit less, but, in company terms, they’re probably not that expensive.&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%2Fod16iuudbu95oz4msv7u.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%2Fod16iuudbu95oz4msv7u.png" alt="Copilot Product Pricing" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu9cpfdewq57sp9iadet.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%2Fqu9cpfdewq57sp9iadet.png" alt="Github Copilot Pricing" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&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%2F4obba4fo48f4o8p6kvom.gif" 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%2F4obba4fo48f4o8p6kvom.gif" alt="That's all Folks!" width="349" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! So, I hope that throughout this article I provided an in-depth look at the top language models, highlighting their strengths, pricing, polemics, and use cases. With Latitude's tools and insights, developers have the resources they need to choose the best LLM for their projects and optimize their performance, so, make sure to join the waitlist! &lt;/p&gt;

&lt;p&gt;We encourage you to explore these models further and take advantage of Latitude's platform to enhance your development process. Don't forget to share your thoughts and experiences in the comments, and join the Latitude community to stay updated on the latest advancements in AI and LLMs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>For Engineers in a Hurry: A Guide for Implementing Security</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Tue, 25 Jun 2024 13:07:53 +0000</pubDate>
      <link>https://forem.com/llxd/for-engineers-in-a-hurry-a-guide-for-implementing-security-1o8m</link>
      <guid>https://forem.com/llxd/for-engineers-in-a-hurry-a-guide-for-implementing-security-1o8m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I’m sure that, when trying to be a solopreneur or create your own side projects, time constraints can be a big problem. Most of the time, we have to overlook things and do them as quickly as possible to meet the deadlines. &lt;/p&gt;

&lt;p&gt;Unfortunately, security is one of those things that takes a lot of time to properly solve (if you work in the corporate world, you’ll actually get used to typically having entire teams dedicated to security and risk analysis) and, if we ignore it, consequences can be severe.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll quickly implement robust security measures to protect one of my side projects from attackers and spammers with just a few lines of code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Project introduction and solution
&lt;/h2&gt;

&lt;p&gt;So, just a quick context: I’m creating a website called &lt;a href="https://ruleslawyerai.com/" rel="noopener noreferrer"&gt;RulesLawyerAI&lt;/a&gt;. The project itself is kind of simple: A GPT wrapper trained on open rules and game aspects for tabletop rpgs. Whenever a user has a doubt, the user can simply ask the AI for the solution and it’ll be as precise as it possibly can. Here’s a 1-minute demo for it:&lt;/p&gt;

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

&lt;p&gt;As you may have &lt;a href="https://serverlesshorrors.com/" rel="noopener noreferrer"&gt;recently heard&lt;/a&gt;, most hosting and serverless services, which are designed to scale &lt;em&gt;infinitely&lt;/em&gt;, can end up costing a lot if proper security measures are not in place. Besides that, &lt;a href="https://haveibeenpwned.com/" rel="noopener noreferrer"&gt;data breaches and leaks&lt;/a&gt; are more frequent than ever, and, creating an idea without security is a true recipe for disaster. This means that even these small side-projects made for fun or learning can cost a bunch of money if we do not implement anything security-related.&lt;/p&gt;

&lt;p&gt;That's precisely where &lt;a href="https://arcjet.com/" rel="noopener noreferrer"&gt;Arcjet&lt;/a&gt; comes in. From bot and spam protection to rate limiting and email validation, Arcjet offers a robust set of tools to secure your Next.js (and Node, Bun, SvelteKit, Express, and Hono, with other common frameworks coming soon) application.&lt;/p&gt;

&lt;p&gt;It's designed to be easy to integrate into your application, providing robust security measures with minimal effort on your part, exactly what I was looking for while working on this side project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Although Arcjet invited me to alpha test their product and write about the experience, they did not influence my opinion in this article. While they did provide the necessary support when I had questions about how things worked and how to implement things for this article, their &lt;a href="https://discord.gg/TPra6jqZDC" rel="noopener noreferrer"&gt;discord channel&lt;/a&gt; is an &lt;strong&gt;official support channel,&lt;/strong&gt; so I hope this level of support is standard for everyone who reaches out, as it appears to be the case for past cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration and Demonstration of the Security Improvements
&lt;/h2&gt;

&lt;p&gt;Integrating Arcjet into your Next.js app is truly a straightforward process. The project I've been working on, RulesLawyerAI, utilizes Supabase for login. With Arcjet, it's relatively easy to add login spam prevention and limit the number of requests. Let's go through the process step-by-step.&lt;/p&gt;

&lt;p&gt;First of all, if you’d like to check Arcjet’s documentation, you can find it &lt;a href="https://docs.arcjet.com/get-started" rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s start by simply downloading the package to our codebase. In my case, I use pnpm, so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add @arcjet/next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing the package, we should head up and create an account. Currently, since Arcjet is in beta, they are offering their protections and services &lt;a href="https://docs.arcjet.com/pricing" rel="noopener noreferrer"&gt;totally free&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%2F3xg7yct6gr9w2m63rarm.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%2F3xg7yct6gr9w2m63rarm.png" alt="Arcjet Homepage" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating an account, we’ll get an ARCJET_KEY, which we’ll use to connect our app to their platform:&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%2Fgfwzg40k7qy7y4ftzghp.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%2Fgfwzg40k7qy7y4ftzghp.png" alt="ARCJET KEY" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After having the basic info set up, we should choose the things we actually want protected in our app. In my case, rate limiting and bot protection are must-haves, so that’s where we are going next!&lt;/p&gt;

&lt;p&gt;So, for the rate-limiting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;arcjet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokenBucket&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="s2"&gt;@arcjet/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;NextResponse&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="s2"&gt;next/server&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;aj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arcjet&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&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;ARCJET_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a token bucket rate limit. Other algorithms are supported.&lt;/span&gt;
    &lt;span class="nf"&gt;tokenBucket&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LIVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// will block requests. Use "DRY_RUN" to log only&lt;/span&gt;
      &lt;span class="na"&gt;characteristics&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="s2"&gt;ip.src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// track requests by a custom user ID&lt;/span&gt;
      &lt;span class="na"&gt;refillRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// refill 5 tokens per interval&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// refill every 10 seconds&lt;/span&gt;
      &lt;span class="na"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// bucket maximum capacity of 10 tokens&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;This will create a token bucket rate limiter. It’s a really interesting algorithm for requests where basically, we have a bucket that refills itself for some tokens per interval, and, with each request, we deplete the bucket with a few tokens. You can learn more about the algorithm (and other types of rate-limiting algorithms &lt;a href="https://docs.arcjet.com/rate-limiting/algorithms#token-bucket" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;After adding the Arcjet instance, we just call it in our function to know if the request is approved or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&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;GET&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;Request&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;decision&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;aj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;protect&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;requested&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Deduct 5 tokens from the bucket&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;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDenied&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Too Many Requests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;429&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="nx"&gt;NextResponse&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="s2"&gt;Hello world&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this new code in place, we can check that on Arcjet’s website that, after we made sufficient requests to not afford to do another one, this happens:&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%2F3xtjw4y7lmw3u8yso1av.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%2F3xtjw4y7lmw3u8yso1av.png" alt="Arcjet Dashboard" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And of course, on our application, we can make a more user-friendly message:&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%2Fi76qx0b4xdbl92aq5u64.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%2Fi76qx0b4xdbl92aq5u64.png" alt="Translated error" width="730" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the bot protection, just a simple middleware should do the trick. In Next.js, just creating a &lt;code&gt;middleware.ts&lt;/code&gt; file at the root of the project solves this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;arcjet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;detectBot&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="s2"&gt;@arcjet/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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// matcher tells Next.js which routes to run the middleware on.&lt;/span&gt;
  &lt;span class="c1"&gt;// This runs the middleware on all routes except for static assets.&lt;/span&gt;
  &lt;span class="na"&gt;matcher&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="s2"&gt;/((?!_next/static|_next/image|favicon.ico).*)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arcjet&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&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;ARCJET_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;detectBot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LIVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// will block requests. Use "DRY_RUN" to log only&lt;/span&gt;
      &lt;span class="na"&gt;block&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="s2"&gt;AUTOMATED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// blocks all automated clients&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;// Pass any existing middleware with the optional existingMiddleware prop&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;createMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will result in requests coming from bots being blocked! How cool is that?&lt;/p&gt;

&lt;p&gt;Remember, security is a continuous process, not a one-time event. Always be vigilant for new threats and adjust your security measures accordingly. An excellent resource to keep in mind is the &lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top 10&lt;/a&gt;, a standard awareness document representing a broad consensus about the most critical security risks to web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important details
&lt;/h2&gt;

&lt;p&gt;One important detail is that, although all routes are now secure, we are calling the protection twice: One on the &lt;code&gt;middleware.ts&lt;/code&gt; and another on the protected route itself. Fortunately, they offer great &lt;a href="https://docs.arcjet.com/shield/reference/nextjs#avoiding-double-protection-with-middleware" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; on avoiding such problems — we simply have to exclude the protected routes of the middleware with the middleware pattern-matching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;arcjet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;detectBot&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="s2"&gt;@arcjet/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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// matcher tells Next.js which routes to run the middleware on.&lt;/span&gt;
  &lt;span class="c1"&gt;// This runs the middleware on all routes except for static assets&lt;/span&gt;
  &lt;span class="c1"&gt;// and now, the api/protected_route path too!&lt;/span&gt;
  &lt;span class="na"&gt;matcher&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="s2"&gt;/((?!_next/static|_next/image|favicon.ico|api/protected_route).*)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arcjet&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&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;ARCJET_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;detectBot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LIVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;block&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="s2"&gt;AUTOMATED&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;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="nf"&gt;createMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another really important detail is that, currently, Arcjet’s solution works with the &lt;a href="https://docs.arcjet.com/reference/nextjs/#nextjs" rel="noopener noreferrer"&gt;latest Next.js major version&lt;/a&gt; — 14.x. Although it’s a really interesting version with a bunch of new features to improve performance and development experience, it’s important to have that in mind. It also needs Typescript to be in the latest major version — 5.x, so, keep that in mind when adding the package!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Personal Thoughts
&lt;/h2&gt;

&lt;p&gt;In conclusion, we've seen how simple it can be to implement robust security measures in our projects, even when we're pressed for time or working solo. By using the power of tools like Arcjet, we can ensure our applications are protected against threats like bots and excessive requests. &lt;/p&gt;

&lt;p&gt;Honestly, my experience was really positive. The implementation took just a few minutes and it was easy to see the results since the website UI is well made. The only time I needed to reach out to support was because I didn't have the correct Next.js version — and because of that, the SDK wasn’t working. Since this type of small compatibility issue is common in alpha products, a quick bump made everything work.&lt;/p&gt;

&lt;p&gt;Remember, every project, no matter how small or seemingly insignificant, deserves to be secure. So, take this knowledge, apply it to your own projects, and let us know your experiences. If you've used Arcjet or similar tools, we'd love to hear about your experiences in the comments.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>5 Reasons Why Your Side Projects Fail to Make Money And How to Avoid Them</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Wed, 19 Jun 2024 14:10:12 +0000</pubDate>
      <link>https://forem.com/wasp/5-reasons-why-your-side-projects-fail-to-make-money-and-how-to-avoid-them-4l5m</link>
      <guid>https://forem.com/wasp/5-reasons-why-your-side-projects-fail-to-make-money-and-how-to-avoid-them-4l5m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&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%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcjA0MGM0NjN0YjR3aGRicHM3YzUyc254ZmxxNjkxdzlnZWZ0NHRjbCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FljtfkyTD3PIUZaKWRi%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcjA0MGM0NjN0YjR3aGRicHM3YzUyc254ZmxxNjkxdzlnZWZ0NHRjbCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FljtfkyTD3PIUZaKWRi%2Fgiphy.webp" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello there! If you're like many aspiring entrepreneurs (including me), you've probably had your fair share of bright ideas but struggled to turn them into profitable side projects. You're not alone. Many side projects fail to make money, and understanding why is the first step towards success. So let's dive into the common pitfalls of the solopreneur/indiehacker journey and learn how to avoid them.&lt;/p&gt;

&lt;p&gt;Starting this journey, it's important to remember that failure is not the enemy. It is, in fact, a crucial part of the process. Yes, that’s the hard truth: No one ever succeeded by doing something first try. &lt;/p&gt;

&lt;p&gt;Embracing failure and learning from it is what helps us avoid making the same mistakes in the future. So buckle up, because we're about to explore the common reasons why side projects fail and how to navigate around them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #1 - Not trying it out
&lt;/h2&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%2F2bcwyxlln68kmzv853oc.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%2F2bcwyxlln68kmzv853oc.png" alt="Tweet from levelsio" width="409" height="784"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a tweet from &lt;a href="https://twitter.com/levelsio" rel="noopener noreferrer"&gt;@levelsio&lt;/a&gt;, a successful solopreneur, making over $150K/month and it’s a great example to check out. The fear of failure often holds us back from taking that first step. Don't let this fear stop you! &lt;strong&gt;It's better to try and fail than to never try at all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Moreover, keep in mind that not trying at all means you're missing out on valuable experiences and opportunities for growth. Even if your project doesn’t turn out to be profitable, the skills and experience you gain are really the point here. Whether it's enhancing your problem-solving abilities, learning more about a new market, or understanding its dynamics, these skills can be incredibly beneficial in your future projects and interviews.&lt;/p&gt;

&lt;p&gt;So, the next time you have an idea for a side project, go for it! Allow your curiosity and passion to drive you, and don't let the fear of failure hold you back. Fail and learn with your mistakes, over and over again — this is the best way to grow as shown by &lt;a href="https://twitter.com/levelsio" rel="noopener noreferrer"&gt;@levelsio&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #2 - Failed Ideation
&lt;/h2&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%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExMzZ5ejdzZWFhbHl6anF1NXNtN2ZwdXJvbmE5NDBxdjZjY2J1Mm84cSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FPbzwVUojP4d8RcRgK0%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExMzZ5ejdzZWFhbHl6anF1NXNtN2ZwdXJvbmE5NDBxdjZjY2J1Mm84cSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FPbzwVUojP4d8RcRgK0%2Fgiphy.webp" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You've got this idea. But was it formed through effective brainstorming and problem-solving? One common pitfall in side projects is rushing the ideation process. A thorough brainstorming process is crucial to ensure the viability of your idea. &lt;/p&gt;

&lt;p&gt;Try to use your own lenses to filter out ideas that you don’t have that much in common with. The more native the problem is to you, the more obvious and doable the solution seems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate your idea: It's not enough to think it's good. You need to have at least some assurance that there's a market for it. Conduct surveys, ask people you trust, and gather as much initial data as you can.&lt;/li&gt;
&lt;li&gt;Make sure your idea solves a problem: A good business idea is one that fills a gap in the market or solves a problem that people are experiencing.&lt;/li&gt;
&lt;li&gt;Evaluate your resources: Do you have the skills, time, and money to turn your idea into a business? Be honest with yourself. Always remember that you can do an MVP (minimum viable product), but, if the MVP doesn’t give real value to the users, it won’t suffice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want an example? Check this &lt;a href="https://wasp-lang.dev/blog/2023/02/14/amicus-indiehacker-interview" rel="noopener noreferrer"&gt;interview&lt;/a&gt; with Erlis, creator of &lt;a href="https://www.amicus.work/" rel="noopener noreferrer"&gt;amicus.work&lt;/a&gt;. It precisely shows how being close to the problem makes the solution intuitive. If you find yourself stuck, you can have a quick read at this other &lt;a href="https://dev.to/llxd/creating-a-more-than-minor-side-project-from-planning-to-release-3be8"&gt;article&lt;/a&gt;, or, if you’d prefer a more deep dive &lt;a href="https://makebook.io/" rel="noopener noreferrer"&gt;Make Book&lt;/a&gt; or &lt;a href="https://www.amazon.com/Lean-Startup-Entrepreneurs-Continuous-Innovation/dp/0307887898" rel="noopener noreferrer"&gt;The Lean Startup&lt;/a&gt; are great references too, since they provide valuable insights into avoiding common mistakes during the ideation phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #3 - The infinite build
&lt;/h2&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%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExNmoxdm1nN2I4dml0OXNibTg5a2N3bGxhbGprZG10eHR4MmllNzJ0dSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FUAHZijO91QCl2%2F200.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExNmoxdm1nN2I4dml0OXNibTg5a2N3bGxhbGprZG10eHR4MmllNzJ0dSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FUAHZijO91QCl2%2F200.webp" width="358" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you are: Technology choices flipping through your mind, and you're actually considering learning a whole new programming language just to solve this new problem. Come on, you already read an &lt;a href="https://dev.to/wasp/the-art-of-self-learning-how-to-teach-yourself-any-programming-concept-5de4"&gt;article on learning&lt;/a&gt;! Nothing can stop you!&lt;/p&gt;

&lt;p&gt;But, wait! Think about it. Now you have to fight against two problems at the same time: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learning a new language,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AND CREATING THE SOLUTION TO YOUR PROBLEM.&lt;/strong&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Turning a fantastic idea into a thriving business is challenging enough already. And you already know that many side projects fail &lt;strong&gt;during the building phase&lt;/strong&gt;, so why do this to yourself?&lt;/p&gt;

&lt;p&gt;The secret here? Innovate, but with caution! &lt;/p&gt;

&lt;p&gt;Try things that can always speed you up way more than burden you and slow you down. An example? Already know React? Try &lt;a href="https://wasp-lang.dev/" rel="noopener noreferrer"&gt;Wasp&lt;/a&gt; , a full-stack framework that takes care of Boilerplate (e.g. Auth) for you and uses AI generation capabilities to help you create products even quicker. &lt;/p&gt;

&lt;p&gt;When trying to create and test an idea, we are not looking too much into learning new stuff, rather &lt;strong&gt;it is more about creating the idea itself.&lt;/strong&gt; So when choosing tools, choose ones that are based on technologies you already know and will help you move fast!&lt;/p&gt;




&lt;p&gt;By the way: &lt;a href="https://wasp-lang.dev/" rel="noopener noreferrer"&gt;Wasp&lt;/a&gt; are the ones making this article possible and, recently, we released Open SaaS — an excellent, 100% free and open-source way to quick-start your new SaaS. Check it out!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wasp-lang/open-saas" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Create your SaaS with Open SaaS 🙏&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opensaas.sh" rel="noopener noreferrer"&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%2Fj9t2q03c6a86dd4oi1xt.png" alt="Open SaaS Banner" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Other really common mistake is striving for perfection, which often leads to endless tweaking and delays. Remember, "Done is better than perfect." It's crucial to complete your project and get it out into the world. If your project was seen by no one, it’s just an idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #4 - The never arriving feedback
&lt;/h2&gt;

&lt;p&gt;Delays aren't the only stumbling block in this phase. Sometimes, we're so consumed with creating the perfect product that we forget to validate it with actual users. Regular feedback is crucial - it helps you make necessary changes and ensure your product meets the users' needs.&lt;/p&gt;

&lt;p&gt;Without feedback, you’ll never know if you hit the jackpot or if you’re creating a solution for a problem that no one has. &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%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExM294bHQyaGN3NHVsaWFncW1lNWc3aGIzaG50YWR3c3d2bThxMHdkNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F4LsN0YwgIsvaU%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExM294bHQyaGN3NHVsaWFncW1lNWc3aGIzaG50YWR3c3d2bThxMHdkNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F4LsN0YwgIsvaU%2Fgiphy.webp" width="245" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, how do you make sure you're getting the necessary feedback? Start by testing your product with a small group of users. This could be a group of friends, family, or even a dedicated focus group. Their feedback is valuable in identifying any issues or areas of improvement.&lt;/p&gt;

&lt;p&gt;It’s really common that we face the fear of receiving negative feedback too, which often leads to withholding the product from the market until it's 'perfect'. This approach, however, can be harmful. It's vital to ship your product as early as possible, even if it's lacking some of the cool features you're planning to add. Early feedback from users can lead you to add features you hadn't previously thought of but, are the features the actual users want.&lt;/p&gt;

&lt;p&gt;Remember, feedback is a gift. It allows you to improve your product and make it something that people not only use but love. So, don’t shy away from it, embrace it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #5 - A shy launch
&lt;/h2&gt;

&lt;p&gt;And talking about being shy: So, you've built it, now what? It's time to present it to the world. Yet, remember, timing is everything. If you do a launch that is shy and badly planned, you won’t get the users (neither the revenue) you need.&lt;/p&gt;

&lt;p&gt;The first step here is to understand your audience and select the appropriate platform. &lt;a href="https://www.reddit.com/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; is excellent for open-source or projects not primarily driven by profit, while, &lt;a href="https://devhunt.org/" rel="noopener noreferrer"&gt;Dev Hunt&lt;/a&gt;, &lt;a href="https://www.producthunt.com/" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt;, and &lt;a href="https://news.ycombinator.com/" rel="noopener noreferrer"&gt;Hacker News (YC)&lt;/a&gt; are wonderful for a broader spectrum of projects. Choosing the right place to launch can mean the difference between a business and nothingness.&lt;/p&gt;

&lt;p&gt;Moreover, creating a strategic launch plan is crucial. It's not enough to just publish your project and hope for the best, although it can happen. You need to plan your launch, considering factors such as the right time to launch, the platform's mannerisms, and adjust your communication to your target audience. &lt;/p&gt;

&lt;p&gt;A well-thought-out launch plan will not only help you reach a wider audience but also increase the chances of your project's success. You should use tools like &lt;a href="https://www.screen.studio/" rel="noopener noreferrer"&gt;Screen Studio&lt;/a&gt; and &lt;a href="https://canva.com" rel="noopener noreferrer"&gt;Canva&lt;/a&gt; to help you create beautiful screen recordings and promotional images/banners.&lt;/p&gt;

&lt;p&gt;As a bonus, here's an example launch plan to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Week 1: prepare all promotional materials, like images and videos&lt;/li&gt;
&lt;li&gt;Week 2: Launch on &lt;a href="https://devhunt.org/" rel="noopener noreferrer"&gt;Dev Hunt&lt;/a&gt; + promote on social media&lt;/li&gt;
&lt;li&gt;Week 3: Launch on &lt;a href="https://www.producthunt.com/" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; + &lt;a href="https://news.ycombinator.com/show" rel="noopener noreferrer"&gt;Show HN&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Week 4 &amp;amp; beyond: Be loud! Continue to promote (without getting banned) on places like Reddit, HN, and other social media platforms.&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%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExNmFzZG14azQ1cjJrc25mY3hoNnk1aWI3bHpnNW45MHkxOWJ6ejd6ciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FP0ZRTYaCmPsJPNd3r0%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExNmFzZG14azQ1cjJrc25mY3hoNnk1aWI3bHpnNW45MHkxOWJ6ejd6ciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FP0ZRTYaCmPsJPNd3r0%2Fgiphy.webp" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And hey, you’re on the internet, so, although you might get good feedback, some users will just attack you personally. It's normal, so just ignore the angry people. It’s definitely not a great sensation to have your idea annihilated by some random reddit user, but every now and then you’ll actually get some great insight from an honest user too. It's not easy, but try to recognize which feedback to take seriously, and which to ignore :)&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExNWNraHJwazF1cGtxZWI5YmZmaXc1YzZwZms3djJ0eXY4NDhkMGZjZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/IwAZ6dvvvaTtdI8SD5/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExNWNraHJwazF1cGtxZWI5YmZmaXc1YzZwZms3djJ0eXY4NDhkMGZjZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/IwAZ6dvvvaTtdI8SD5/giphy.gif" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interested in more content like this? Follow our blog at &lt;a href="https://dev.to/wasp"&gt;Wasp - DEV Community&lt;/a&gt; and give us a star on github. This is the easiest way to support us!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.github.com/wasp-lang/wasp" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Star Wasp on GitHub 🙏&lt;/a&gt;
&lt;/p&gt;




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

&lt;p&gt;In conclusion, transforming a side project into a successful business is a journey filled with challenges and triumphs. Along this journey, each step, be it a hurdle or a victory, is a valuable opportunity to learn and grow. &lt;/p&gt;

&lt;p&gt;Each failure is not an end, but a stepping stone towards greater success, serving as a lesson that propels us forward. Every setback is a chance to reassess, refine, and come back stronger. Embrace the iterative nature of this process: continue to refine your ideas, persistently strive for improvement, and most importantly, never stop trying and learning.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>📕 Start-ups vs. Big Companies: The Best Takeaways For You To Know 📊</title>
      <dc:creator>Lucas Lima do Nascimento</dc:creator>
      <pubDate>Wed, 15 May 2024 12:00:00 +0000</pubDate>
      <link>https://forem.com/wasp/start-ups-vs-big-companies-the-best-takeaways-for-you-to-know-28n5</link>
      <guid>https://forem.com/wasp/start-ups-vs-big-companies-the-best-takeaways-for-you-to-know-28n5</guid>
      <description>&lt;p&gt;I still remember my first day joining a corporate meeting with hundreds of other employees. After a few months of having some successful freelancing jobs, I finally was able to join a big company and the mixture of anxiety and excitement was real. The challenges were now, different, the stakes were higher, and the environment was overwhelming. &lt;/p&gt;

&lt;p&gt;But that’s not the only case I got stressed out from. I also clearly remember a day while working on a small startup when I was presenting to the whole company part of the new front-end architecture we were going to use. We were small enough that every person in the meeting was listening with attention to the words I said.&lt;/p&gt;

&lt;p&gt;From being a huge voice in a start-up to becoming a small part of a larger pack in a corporation, every experience has its own set of learnings. &lt;/p&gt;

&lt;p&gt;Of course, that’s not always the case. Out there, we all know that unprepared companies exist and that’s why this article was created. Here, &lt;strong&gt;we will explore some of the&lt;/strong&gt; &lt;strong&gt;key learnings and takeaways I got while working on both, start-ups and big companies&lt;/strong&gt;, so you can learn it agnostically from the company you currently work at and even decide your next career steps on your own, to see which of them is more your fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processes and Culture
&lt;/h2&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%2F0exqcm882w9gvs11u3go.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%2F0exqcm882w9gvs11u3go.png" alt="Processes" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s start with the processes since they are the first very obvious difference. While working on a start-up most of the processes are still being implemented and a huge part of your work can actually involve &lt;strong&gt;trying and experimenting&lt;/strong&gt; with different processes for those tasks. &lt;/p&gt;

&lt;p&gt;Culture can also be in the creation phase, so, the shared values that define a company and its people, or the 'way things are done around here.' can change a lot and rapidly!&lt;/p&gt;

&lt;p&gt;Of course, this makes the experience way more chaotic but also more flexible. It’s not uncommon to juggle multiple roles and responsibilities, which can be a great opportunity to learn and grow in different aspects, for example, creating new good cultural patterns.  &lt;/p&gt;

&lt;p&gt;On the other hand, in a more corporate environment, processes are more structured and defined, which can provide stability and clear expectations, but come on the downside of bureaucracy, taking a long time to actually move through multiple pipelines and funnels.&lt;/p&gt;

&lt;p&gt;The key takeaway here is &lt;strong&gt;balance&lt;/strong&gt;. Scarcity in processes makes the whole ecosystem chaotic, which is uncomfortable, but too much process and you will not get anything done. Balancing the weights on the absence and the overflow will create a better environment for everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agility and Adaptability
&lt;/h2&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%2Fyasslnhkhhhx9oycybps.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%2Fyasslnhkhhhx9oycybps.png" alt="Agility" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Working in a startup often involves wearing multiple hats and adapting to changes on the fly. In a fast-paced startup environment, agility and adaptability are key. You have to be ready to pivot, which can make you grow a lot in terms of not getting too attached to your ideas. You also have to be ready to adjust your strategies and embrace new technologies and methodologies if they seem fit. &lt;/p&gt;

&lt;p&gt;This can be a thrilling experience that fosters creativity and innovation but also can lead in the long term to a dispersed and stressful environment (where all aspects of your company are on different technologies, and making all that chaos work is &lt;strong&gt;HARD&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;In contrast, big companies have the luxury of time and resources, allowing for more thorough planning and execution. Also, big companies tend to rely on things they already trust and generally are not too open to new things.&lt;/p&gt;

&lt;p&gt;While this is less exciting than the dynamic startup environment, it offers a different type of learning experience. Here, you can deepen your understanding of strategic planning, project management, and other aspects of business operations.&lt;/p&gt;

&lt;p&gt;The key takeaway here is learning to be agile, versatile, and adaptable &lt;strong&gt;when it’s needed&lt;/strong&gt;. If you don’t want to take my word for it, I recommend reading &lt;a href="https://mcfunley.com/choose-boring-technology" rel="noopener noreferrer"&gt;this article about boring technology&lt;/a&gt;. It’s amazingly insightful and a great read!&lt;/p&gt;




&lt;p&gt;OH! And before I forget, this article is only possible because of &lt;a href="https://wasp-lang.dev/" rel="noopener noreferrer"&gt;Wasp&lt;/a&gt;, and they’re building a full-stack React + NodeJS framework that’s really cool and it would mean a lot if you could help us by &lt;a href="https://www.github.com/wasp-lang/wasp" rel="noopener noreferrer"&gt;starring our repo on GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;By doing that, you're helping us continue to make web dev faster and easier, and bring content like this to you every week! 🚀&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%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbWFnZzJ5dGV2cXduOGluaTgyaTdvbnJ4c3ZvZGxuY3V3czQxZmZzNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FZfK4cXKJTTay1Ava29%2Fgiphy.gif" 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%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbWFnZzJ5dGV2cXduOGluaTgyaTdvbnJ4c3ZvZGxuY3V3czQxZmZzNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FZfK4cXKJTTay1Ava29%2Fgiphy.gif" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.github.com/wasp-lang/wasp" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Give us a star on GitHub 🙏&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Networking Opportunities
&lt;/h2&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%2Fflkmybnqw8ocfj0jd1bn.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%2Fflkmybnqw8ocfj0jd1bn.png" alt="Networking" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another major difference between startups and big companies is the networking opportunities they provide. Big corporations often have a wide network of employees, clients, vendors, and partners. Working in such an environment can open up numerous opportunities for networking and building valuable professional relationships. These connections can be incredibly beneficial for your career growth.&lt;/p&gt;

&lt;p&gt;On the other hand, startups, due to their smaller size, offer more intimate networking opportunities. You'll likely work closely with every member of your team, giving you the chance to form stronger relationships and learn directly from your colleagues and superiors.&lt;/p&gt;

&lt;p&gt;The key takeaway here is to embrace every connection and &lt;strong&gt;try to create a great working environment everywhere you go&lt;/strong&gt;. This will allow you to sustain rough periods more easily and you’ll certainly grow some friendships for all your life 😃&lt;/p&gt;

&lt;h2&gt;
  
  
  Impact
&lt;/h2&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%2Ft1hn0o5x8olm7sw7i21c.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%2Ft1hn0o5x8olm7sw7i21c.png" alt="Impact" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s talk about impact. On larger companies, your codebase is probably accessed by thousands (more probably millions) of people. This means that making a small change can alter the way a lot of people perceive the application and it’s enormously satisfying to see your work being utilized by so many. Unfortunately, the first time you have to deploy a small code change for a code base accessed by millions of users is ABSOLUTELY nerve-wracking — although necessary for increasing your experience and resilience.&lt;/p&gt;

&lt;p&gt;On start-ups, you’re probably looking at a codebase accessed by hundreds (with faith thousands). This means, that your work will be seen by fewer people, but, since you can create a lot more, you are probably going to create much more than just a small change. Pages, user journeys, and everything can be at your range alone or with your team. It doesn’t come without a drawback though. Since processes are more scarce, rollbacking and reverting changes can sometimes be a hard (or even worse, undocumented) process.&lt;/p&gt;

&lt;p&gt;The key takeaway here is the importance of understanding your role and the value you bring in different environments. Whether you are in a startup where your work directly drives the company's success, or in a larger corporation where your actions contribute to a broader goal, &lt;strong&gt;your work matters and you should feel proud of it.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Just to give an example, I’m really proud of making a simple product filter on a huge e-commerce website (that they use until today) and I’m also really proud of implementing/participating actively in the implementation of at least 2/3 of every component of a new design system brought up by the designers of the start-up I used to work with. &lt;strong&gt;Good work doesn't invalidate others.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&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%2F3ev801q6beoct1a0ijfa.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%2F3ev801q6beoct1a0ijfa.png" alt="All of the topics into an illustration" width="800" height="911"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this journey through the realms of startups and corporations has left you inspired, why not lend your support to &lt;a href="https://wasp-lang.dev/" rel="noopener noreferrer"&gt;Wasp&lt;/a&gt;? We're crafting tools and content to empower developers like you, whether you're coding solo or conquering corporate challenges.&lt;/p&gt;

&lt;p&gt;If you want to see more content like this, you can help us out really easily by &lt;a href="https://www.github.com/wasp-lang/wasp" rel="noopener noreferrer"&gt;giving us a star on GitHub!&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%2Fqgbmn45pia04bxt6zf83.gif" 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%2Fqgbmn45pia04bxt6zf83.gif" width="746" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.github.com/wasp-lang/wasp" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Star Wasp on GitHub 🙏&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Start-ups and big corporations both offer valuable experiences. In a start-up, you get to do different tasks, try out new things, and directly affect the company's future. It's a hands-on learning experience.&lt;/p&gt;

&lt;p&gt;In a big corporation, you have access to many resources and a structured environment. You can work with a team of diverse experts, which helps you learn and grow. The established processes, stability, and predictability can help improve your skills and shape your career.&lt;/p&gt;

&lt;p&gt;But, it's not about choosing one over the other. It's about learning to do well in both environments. Take the best parts from both and use them wherever you are. Be agile, adaptable, and open to new experiences. Both experiences are important for your career.&lt;/p&gt;

&lt;p&gt;In conclusion, every environment has its own unique set of challenges and opportunities. Embrace the differences, learn from the experiences, and leverage them to your advantage. After all, it's these diverse experiences that help you grow both personally and professionally. So, whether you're in a start-up or a big corporation, always remember - your work matters and it contributes to the bigger picture.&lt;/p&gt;

&lt;p&gt;What are your thoughts on this comparison between startups and big corporations? We'd love to hear your experiences and takeaways. Please share your thoughts in the comments below!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>career</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
