<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jay-Em</title>
    <description>The latest articles on DEV Community by Jay-Em (@joshmatthew).</description>
    <link>https://dev.to/joshmatthew</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F479268%2Fd1c72509-437e-45ba-b1a9-e8fd700bf4e9.jpeg</url>
      <title>DEV Community: Jay-Em</title>
      <link>https://dev.to/joshmatthew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joshmatthew"/>
    <language>en</language>
    <item>
      <title>The Fog: What 6 Months of AI Coding Did to My Brain</title>
      <dc:creator>Jay-Em</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:46:42 +0000</pubDate>
      <link>https://dev.to/joshmatthew/the-fog-what-6-months-of-ai-coding-did-to-my-brain-12a5</link>
      <guid>https://dev.to/joshmatthew/the-fog-what-6-months-of-ai-coding-did-to-my-brain-12a5</guid>
      <description>&lt;p&gt;I've been writing code for about five years professionally. If you count the years where I was just Googling &lt;em&gt;"why is my div not centering"&lt;/em&gt; at 2am, it goes back to 2017. I started my first real job in 2020. And for most of that time, it was just me and the editor. No autocomplete magic, no chat window, no &lt;em&gt;"here's your entire feature, boss."&lt;/em&gt; Just me, the docs, and a lot of &lt;code&gt;console.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then AI happened to me. Slowly, then all at once.&lt;/p&gt;

&lt;p&gt;This is the story of how I got faster than I've ever been in my life, and somehow started feeling like a stranger to my own code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Copilot warning I ignored
&lt;/h2&gt;

&lt;p&gt;My first taste was GitHub Copilot. And look, it was cool. It finished my thoughts before I finished them. It felt like pair programming with someone who never took a lunch break.&lt;/p&gt;

&lt;p&gt;But something weird started happening. I noticed I was forgetting syntax I &lt;em&gt;used to know cold&lt;/em&gt;. Small stuff. The exact shape of an array method. How to write a reduce without staring at it. I'd start typing, wait for the gray text, and just... tab.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wait, am I getting dumber?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was. Not really dumber, but my muscle memory was quietly rotting. The stuff I built over years was fading because I stopped using it. So I did something that felt insane at the time: I turned it off. Went back to raw typing. Felt slow. Felt good.&lt;/p&gt;

&lt;p&gt;I thought that was the whole lesson. Turns out it was just the trailer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The job that made AI non-negotiable
&lt;/h2&gt;

&lt;p&gt;This year I landed a full-time role as a full stack dev building internal AI tools. And here's the twist: using Claude Code wasn't optional. It was the job.&lt;/p&gt;

&lt;p&gt;So for the first time, I wrote an entire feature &lt;em&gt;with&lt;/em&gt; AI. Spec to feature to production. And I'm not gonna lie to you, it blew my mind. The speed was unreal. Stuff that used to take me a month was landing in days.&lt;/p&gt;

&lt;p&gt;I was hesitant at first. &lt;em&gt;This feels like cheating.&lt;/em&gt; But it works, and it ships, and when something ships that fast, guess what happens next?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The expectations move to match the speed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suddenly it's two features a week. Two. Features. A week. The kind of pace that, doing it by hand, would've been a month minimum. And the only way to hit that number is to lean all the way in. So I did.&lt;/p&gt;

&lt;p&gt;Reader, I leaned so far in I fell over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fog
&lt;/h2&gt;

&lt;p&gt;Weeks passed. Then more weeks. And one day I realized I couldn't remember what I wrote.&lt;/p&gt;

&lt;p&gt;Not "I forgot a detail." I mean I couldn't remember the &lt;em&gt;parts&lt;/em&gt;. The spec of the tools I built. How they fit together. I'd open a PR with my name on it and read it like a tourist. I was writing prompt after prompt after prompt, shipping the whole time, but not really &lt;em&gt;understanding&lt;/em&gt; any of it.&lt;/p&gt;

&lt;p&gt;It felt like floating. Like the work was happening next to me instead of through me.&lt;/p&gt;

&lt;p&gt;And it hit me how different this was from before. Back in 2020 to 2025, when everything was manual, I knew every single line. The code felt like &lt;em&gt;mine&lt;/em&gt;. Now? I felt detached from the thing I supposedly built.&lt;/p&gt;

&lt;p&gt;So I stopped. I said, okay, I need to figure out what's actually happening to me here.&lt;/p&gt;

&lt;p&gt;And yeah, I know how this sounds, but I consulted the AI about my AI problem. Fight fire with fire, I guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we actually figured out
&lt;/h2&gt;

&lt;p&gt;Here's the part that reorganized my brain.&lt;/p&gt;

&lt;p&gt;My first instinct was to blame the typing. Like the value of the old way was the physical act of writing the code. Muscle memory, keystrokes, all that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But that wasn't it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The real thing manual coding did was force a &lt;em&gt;prediction&lt;/em&gt; out of me on every single line. Before I ran anything, I had already guessed what it would do. I &lt;em&gt;had&lt;/em&gt; to. That constant loop of &lt;em&gt;"I expect this to return X"&lt;/em&gt; and then watching to see if X actually happened, that's what quietly built the model in my head. The typing was never the point. The typing was just the delivery mechanism for the guess.&lt;/p&gt;

&lt;p&gt;And AI removes the guess.&lt;/p&gt;

&lt;p&gt;It hands you working code before you've formed a single expectation about it. So the prediction step goes from mandatory to optional. And here's the brutal part: &lt;em&gt;anything optional gets skipped under a deadline.&lt;/em&gt; Especially a two-features-a-week deadline.&lt;/p&gt;

&lt;p&gt;So you ship correct code without ever having predicted what it would do. Which means the understanding never gets built. Which is the fog.&lt;/p&gt;

&lt;p&gt;It's not that I got lazy. It's that the one moment that used to compile understanding into my head got quietly deleted from the loop, and nobody sent a memo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it feels like detachment specifically
&lt;/h2&gt;

&lt;p&gt;Because my understanding stopped living in my head and moved into the AI and my notes.&lt;/p&gt;

&lt;p&gt;That's why I kept asking things like &lt;em&gt;"wait, what did we do yesterday?"&lt;/em&gt; and &lt;em&gt;"is this one done?"&lt;/em&gt; and &lt;em&gt;"is it logged?"&lt;/em&gt; I was reconstructing my own work from session summaries like I was investigating a stranger.&lt;/p&gt;

&lt;p&gt;Here's the distinction that stuck with me: &lt;strong&gt;understanding-on-demand is not the same as retained understanding.&lt;/strong&gt; I could retrieve it. I couldn't hold it. And holding it is the whole reason work feels like yours instead of something you supervised.&lt;/p&gt;

&lt;p&gt;You don't own what you can only look up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix (I'm not going back to manual, relax)
&lt;/h2&gt;

&lt;p&gt;I want to be clear, the answer is not &lt;em&gt;"delete Claude and suffer."&lt;/em&gt; That's cope. The speed is real and I'm not giving it up.&lt;/p&gt;

&lt;p&gt;The answer is to put the prediction back in on purpose, since it's not forced anymore.&lt;/p&gt;

&lt;p&gt;So now, before I read the AI's answer, I guess what it's going to say. Before I accept a diff, I state what I expect it to change and why. Out loud, in my head, in a comment, doesn't matter.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When I'm right, that's a rep. The model in my head gets stronger.&lt;/li&gt;
&lt;li&gt;When I'm wrong, &lt;em&gt;that's the exact spot the fog would have formed&lt;/em&gt;, and now it doesn't.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's slower. Obviously. Which is exactly why a deadline murders it. So I don't do it on everything. I'm not predicting the outcome of &lt;em&gt;"change this button to pink."&lt;/em&gt; I do it on the work that actually matters, the stuff I need to own six months from now.&lt;/p&gt;

&lt;p&gt;That's the trade. A little friction on purpose, in exchange for staying the author of my own work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-liner I'm leaving with
&lt;/h2&gt;

&lt;p&gt;AI didn't make me a worse developer. It made the moment where I &lt;em&gt;become&lt;/em&gt; a better one optional.&lt;/p&gt;

&lt;p&gt;The fog isn't the price of using AI. It's the price of using it without guessing first.&lt;/p&gt;

&lt;p&gt;So now I guess first. Every time that counts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And if you felt seen by any of this, that's your sign to go predict your next diff before you tab.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>neovim-final-final: Why I Can't Stop Tinkering With My Dev Environment (And Why That's Okay)</title>
      <dc:creator>Jay-Em</dc:creator>
      <pubDate>Fri, 05 Jun 2026 19:13:33 +0000</pubDate>
      <link>https://dev.to/joshmatthew/neovim-final-final-why-i-cant-stop-tinkering-with-my-dev-environment-and-why-thats-okay-3576</link>
      <guid>https://dev.to/joshmatthew/neovim-final-final-why-i-cant-stop-tinkering-with-my-dev-environment-and-why-thats-okay-3576</guid>
      <description>&lt;p&gt;Let me paint you a picture.&lt;/p&gt;

&lt;p&gt;It's a perfectly good Saturday afternoon. You had &lt;em&gt;plans&lt;/em&gt;. Real plans. Maybe you were going to finish that side project, maybe finally write some tests (lol), or at the very least touch grass for twenty minutes.&lt;/p&gt;

&lt;p&gt;Instead, you're 4 hours deep into your Neovim config, you've rewritten your &lt;code&gt;keymaps.lua&lt;/code&gt; for the third time this month, your &lt;code&gt;lazy.nvim&lt;/code&gt; plugin list has grown by six plugins you don't fully understand yet, and your repo—God help you—is named &lt;code&gt;neovim-final-final&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not &lt;code&gt;neovim-config&lt;/code&gt;. Not &lt;code&gt;dotfiles&lt;/code&gt;. &lt;strong&gt;&lt;code&gt;neovim-final-final&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because the one before it was &lt;em&gt;final&lt;/em&gt;, and that was a lie, and you knew it was a lie when you named it, and you did it anyway.&lt;/p&gt;

&lt;p&gt;Hi. My name is Josh, and I have a configuration problem. I'm not in recovery.&lt;/p&gt;




&lt;h2&gt;
  
  
  "Just Use VS Code" — A Eulogy
&lt;/h2&gt;

&lt;p&gt;I did use VS Code. For a long time, actually. It's fine. It's great, even. It has extensions for everything, it works out of the box.&lt;/p&gt;

&lt;p&gt;But at some point, something shifted. I'd be in the middle of coding and I'd think: &lt;em&gt;this editor doesn't feel like mine&lt;/em&gt;. It felt like renting an apartment versus owning a house. Everything worked, but none of it was &lt;em&gt;mine&lt;/em&gt;. I couldn't knock down a wall. I couldn't rewire the kitchen. The landlord (Microsoft) was always one update away from rearranging the furniture while I slept.&lt;/p&gt;

&lt;p&gt;So I did what any completely normal, well-adjusted developer does.&lt;/p&gt;

&lt;p&gt;I nuked it. Installed Neovim. And fell into a rabbit hole I haven't climbed out of since.&lt;/p&gt;

&lt;p&gt;Credit where it's due: a big part of what pushed me over the edge was &lt;a href="https://www.youtube.com/@ThePrimeagen" rel="noopener noreferrer"&gt;ThePrimeagen&lt;/a&gt;. If you've never watched him, he's a developer who moves through code so fast it looks illegal, and he does it all in Neovim. Watching him work made me feel like I was using a tricycle when I could be riding a motorcycle. He didn't just inspire me to switch editors — he inspired me to &lt;em&gt;tinker&lt;/em&gt;. To care about the tools. To never just accept the defaults.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Config Is Always a Disaster (And That's the Point)
&lt;/h2&gt;

&lt;p&gt;Here's what nobody tells you about switching to Neovim: &lt;strong&gt;the first week is a humbling experience.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Honestly, my first encounter with Vim wasn't even intentional. I made a &lt;code&gt;git commit&lt;/code&gt; without the &lt;code&gt;-m&lt;/code&gt; flag, and suddenly I was staring at a screen I did not ask for. I had no idea what it was. I just knew I was stuck. Couldn't type, couldn't exit, couldn't do anything. I literally Googled "stuck in commit can't exit" — not even "how to exit vim" — because I didn't even know it &lt;em&gt;was&lt;/em&gt; Vim. That Stack Overflow question with 2 million views? I am one of those 2 million people.&lt;/p&gt;

&lt;p&gt;And yet, somehow, that cursed moment planted a seed.&lt;/p&gt;

&lt;p&gt;Fast forward to actually switching to Neovim full time: you forget how to save files. You accidentally enter some mode you've never seen before and the only way out is to close the terminal and pretend it never happened.&lt;/p&gt;

&lt;p&gt;But then something clicks. You learn that every single thing—every keybind, every behavior, every color on your screen—is a &lt;em&gt;choice you made&lt;/em&gt;. Nobody pre-packaged it for you. When your LSP starts working and Telescope fuzzy-finds a file in 0.1 seconds and your statusline shows exactly the info you care about and nothing else...&lt;/p&gt;

&lt;p&gt;That feeling? That's ownership. That's craftsmanship. That's the closest thing a programmer gets to carving their name into something.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Configs That Taught Me More Than Any Tutorial
&lt;/h2&gt;

&lt;p&gt;Here's the dirty secret about tinkering with your dev environment: &lt;strong&gt;it's not actually about the tools.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sure, I love my &lt;code&gt;which-key&lt;/code&gt; setup. I love that I've bound &lt;code&gt;&amp;lt;leader&amp;gt;\&lt;/code&gt; to Telescope and &lt;code&gt;&amp;lt;leader&amp;gt;gg&lt;/code&gt; to NeoGit and my fingers just &lt;em&gt;know&lt;/em&gt; where to go without thinking. I love that my Neovim is fast—genuinely, disgustingly fast—in a way that VS Code on a good day can only dream about.&lt;/p&gt;

&lt;p&gt;But what I actually &lt;em&gt;learned&lt;/em&gt; from all of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How Lua works&lt;/strong&gt;, because your Neovim config is just a Lua program. You are literally programming your editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How LSPs work&lt;/strong&gt;—like, actually work. What a language server protocol &lt;em&gt;is&lt;/em&gt;, why it exists, what &lt;code&gt;mason.nvim&lt;/code&gt; is doing when it installs one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How terminal multiplexing works&lt;/strong&gt;, because once you go Neovim you inevitably end up in Tmux, splitting panes, managing sessions, and feeling like a wizard in a movie about hackers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to read documentation&lt;/strong&gt;, because Neovim will teach you patience or it will break you. There is no middle ground.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that came from a course. It came from breaking things, reading the source code of plugins at 1 AM, and occasionally nuking the whole config and starting over.&lt;/p&gt;

&lt;p&gt;Which brings me to something important.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Nuclear Option Is Not Failure. It's a Feature.
&lt;/h2&gt;

&lt;p&gt;I've deleted my Neovim config and started from scratch multiple times.&lt;/p&gt;

&lt;p&gt;Every time, I told myself &lt;em&gt;this is the final one&lt;/em&gt;. Every time, I was wrong. Hence: &lt;code&gt;neovim-final-final&lt;/code&gt;. (Spoiler: there will be a &lt;code&gt;neovim-final-final-v2&lt;/code&gt;. I've made my peace with this.)&lt;/p&gt;

&lt;p&gt;And you know what? Each restart made my config &lt;em&gt;better&lt;/em&gt;. Because I stopped copying configurations I found online wholesale and started understanding &lt;em&gt;why&lt;/em&gt; things were structured a certain way. I stopped installing plugins because some YouTuber had them and started asking "do I actually need this, or does it just look cool in a demo?"&lt;/p&gt;

&lt;p&gt;The tinkering &lt;em&gt;is&lt;/em&gt; the learning. The mess &lt;em&gt;is&lt;/em&gt; the process.&lt;/p&gt;

&lt;p&gt;There's a certain type of programmer who looks at someone like me and says "that's a waste of time, just use the defaults." And look, I get it. Pragmatism is a virtue.&lt;/p&gt;

&lt;p&gt;But there's something those programmers are missing: &lt;strong&gt;the act of configuring your environment forces you to understand it.&lt;/strong&gt; You can't set up an LSP without learning what an LSP is. You can't write a keymap without thinking about your own workflow. You can't structure a Lua config without picking up at least some programming instincts.&lt;/p&gt;

&lt;p&gt;Tinkerers aren't wasting time. They're learning sideways.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tmux: The Part Where I Become Insufferable at Screen Shares
&lt;/h2&gt;

&lt;p&gt;I need to talk about Tmux for a second.&lt;/p&gt;

&lt;p&gt;Tmux is a terminal multiplexer, which is a fancy way of saying "multiple terminals in one terminal, with sessions that persist even when you close everything." It sounds niche. It sounds unnecessary. Every person I've shown it to in a screen share has said some variation of "wait, what just happened" followed by either genuine curiosity or quiet concern for my mental health.&lt;/p&gt;

&lt;p&gt;I love it.&lt;/p&gt;

&lt;p&gt;I have a Tmux session for every project. I detach, I reattach, I split panes horizontally and run my dev server on one side and my Neovim on the other. My workflow is a single terminal window and nothing else. No alt-tabbing. No losing focus. Just me, my keyboard, and a black screen full of text that somehow builds web applications.&lt;/p&gt;

&lt;p&gt;Is this more efficient than having a normal setup? Genuinely, yes. I think so.&lt;/p&gt;

&lt;p&gt;Is part of the appeal that it looks like I'm doing something extremely technical and impressive at all times? &lt;/p&gt;

&lt;p&gt;...also yes. I'm not a saint.&lt;/p&gt;

&lt;p&gt;There's also this other thing that happens during screen shares that I didn't expect: occasionally, someone will see my setup and just &lt;em&gt;light up&lt;/em&gt;. Not confusion — recognition. They'll say something like "wait, are you using Neovim and Tmux?" and suddenly we're talking like old friends. It's happened with developers I've never met before, halfway across the world — and as a Filipino working remotely, that moment of unexpected connection hits different. It's like stumbling into a secret club. The terminal is the handshake. It's a small community, but it's ours.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why You Should Try It (Even If You Don't Stick With It)
&lt;/h2&gt;

&lt;p&gt;Here's my honest take: &lt;strong&gt;you don't have to use Neovim or Tmux forever.&lt;/strong&gt; You don't have to commit. You don't have to throw away VS Code or Cursor or whatever IDE is paying your rent right now.&lt;/p&gt;

&lt;p&gt;But you should tinker with &lt;em&gt;something&lt;/em&gt; outside your comfort zone. Configure something from scratch. Break it. Fix it. Break it again. Name the repo something embarrassing like &lt;code&gt;neovim-final-final&lt;/code&gt; because that's just the natural endpoint of caring about your tools.&lt;/p&gt;

&lt;p&gt;Because here's what I've found: &lt;strong&gt;programmers who understand their environment write better code.&lt;/strong&gt; Not because Vim makes you smarter (it doesn't, I've tested this on myself), but because the curiosity that drives you to customize your editor is the same curiosity that drives you to understand your codebase. It's the same instinct.&lt;/p&gt;

&lt;p&gt;The tinkerers are the ones who ask "why does this work this way?" instead of accepting it.&lt;/p&gt;

&lt;p&gt;And that question—&lt;em&gt;why does this work this way?&lt;/em&gt;—is the most important question in this entire profession.&lt;/p&gt;




&lt;h2&gt;
  
  
  Go Break Your Config
&lt;/h2&gt;

&lt;p&gt;Stop using default settings for everything (unless you have a deadline, in which case: godspeed, use VS Code, no judgment).&lt;/p&gt;

&lt;p&gt;But when you have a free Saturday? Crack open a Neovim config. Spend four hours on a keymap. Name the repo something ridiculous. Feel the specific joy of your editor doing &lt;em&gt;exactly&lt;/em&gt; what you want it to do.&lt;/p&gt;

&lt;p&gt;It's worth it. I promise. And if you nuke the whole thing and start over, that's fine too.&lt;/p&gt;

&lt;p&gt;That's just &lt;code&gt;neovim-final-final-v2&lt;/code&gt; waiting to happen.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this? Follow me for more programming blogs where I justify my terrible life choices with technical reasoning.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/jmtalplacido" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/JoshMatthew" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jmct.dev" rel="noopener noreferrer"&gt;My Website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Catch you in the next one. 🚀&lt;/p&gt;

</description>
      <category>pro</category>
      <category>neovim</category>
    </item>
    <item>
      <title>I Built an ORM That Starts With JSON So You Can Stop Overthinking Your Database</title>
      <dc:creator>Jay-Em</dc:creator>
      <pubDate>Thu, 19 Feb 2026 03:36:05 +0000</pubDate>
      <link>https://dev.to/joshmatthew/i-built-an-orm-that-starts-with-json-so-you-can-stop-overthinking-your-database-2439</link>
      <guid>https://dev.to/joshmatthew/i-built-an-orm-that-starts-with-json-so-you-can-stop-overthinking-your-database-2439</guid>
      <description>&lt;p&gt;You know that thing where you have a project idea at 1am, you're hyped, and then you spend the next 2 hours setting up Postgres, writing migrations, configuring connection strings, and by the time you're done your motivation is gone and you go to bed?&lt;/p&gt;

&lt;p&gt;Yeah. That kept happening to me. So I built something about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SeedORM?
&lt;/h2&gt;

&lt;p&gt;SeedORM is a Node.js ORM that stores everything in local JSON files. No database server, no Docker, no connection strings. You define your models and start building immediately.&lt;/p&gt;

&lt;p&gt;Then when your project is ready for the real world, you migrate to Postgres with one command. Same models, same queries, same API. Nothing changes except where the data lives.&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;seedorm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every side project I start follows the same pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cool idea hits me&lt;/li&gt;
&lt;li&gt;Create new folder, &lt;code&gt;npm init&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Okay now I need a database&lt;/li&gt;
&lt;li&gt;Do I use Postgres? MongoDB? SQLite?&lt;/li&gt;
&lt;li&gt;Spend 30 minutes setting up Docker, env vars, connection pooling&lt;/li&gt;
&lt;li&gt;Write migration files&lt;/li&gt;
&lt;li&gt;I'm tired now&lt;/li&gt;
&lt;li&gt;Abandon project&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted something where step 3 is just... skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Define your models like you normally would:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SeedORM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FieldType&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;seedorm&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;db&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;SeedORM&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&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;User&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;model&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;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fields&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FieldType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FieldType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;unique&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;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FieldType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Number&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;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No database running. No config file pointing to &lt;code&gt;localhost:5432&lt;/code&gt;. It just writes to JSON files in a &lt;code&gt;data/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Now use it like any ORM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="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;Josh&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;josh@hey.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Query&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adults&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&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;// Update&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Delete&lt;/span&gt;
&lt;span class="k"&gt;await&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;delete&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;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Relations
&lt;/h2&gt;

&lt;p&gt;It supports the relation types you'd expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Post&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;model&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;posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FieldType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&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;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FieldType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;relations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;belongsTo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;foreignKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;authorId&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;hasMany, belongsTo, manyToMany. They all work the same way when you eventually switch to Postgres.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Studio
&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%2Fkk2neq6vy2e52p6krqpq.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%2Fkk2neq6vy2e52p6krqpq.png" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I got tired of opening JSON files to check my data, so I built a visual browser for it. Run &lt;code&gt;seedorm studio&lt;/code&gt; and you get a web UI at &lt;code&gt;localhost:4200&lt;/code&gt; where you can browse collections, search across fields, paginate through documents, and edit records.&lt;/p&gt;

&lt;p&gt;It's nothing fancy. It's just nice to have when you're building and want to see what's in your database without writing a query.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-Collection File Storage
&lt;/h2&gt;

&lt;p&gt;One thing that bugged me early on was that everything was stored in a single &lt;code&gt;seedorm.json&lt;/code&gt; file. With a few thousand documents across multiple collections, that file gets massive.&lt;/p&gt;

&lt;p&gt;So now each collection gets its own file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data/
  users.json
  posts.json
  comments.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file is minified (single line), writes only happen for collections that changed, and if you have an old &lt;code&gt;seedorm.json&lt;/code&gt; from a previous version it auto-migrates on startup. You don't have to do anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  When You're Ready for Postgres
&lt;/h2&gt;

&lt;p&gt;Your project took off. Congrats. Time for a real database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seedorm migrate to postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your models stay the same. Your queries stay the same. You just change the adapter config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&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;SeedORM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&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;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgresql://localhost:5432/myapp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole point. Build fast with JSON, switch when it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It's NOT
&lt;/h2&gt;

&lt;p&gt;Let me be clear about what SeedORM is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's not a Prisma replacement for your production app with 10 million users&lt;/li&gt;
&lt;li&gt;It's not meant for high-concurrency workloads&lt;/li&gt;
&lt;li&gt;It's not trying to be the last ORM you'll ever use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's for prototyping, side projects, hackathons, and that 1am idea that deserves to exist without a 30 minute setup ritual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&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;seedorm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/JoshMatthew/seedorm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/seedorm" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try it, I'd genuinely love to hear what you think. What's missing? What's annoying? What would make you actually use this?&lt;/p&gt;

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

</description>
      <category>javascript</category>
      <category>node</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Dart Extensions: Unleashing the Power of Your Code! 🚀</title>
      <dc:creator>Jay-Em</dc:creator>
      <pubDate>Sat, 18 May 2024 02:04:50 +0000</pubDate>
      <link>https://dev.to/joshmatthew/dart-extensions-unleashing-the-power-of-your-code-5h8m</link>
      <guid>https://dev.to/joshmatthew/dart-extensions-unleashing-the-power-of-your-code-5h8m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Hello everyone! Welcome to another exciting post. I hope you'll find this one just as useful!! Arigatogozaimasuuu! 🎉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you ever felt limited by the built-in methods in Dart? Ever wished you could add your own methods to existing classes? Well, you're in luck because today I'm going to show you how to harness the magic of Dart extensions! 🌟&lt;/p&gt;

&lt;p&gt;Extensions allow you to add new functionality to existing libraries. They're a game-changer for making your code cleaner and more readable. Let's dive right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dart SDK&lt;/li&gt;
&lt;li&gt;A Dart project setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started with Dart Extensions
&lt;/h2&gt;

&lt;p&gt;First things first, make sure you have Dart installed. If you don't, you can download it from &lt;a href="https://dart.dev/get-dart" rel="noopener noreferrer"&gt;Dart's official website&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your First Extension
&lt;/h3&gt;

&lt;p&gt;Let's say you want to add a new method to the &lt;code&gt;String&lt;/code&gt; class. Here's how you can do it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your Dart project and create a new file called &lt;code&gt;string_extensions.dart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside &lt;code&gt;string_extensions.dart&lt;/code&gt;, add the following code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="n"&gt;StringExtensions&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isPalindrome&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;this&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reversed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What did we just do? We created an extension on the &lt;code&gt;String&lt;/code&gt; class that adds a method called &lt;code&gt;isPalindrome&lt;/code&gt;. This method checks if a string reads the same backward as forward. Cool, right? 😎&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Your Extension
&lt;/h3&gt;

&lt;p&gt;Now, let's use this new method in our project.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import your extension into your main Dart file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'string_extensions.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Use the new method on any string:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'level'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Is "&lt;/span&gt;&lt;span class="si"&gt;$word&lt;/span&gt;&lt;span class="s"&gt;" a palindrome? &lt;/span&gt;&lt;span class="si"&gt;${word.isPalindrome()}&lt;/span&gt;&lt;span class="s"&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;Run your Dart program, and you should see the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is "level" a palindrome? true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom! You've just extended the String class with a custom method. 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  More Practical Examples
&lt;/h2&gt;

&lt;p&gt;Let's explore some more practical examples to get you comfortable with extensions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Adding a &lt;code&gt;toCapitalized&lt;/code&gt; Method
&lt;/h3&gt;

&lt;p&gt;Sometimes you might need to capitalize the first letter of a string. Let's create an extension for that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="n"&gt;CapitalizedString&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;toCapitalized&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;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${this[0].toUpperCase()}${this.substring(1)}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 2: Adding a &lt;code&gt;num&lt;/code&gt; Extension
&lt;/h3&gt;

&lt;p&gt;You can also extend numeric types. Let's add a method to double a number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="n"&gt;NumExtensions&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="n"&gt;doubled&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;this&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&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;
  
  
  Using the New Extensions
&lt;/h3&gt;

&lt;p&gt;Don't forget to import your extensions and use them in your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'string_extensions.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'dart'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Capitalized: &lt;/span&gt;&lt;span class="si"&gt;${name.toCapitalized()}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Doubled: &lt;/span&gt;&lt;span class="si"&gt;${value.doubled()}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;That's it! You've just learned how to create and use Dart extensions to make your code more powerful and expressive. 🎉&lt;/p&gt;

&lt;p&gt;Extensions are a fantastic way to add custom functionality to existing classes without modifying their source code. Use them wisely to keep your code clean and maintainable.&lt;/p&gt;

&lt;p&gt;I hope you've enjoyed this post and found it useful. Stay tuned for more exciting content! 🚀&lt;/p&gt;

</description>
      <category>dart</category>
      <category>programming</category>
      <category>extensions</category>
      <category>coding</category>
    </item>
    <item>
      <title>Auto update React app in Heroku upon git push on GitHub</title>
      <dc:creator>Jay-Em</dc:creator>
      <pubDate>Sat, 16 Jul 2022 12:28:45 +0000</pubDate>
      <link>https://dev.to/joshmatthew/auto-update-react-app-in-heroku-upon-git-push-on-github-2m8i</link>
      <guid>https://dev.to/joshmatthew/auto-update-react-app-in-heroku-upon-git-push-on-github-2m8i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hello everyone! This is going to be my first ever post here. I hope you'll find this useful!! Arigatogozaimasuuu!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: Heroku is not free anymore, these tutorial is outdated and will be updated soon&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you ever wondered if it is possible to just push your application update in your Github repo and then it will auto re-deploy your app in Heroku? Well, stop wondering because today I will share you the process on how to setup one in your React app project and save you the hassle of searching it on your own!&lt;/p&gt;

&lt;p&gt;We will utilize the use of what we call, "the magical" Github Actions. This is the main key that will unlock the possibility on how to make this idea come true.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I will assume that you already know how to create a Github repo, create an application in Heroku, and know the basics of Git. With that in mind, let us now start doing it!&lt;/p&gt;
&lt;/blockquote&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="//heroku.com"&gt;Heroku account&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/" rel="noopener noreferrer"&gt;Github account&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up Github and Heroku
&lt;/h2&gt;

&lt;p&gt;1) First, you need to create a Github repository and push your React project there. In my case, I just pushed the default React app created by using npx create-react-app. &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%2Fa9vdvuakom53w050da91.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%2Fa9vdvuakom53w050da91.png" alt="github repo" width="800" height="488"&gt;&lt;/a&gt; &lt;br&gt;
2) After that, you can now create an app in Heroku. Just leave the tabs open for the moment ;)&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%2F4cndmawsspb28fjwgkoo.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%2F4cndmawsspb28fjwgkoo.png" alt="heroku app" width="799" height="428"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up your React app
&lt;/h2&gt;

&lt;p&gt;3) Now in your project's root directory, create a new folder or a directory if that's what you want to call it, name it as &lt;code&gt;server&lt;/code&gt; and then create a new file inside naming &lt;code&gt;app.js&lt;/code&gt; and paste this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&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;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&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;publicPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicPath&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is up on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What in the world does this code do? Well, if you read it carefully, it's just serving your app's public folder to the browser.&lt;/p&gt;

&lt;p&gt;4) The project should look something like this.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsb0rml1milocjqy0vtl.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%2Fzsb0rml1milocjqy0vtl.png" alt="project structure" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) Now open your favorite terminal, navigate inside the &lt;code&gt;server&lt;/code&gt; directory of your React app, and initiate node.js by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;--y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;6) Now from here, I recommend using &lt;a href="https://www.npmjs.com/package/yarn" rel="noopener noreferrer"&gt;yarn&lt;/a&gt;, and then install express.js by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7) After installing express you should probably add a &lt;code&gt;.gitignore&lt;/code&gt; file containing &lt;code&gt;node_modules&lt;/code&gt; inside. You don't want to push it in Heroku because of its massive size. It should look like this.&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%2Fybyqnuso0id8rr6szkz3.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%2Fybyqnuso0id8rr6szkz3.png" alt="gitignore" width="514" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8) Navigate back to our project's root directory and create a &lt;code&gt;Procfile&lt;/code&gt; file and paste this inside&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web: node ./server/app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should now look something like this.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5ymlnhfkljh1k6mnzus.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%2Fs5ymlnhfkljh1k6mnzus.png" alt="procfile" width="670" height="464"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the Github action
&lt;/h2&gt;

&lt;p&gt;9) After adding that, open a new terminal and login to Heroku by typing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If heroku is unknown to your system, you should &lt;a href="https://devcenter.heroku.com/articles/heroku-cli" rel="noopener noreferrer"&gt;install&lt;/a&gt; the Heroku cli first. It will open a login prompt in your browser. Just follow the instructions there and if it works, you should see something like this. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvn72f6hwt7kkt9yfrc9m.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%2Fvn72f6hwt7kkt9yfrc9m.png" alt="heroku login" width="721" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;10) After successfully logging in, switch back to your previous terminal or open a new one and navigate back to your project's root directory. Commit all of your changes to your local branch, and add a remote branch for Heroku by typing in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku git:remote &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;name of your app]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should look like this.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjeh5gmv1uqwgt84xy98i.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%2Fjeh5gmv1uqwgt84xy98i.png" alt="add heroku branch" width="719" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;11) Now push your React app to Heroku by typing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push heroku &lt;span class="o"&gt;[&lt;/span&gt;your master branch]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My master branch is &lt;code&gt;main&lt;/code&gt; so it should look like this.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdekoghau5woztivo89w4.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%2Fdekoghau5woztivo89w4.png" alt="start" width="352" height="77"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyocfnd53kbstfnksqjj.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%2Fkyocfnd53kbstfnksqjj.png" alt="done" width="393" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;12) After pushing it to Heroku successfully, from your project's root directory, create a new directory following this structure.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdrjdfyfqc5t7szcxyxk.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%2Fxdrjdfyfqc5t7szcxyxk.png" alt="structure" width="231" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;13) In the newly created file &lt;code&gt;main.yml&lt;/code&gt;, paste this code inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;gitmainbranch&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;akhileshns/heroku-deploy@v3.12.12&lt;/span&gt; &lt;span class="c1"&gt;# This is the action&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;heroku_api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.HEROKU_API_KEY}}&lt;/span&gt;
          &lt;span class="na"&gt;heroku_app_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[herokuappname]"&lt;/span&gt; &lt;span class="c1"&gt;#Must be unique in Heroku&lt;/span&gt;
          &lt;span class="na"&gt;heroku_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[emailloggedinheroku]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;em&gt;[gitmainbranch]&lt;/em&gt; with your master branch or main branch.&lt;br&gt;
Replace &lt;em&gt;[herokuappname]&lt;/em&gt; with your Heroku app name.&lt;br&gt;
Replace &lt;em&gt;[emailloogedinheroku]&lt;/em&gt; with the email you use in your Heroku account. &lt;/p&gt;

&lt;p&gt;This code is just a simple Github workflow that tells Github to auto update Heroku upon changes in the main branch of your React application.&lt;/p&gt;

&lt;p&gt;With my setup, it should look like this.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtjt3yobgl9jvgocp3sg.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%2Fqtjt3yobgl9jvgocp3sg.png" alt="yml" width="714" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;14) In your Heroku account, go to account settings and reveal your API key, and guess what? Copy it.&lt;br&gt;
 &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff37s11dzemv4oty8y9al.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%2Ff37s11dzemv4oty8y9al.png" alt="api key" width="799" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;15) In your Github repo, go to your repository settings and add a new secret named &lt;code&gt;HEROKU_API_KEY&lt;/code&gt; and paste the API key you copied from Heroku.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiks3s5we5b9a5p93erbz.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%2Fiks3s5we5b9a5p93erbz.png" alt="secret" width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;16) We're almost done!!! Now save all files, commit all the changes and push it to your Github repo by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should be something like this. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft04gukln100fkepiieam.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%2Ft04gukln100fkepiieam.png" alt="commit" width="722" height="455"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  You're done! Congrats!
&lt;/h2&gt;

&lt;p&gt;17) Hooray!! We're done! Try making some changes in your app and push it on Github repo by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or by merging a certain branch to your master branch. This action will be triggered whenever there's a change in your master branch. Once you've pushed a change, you'll see something like this in your action tab.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblmneb1npyg5svhawumb.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%2Fblmneb1npyg5svhawumb.png" alt="action" width="799" height="164"&gt;&lt;/a&gt;&lt;br&gt;
 You'll also gonna see the logs in your Heroku app&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9ctxv55sdxm00sik3di.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%2Fw9ctxv55sdxm00sik3di.png" alt="Heroku log" width="482" height="152"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Thanks!
&lt;/h2&gt;

&lt;p&gt;That's it! You have now successfully setup your Github-Heroku workflow that will auto update your deployed React app on the go. &lt;br&gt;
I hope you've liked my first content here at DEV! I will post more in the future! Please see my &lt;a href="https://joshmatthew.herokuapp.com" rel="noopener noreferrer"&gt;website&lt;/a&gt; to know me more! Thanks!&lt;/p&gt;

</description>
      <category>github</category>
      <category>react</category>
      <category>heroku</category>
      <category>workflow</category>
    </item>
  </channel>
</rss>
