<?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: Katya Pavlopoulos</title>
    <description>The latest articles on DEV Community by Katya Pavlopoulos (@katya_pavlopoulos).</description>
    <link>https://dev.to/katya_pavlopoulos</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%2F485876%2Fec8e61ab-ec25-4c03-8420-502810573341.jpeg</url>
      <title>DEV Community: Katya Pavlopoulos</title>
      <link>https://dev.to/katya_pavlopoulos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/katya_pavlopoulos"/>
    <language>en</language>
    <item>
      <title>How I Built an App with Cursor AI Agent for the First Time (the Good, the Bad, and the Drama)</title>
      <dc:creator>Katya Pavlopoulos</dc:creator>
      <pubDate>Fri, 24 Jan 2025 15:31:17 +0000</pubDate>
      <link>https://dev.to/katya_pavlopoulos/how-i-built-an-app-with-cursor-ai-agent-for-the-first-time-the-good-the-bad-and-the-drama-168o</link>
      <guid>https://dev.to/katya_pavlopoulos/how-i-built-an-app-with-cursor-ai-agent-for-the-first-time-the-good-the-bad-and-the-drama-168o</guid>
      <description>&lt;p&gt;One January morning, I wrote, &lt;code&gt;using these project instructions, architect and implement a solution&lt;/code&gt;, then sat back and sipped my coffee while AI built a production-ready app following best practices in minutes.&lt;/p&gt;

&lt;p&gt;OK, that's not exactly what happened in my case, but I've heard so many reports from others that new AI tools are not just 10xing their productivity but even enabling them to build and deploy apps with no engineering effort on their part. If that's you, please comment with your best tips and tricks, because I am not there yet. Help a girl out 😅 &lt;/p&gt;

&lt;p&gt;As a developer, I've already integrated AI into my toolkit, primarily for prototyping interfaces. However, my experience has involved considerable back-and-forth with the AI, lots of hand-holding, and still required me to handle most of the heavy lifting. This didn't sound at all like the stories I saw trending on X and Linkedin almost every day, so that's how, one morning, I found myself setting up Cursor.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;I installed Cursor. It has a generous free trial for 2 weeks, and then you can get a monthly subscription. &lt;/li&gt;
&lt;li&gt;I created an empty folder for Cursor to write the files in.&lt;/li&gt;
&lt;li&gt;For my initial settings, I had claude-3.5-sonnet model, in "normal" mode. I later changed this to "agent."&lt;/li&gt;
&lt;li&gt;I created a .cursorrules file in the folder, which serves as general context for how I want AI to act and respond. It starts with "You are an expert senior developer specializing in modern web development..." and instructs the AI to analyze my requests, come up with a plan before executing, and follow best practices in web development. There are many sample .cursorrules available online, I just picked one that focused on fullstack React/Next/Typescript development.&lt;/li&gt;
&lt;li&gt;I created a simple project request for AI to implement, and I put it in a projectinstructions.txt file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ProjectInstructions.txt
&lt;/h3&gt;

&lt;p&gt;This was a simple project brief, saying I'm an ad agency that needs a web portal where users can log in to create, view, and edit their advertising campaigns. I listed some fields I would want the users to provide, asked for Next/Typescript/Tailwind stack, and specified that pages need to be auth-protected. That's it. I tried not to be too prescriptive, since my goal was to see how AI would make engineering decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Attempt
&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%2Fkgah6wawg52us724a4kv.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%2Fkgah6wawg52us724a4kv.png" alt="First message" width="800" height="410"&gt;&lt;/a&gt;&lt;br&gt;
Cursor immediately launched into planning the core architecture, creating types and interfaces to work with the data, and writing out the logic to configure auth. It was creating files on the go, and I noticed it created a &lt;code&gt;src&lt;/code&gt; folder, which I thought neither React nor Next.js really used anymore (I've only seen &lt;code&gt;pages&lt;/code&gt; and &lt;code&gt;app&lt;/code&gt; used in recent years). Was it using an outdated version of Next? &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%2F5oufryc5hmg81p9vwt80.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%2F5oufryc5hmg81p9vwt80.png" alt="Prompt: " width="800" height="613"&gt;&lt;/a&gt;&lt;br&gt;
Cursor informed me that indeed the project it just set up was set up incorrectly 🤦‍♀️ ”We should start by creating a new Next.js project with the &lt;em&gt;latest&lt;/em&gt; version and &lt;em&gt;proper&lt;/em&gt; dependencies.” Okay fam, idk why you didn’t do that from the start, but let's go.&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%2F8l8cackz4k3ne89zmznq.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%2F8l8cackz4k3ne89zmznq.png" alt="Installing Shadcn UI" width="800" height="506"&gt;&lt;/a&gt;&lt;br&gt;
Moving on to shadcn, a beautifully simple component library. In Cursor, when you need to install something the AI will not install it for you but it will write the script for you to run. When I ran this shadcn command, it gave me an error:&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%2Fr0rxpto47g132oxxvpii.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%2Fr0rxpto47g132oxxvpii.png" alt="shadcn error" width="800" height="111"&gt;&lt;/a&gt;&lt;br&gt;
I asked AI to debug this error in a side chat, and it asked me to create a &lt;em&gt;new&lt;/em&gt; Next.js project to ensure that everything installed correctly. Personally, I thought this was a weird place to start debugging, so I pulled up shadcn documentation and saw that &lt;em&gt;the script Cursor was using to install it was incorrect&lt;/em&gt;. Once I ran the right script, it began installing but then informed me that it’s incompatible with React 19 that Cursor set up for this project 😬&lt;/p&gt;

&lt;p&gt;I just wanted to test out the workflow with Cursor so I didn’t care as much about using the latest versions of everything. Downgrading to the last stable version seemed like the best way forward (or at least the path of least resistance).&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%2Fcp3z1e0ohupu93hbi5br.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%2Fcp3z1e0ohupu93hbi5br.png" alt="Starting over" width="800" height="559"&gt;&lt;/a&gt;&lt;br&gt;
Despite me explicitly asking for the previous version of Next.js (14), Cursor tells me to run a script installing the latest Next.js (15).&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%2Fuvz7kj0icuw100xu1i59.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%2Fuvz7kj0icuw100xu1i59.png" alt="Fixing Next.js installation" width="800" height="439"&gt;&lt;/a&gt;&lt;br&gt;
I repeated my instructions to downgrade to Next14, and it defaulted to the earliest version 14 instead of the latest release. My fault, I wasn't specific enough.&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%2F9cpapro1tby27z87dsdi.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%2F9cpapro1tby27z87dsdi.png" alt="Me being specific" width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
And more specific&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%2Fny8yyu1aimyu2lyxuw8u.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%2Fny8yyu1aimyu2lyxuw8u.png" alt="And more specific" width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
At this point, I had 0 trust that the project was set up correctly. I also noticed that, in the left sidebar, it was creating multiple package.json files at different levels in the project folder, and same with config files. No idea why. Sure I could just delete the unnecessary files and change things myself, but I really wanted to remove myself from the workflow as much as possible and see how AI would do. And so far, it wasn't doing so great. I decided to try something different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Again, but with AI Agent
&lt;/h3&gt;

&lt;p&gt;I made a new folder with the same projectinstructions.txt and .cursorrules, same claude 3.5 sonnet model, but I switched the mode from 'normal' to 'agent.' I wanted to see if AI would do better if I gave it more freedom to make decisions on its own. &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%2Fpz3com74oe6hzziu5nto.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%2Fpz3com74oe6hzziu5nto.png" alt="Attempt number 2" width="800" height="255"&gt;&lt;/a&gt;&lt;br&gt;
While saying it will use Nextjs 14, the agent still went with &lt;code&gt;create-next-app@latest&lt;/code&gt; script which installs version 15. I groaned inwardly, but I was curious how the agent would manage incompatible dependency versions, if any arose, so I went with 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%2Fxfi2kjkw97xo8i9qxj6m.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%2Fxfi2kjkw97xo8i9qxj6m.png" alt="clean install" width="800" height="128"&gt;&lt;/a&gt;&lt;br&gt;
Running this script didn’t install anything. Maybe it was because the agent was trying to name the project &lt;code&gt;.&lt;/code&gt;? I ran the command again but with a different project name and it worked. The files installed, and once again I was looking at the &lt;code&gt;src&lt;/code&gt; folder. I realized later, after looking at the script more closely, that the agent added &lt;code&gt;--src-dir&lt;/code&gt; as part of the installation script. Why? Who knows. The only thing in the &lt;code&gt;src&lt;/code&gt; was the &lt;code&gt;app&lt;/code&gt; folder that contained everything else, so &lt;code&gt;src&lt;/code&gt; didn't provide any extra benefits, but at least now I knew what kept creating the &lt;code&gt;src&lt;/code&gt; folder. &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%2Fqbpv64bko6bvzhg2dwmu.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%2Fqbpv64bko6bvzhg2dwmu.png" alt="finally coding!" width="800" height="383"&gt;&lt;/a&gt;&lt;br&gt;
Finally, after some setup hiccups, I got the agent to start writing code! It started by working on setting up authentication with NextAuth, so I sat back and watched as it created files, wrote code, checked its own code (!), and even went into debugging mode when it ran into issues, all without additional prompts from me (!!). I waited for it to finish setting up auth, eager to see the result, so imagine my surprise when the agent informed me about 3 minutes later that it finished everything. Not just auth, everything 🤯 &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%2F6wmgrlej9rcvn0m25asz.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%2F6wmgrlej9rcvn0m25asz.png" alt="grand finale?" width="800" height="140"&gt;&lt;/a&gt;&lt;br&gt;
It even made a list of suggested future improvements! &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%2Fxiaa6eec7g0f3apciw5o.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%2Fxiaa6eec7g0f3apciw5o.png" alt="future iterations?" width="800" height="86"&gt;&lt;/a&gt;&lt;br&gt;
Whaaaat? 3 minutes, and I have a production ready app? I ran &lt;code&gt;npm run dev&lt;/code&gt; to serve it locally and see what the agent built!&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%2F087w31g0ab7xb4em10mh.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%2F087w31g0ab7xb4em10mh.png" alt="nextjs boilerplate page" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
Umm... That's just the boilerplate Next.js landing page you get when you first install it. I was expecting to see a custom login screen for my hypothetical users to sign in. I kept trying to resist looking at the code and doing anything myself, but here I took a peek--and saw that the main page.tsx was completely untouched. What?&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%2Fcfoudowcjp4lmv2pkwwd.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%2Fcfoudowcjp4lmv2pkwwd.png" alt="asking AI to look into this" width="800" height="475"&gt;&lt;/a&gt;&lt;br&gt;
LOL. “Ah, I see the issue. I didn’t write the code to do that” 😂 It’s okay, happens to the best of us.&lt;/p&gt;

&lt;p&gt;Another minute, another prompt to install more dependencies, a few more updates to existing configurations, and the agent says we’re ready to test again.&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%2F3wrjy5xl4czak4zmo6hw.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%2F3wrjy5xl4czak4zmo6hw.png" alt="user credentials being exposed" width="800" height="666"&gt;&lt;/a&gt;&lt;br&gt;
🤣 Not super production ready, with the user credentials being exposed and whatnot, but hey at least it's not boilerplate!&lt;/p&gt;

&lt;p&gt;I tried logging in using one of these helpfully-provided credentials. On submit, the UI header updated to show me the Sign Out button and the email address that just went through, but I was still on the login page 🤔 &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%2F5lvkf5frg26zte74e3zo.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%2F5lvkf5frg26zte74e3zo.png" alt="AI diagnosing the issue" width="556" height="152"&gt;&lt;/a&gt;&lt;br&gt;
Sure enough, AI starts finding problems and discovering that the way it’s handling auth is inconsistent throughout this tiny app it just wrote. This was just one example where I noticed the agent was &lt;strong&gt;making decisions incompatible with its own previous decisions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Anyway, my AI agent asked me to install more dependencies to manage cookies, accept all changes, and restart the server. All I saw on the web page was “Loading…” 🤔 It hung there until I refreshed the page, then I was redirected to the login page. Okay, I thought, just another bug we’ll deal with later, I just want to see core functionality.&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%2Fw8g2q5yvxmxphnfb6ul1.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%2Fw8g2q5yvxmxphnfb6ul1.png" alt="...and we're in!" width="703" height="444"&gt;&lt;/a&gt;&lt;br&gt;
AAAND WE'RE IN 💪 Now I need to see if, as a user, I can create, view, and edit campaigns.&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%2F8l1kobt0pjzzmq17imer.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%2F8l1kobt0pjzzmq17imer.png" alt="form error" width="702" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turns out, I cannot. As soon as I start filling out the campaign form, I see an error that I haven't seen in years! Uncontrolled form?? I was really surprised that this AI agent, running on claude 3.5 sonnet model, didn't think through how it would handle forms in an app that is basically "users need to be able to fill out this form and then see their form data." Sure, I can fix it, but since the goal of this whole endeavor was to be as hands off as possible, I reported this to the agent.&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%2Fopb1t1t32qcrejndp0m4.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%2Fopb1t1t32qcrejndp0m4.png" alt="issue found" width="548" height="74"&gt;&lt;/a&gt;&lt;br&gt;
Once I pointed it out, the agent was able to debug. But I kept wondering, why didn't it see the issue before? Clearly it knows how to handle form state updates, why did it choose not to do it right the first time?&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%2Fvl702k07v02wdur653ol.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%2Fvl702k07v02wdur653ol.png" alt="i can see the dashboard!" width="645" height="247"&gt;&lt;/a&gt;&lt;br&gt;
Another issue solved, and I successfully created a campaign! The app redirected me to the dashboard where I could see the campaign at a glance in table view! Not bad. &lt;/p&gt;

&lt;p&gt;Time to test the Edit functionality. I clicked 'Edit' and immediately got slammed with 8 errors:&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%2Fe3s4ccrfrgsjmih2icgi.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%2Fe3s4ccrfrgsjmih2icgi.png" alt="8 errors" width="588" height="209"&gt;&lt;/a&gt;&lt;br&gt;
All 8 errors had to deal with how the app was handling the id parameter passed in the url. &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%2Fm3rpsyhwp23pee4r6mxa.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%2Fm3rpsyhwp23pee4r6mxa.png" alt="fixing async id params" width="527" height="98"&gt;&lt;/a&gt;&lt;br&gt;
This solved all 8 errors. Now I could view the Edit page, make updates, and make sure that they are saving correctly ✨ &lt;/p&gt;

&lt;p&gt;I created more campaigns, then signed out of the app. Now I wanted to login as another user, to make sure I cannot see campaigns created from another email address. I asked the agent to register a second non-admin user (third user in total) so I could confirm this. And we ran into some problems.&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%2Ffolt1f9kk9y3ewkk99en.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%2Ffolt1f9kk9y3ewkk99en.png" alt="more problems" width="560" height="117"&gt;&lt;/a&gt;&lt;br&gt;
First the new user credentials didn’t work, then the app seemed to accept the credentials but didn’t redirect, you know, just auth things🧚‍♀️ &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%2Fpralun6gd6d9j38r1njd.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%2Fpralun6gd6d9j38r1njd.png" alt="form submitting incorrectly" width="555" height="198"&gt;&lt;/a&gt;&lt;br&gt;
“Ah, I see the issue… the form is not submitting correctly” FAM, we have 2 forms in this app and it seems neither one of them was configured correctly. YOU HAD ONE JOB (x2).&lt;/p&gt;

&lt;p&gt;Finally I was able to login as Bob, and none of the campaigns I created as Jane were on his dashboard. A WIN IS A WIN. Then I logged in as the admin user, with the credentials provided. Note that the admin user type was not in my original project requirements, so I was really curious to see what this would allow me to do. It turned out, nothing special. I was looking at the same dashboard I saw as a regular user. I asked the agent to walk me through 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%2F591rsvh9wxkq9le7nuxe.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%2F591rsvh9wxkq9le7nuxe.png" alt="admin vs non-admin" width="550" height="115"&gt;&lt;/a&gt;&lt;br&gt;
I was kind of intrigued at this part--the agent came up with the idea of adding an admin on its own, but it didn't do a whole lot with it (yay for not straying too far from my project instructions!). I also liked that it came up with a whole list of things an admin might be able to do, and thought, Why not, let's try implementing some of these and see what happens.&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%2Fh8h17j0bp2kafmkx1ygj.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%2Fh8h17j0bp2kafmkx1ygj.png" alt="feature creep" width="567" height="152"&gt;&lt;/a&gt;&lt;br&gt;
The moment of truth:&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%2Fqcoomz2avqsnmo5cchxn.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%2Fqcoomz2avqsnmo5cchxn.png" alt="admin dashboard" width="647" height="216"&gt;&lt;/a&gt;&lt;br&gt;
Alright, kudos to the agent! As an admin, I can see everyone else's campaigns, and I also noticed it correctly assumed that an admin should only be able to pause campaigns that are currently Active 👏 I asked it to change the Edit and Pause links into buttons, then logged in as Bob, my non-admin user to add more Active status campaigns (just to see how it would look in the admin panel).&lt;/p&gt;

&lt;p&gt;To my surprise, I discovered that in Bob's view I could no longer edit my campaign 😭 &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%2F37e6s5kjqlh6052kx413.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%2F37e6s5kjqlh6052kx413.png" alt="bob is having issues" width="555" height="179"&gt;&lt;/a&gt;&lt;br&gt;
"Ah, I see the issue... We updated the code in some places but not in all places where it's used." In my opinion, this was kind of a serious oversight from AI agent. If it has to update the code in multiple places, in a tiny app, it probably wasn't using the DRY principle (even though my .cursorrules prompt includes this). But also, this agent had access to the entire context of this app: our chat history, instructions, and the entire codebase, and still when implementing a new feature it didn't integrate the new code as seamlessly as I expected.&lt;/p&gt;

&lt;p&gt;Okay, another problem solved, Bob can do his thing now, and we have 2 active campaigns!&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%2F777pn4d4iencpg97g4sq.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%2F777pn4d4iencpg97g4sq.png" alt="admin view of active campaigns" width="704" height="162"&gt;&lt;/a&gt;&lt;br&gt;
I also noticed the Owner column was displaying numbers, and after confirming with the agent that it represents user id I asked it to change the column name to Owner ID. Feeling like we were pretty much done here, I clicked on one of the campaigns:&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%2Fee65fk6eqttmegofq0wp.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%2Fee65fk6eqttmegofq0wp.png" alt="404 not found page" width="702" height="298"&gt;&lt;/a&gt;&lt;br&gt;
Now what 🤦‍♀️ I ran to my agent. &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%2F14gcw8zcb0y0vikmynq7.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%2F14gcw8zcb0y0vikmynq7.png" alt="agent response" width="554" height="104"&gt;&lt;/a&gt;&lt;br&gt;
"Ah, I see the issue. We have not created the page yet." 😆&lt;/p&gt;

&lt;p&gt;Side note, I love that the agent was using "we" to kind of spread the blame around a little bit and not take all the responsibility. I can respect that. &lt;/p&gt;

&lt;p&gt;Finally it created the missing page that allowed me as an admin to see the campaigns created by other users. But for some reason, most of the campaign details were missing. It also added a second layer of navigation, where I could go back to the main dashboard view or edit campaigns.&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%2F41pkfi90f19p473zksvi.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%2F41pkfi90f19p473zksvi.png" alt="asking AI agent to make more changes" width="558" height="227"&gt;&lt;/a&gt;&lt;br&gt;
The agent's response here was unusually short and to the point, and for a moment I thought "oh no, did I say something wrong?" I got so used to our conversational tone and the agent's "Let me investigate!" or "Ah, I see the issue," or my favorite "You're right!", I kind of forgot that I was talking to a bot. It's fun to talk to AI like it's a fellow human being, but it's jarring to suddenly be reminded that it's not.&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%2Fpek90vdbtyz1c6z7idk4.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%2Fpek90vdbtyz1c6z7idk4.png" alt="AI apologizes" width="547" height="232"&gt;&lt;/a&gt;&lt;br&gt;
OK we are back to conversational tone, but I noticed the agent attempted to add fields to the form that I didn’t ask for. Once again I am reminded that I cannot trust it to follow my instructions. I wondered about those trending stories of production-level apps built and maintained entirely by AI: how do they make sure their agent doesn’t randomly add new fields to a form, or create new user roles, or delete pages? Do they have other agents double checking the first agent's work? And who is double checking the supervisor agents?&lt;/p&gt;

&lt;p&gt;The agent fixed the issue and I moved on to confirm that pages were auth protected. AND THEY WERE ✅ I could not access the dashboard or any individual campaign view by url when I was logged out, and the app correctly kept redirecting me to the login page whenever I tried. Excellent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile View
&lt;/h3&gt;

&lt;p&gt;One more thing, I wanted to see if the app was responsive. I resized the browser window:&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%2F9z1orp8g3wxlpgbcfean.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%2F9z1orp8g3wxlpgbcfean.png" alt="mobile view - not the best" width="483" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Definitely not the most intuitive table view for mobile devices, but I tried not to be too hard on the agent here. I think I was starting to feel bad for it, like I would for a coworker who was having a bad day. Maybe it makes sense that the agent wouldn't prioritize optimizing too much for an admin read-only feature that, in the real world, most likely wouldn't be done on a small screen? So I let it go, since what I really wanted to see and test in mobile view was the Create Campaign form. I scrolled to the top to get to the navigation and go to Campaigns… and realized I could not 🥲 For some reason, the agent decided that the way to make a crowded header mobile-friendly was to COMPLETELY DROP the navigation.&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%2Ft5k7l4xlei2hdt1nntim.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%2Ft5k7l4xlei2hdt1nntim.png" alt="my mobile prompt" width="552" height="124"&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%2F8msjmjkkvyjr5o5t7nx8.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%2F8msjmjkkvyjr5o5t7nx8.png" alt="agent's response" width="550" height="85"&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%2Fbz4aobshnl88e64hw5ab.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%2Fbz4aobshnl88e64hw5ab.png" alt="my shocked face" width="561" height="238"&gt;&lt;/a&gt;&lt;br&gt;
I found out that my agent had some really strange assumptions about mobile navigation. I definitely wouldn’t trust it to build a production level mobile app without reading the code myself any time soon.&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%2Fvz5dq7ajw5a1ew7e79rm.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%2Fvz5dq7ajw5a1ew7e79rm.png" alt="AI couldn't find the navigation component" width="558" height="250"&gt;&lt;/a&gt;&lt;br&gt;
Not sure why AI couldn't find the Navigation.tsx file, it was exactly where the agent put it, but now I couldn’t shake the feeling that I was stressing it out with my demands. From this point, either due to me feeling guilty and not communicating directly enough, or due to AI getting progressively more stressed out by me (is that a thing?), the agent’s performance deteriorated.&lt;/p&gt;

&lt;p&gt;⏭️ I'm going to skip through the rest of the mobile navigation drama, but here were my prompts just to give you an idea:&lt;/p&gt;

&lt;p&gt;👩🏻‍💻 &lt;code&gt;now the navigation takes up too much space on mobile screens, can you make the adcenter logo a bit smaller on mobile, and move the user's email to a second line within navigation (so that it doesn't try to fit everything on the same line)?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👩🏻‍💻 &lt;code&gt;can you please drop the email address on its own line below the logo and 'campaigns'? because now the email is crammed on top of the 'sign out' button&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👩🏻‍💻 &lt;code&gt;okay since you are now displaying the name and email separately we can drop the name and only use email. please keep email where it currently is, just drop the name on mobile devices&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👩🏻‍💻 &lt;code&gt;yes i see it. i think i confused you. these changes were meant to apply only to mobile (when i go to tablet and desktop view, i expected the name and email would still be displayed on the same line to the left of the sign out button, not separated). please make sure these navigation changes only apply to mobile&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👩🏻‍💻 &lt;code&gt;the sign out button and the user's name and email used to be flushed with the right side of the page, weren't they? now they're all bunched up together on the left with the navigation&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;EVENTUALLY we got it done 🙌 I got the AI agent to build me an app, and I did not have to write code to make it happen. It was my first time building an app using plain English! 🎉 Powerful stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Quality
&lt;/h3&gt;

&lt;p&gt;And at this point, I wanted to take a better look at the code files themselves. A bunch of things stood out immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the agent had no accessibility considerations (no ARIA labels in the UI, despite asking for it in .cursorrules)&lt;/li&gt;
&lt;li&gt;no tests included (despite explicit testing directives in .cursorrules, such as "plan for unit and integration tests", "implement test coverage", and "use React Testing Library.")&lt;/li&gt;
&lt;li&gt;the agent did not take advantage of Next.js SSR at all. Every component, page, and layout file, except the utils, had the 'use client' directive at the top. Why this is problematic is beyond the scope of this already-long article, but needless to say this is not aligned with the "follow best practices" directive I gave my agent on multiple occasions.&lt;/li&gt;
&lt;li&gt;the file containing the form to create campaigns was 333 lines long, and had no form validation! I expected that it would at least use React Hook Form, ideally also zod, or some similar technology. Interesting choice to say the least; I decided to ask the agent about it:
&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%2Fka8s1avdsahg6bzsx8kr.png" alt="another oversight" width="800" height="1395"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;“I made a significant oversight by not implementing proper form…” And that’s the crux of it, isn’t it. The AI agent, using the latest model, is making significant oversights and not following best web development practices, when allowed free reign over the code base with minimal oversight. &lt;/p&gt;

&lt;p&gt;I asked the agent to analyze why it did so poorly with this component specifically. Agent's response:&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%2F2pnoxgiaxb0q1dshputm.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%2F2pnoxgiaxb0q1dshputm.png" alt="agent's response to that" width="800" height="172"&gt;&lt;/a&gt;&lt;br&gt;
This didn't make sense to me at all, so I tried again:&lt;br&gt;
👩🏻‍💻 &lt;code&gt;i want you to clarify the over-engineering issue: in what way was the CampaignForm.tsx prematurely optimized or ideal in its implementation (we have not implemented zod or react hook form). do not change the code, just respond&lt;/code&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%2Fcq83yuv87pswmbncb6e2.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%2Fcq83yuv87pswmbncb6e2.png" alt="fascinating response" width="800" height="412"&gt;&lt;/a&gt;&lt;br&gt;
I like how the agent phrased it, 'When I mentioned “over-engineering” and “premature optimization”, that was incorrect - we haven’t implemented any optimizations yet, let alone premature ones'😂 True, true.&lt;/p&gt;

&lt;p&gt;But humor aside, once again I was facing the fact that the AI agent wasn't thinking about the problem the way I would expect. The prompt was fairly straightforward, look at the code you wrote and tell me why you had a hard time following the best practices you clearly know because you described them to me just a second ago. And the agent said that it focused on optimizations and accidentally over-engineered, which made no sense, and then admitted it "didn't properly review the code before making statements about its implementation." But if it didn't review the code, what did it do when I asked it to review the code? What was it thinking about or looking at while generating the response? What is the context it's using that I'm failing to properly reach? This puzzled me. It still does.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It was actually a lot of &lt;strong&gt;fun&lt;/strong&gt; to program with AI agent, even with all the issues along the way. I didn't notice how fast the time flew by. Programming can feel pretty lonely, so having someone to talk to about the code you're working on, even if it's an AI agent, made developing a much more enjoyable experience.&lt;/li&gt;
&lt;li&gt;I built the app &lt;strong&gt;faster&lt;/strong&gt; with AI than it would have taken me to do it alone. &lt;/li&gt;
&lt;li&gt;Seeing errors was &lt;strong&gt;not as mentally taxing&lt;/strong&gt; on me, because I knew that between the agent and me, we would figure it out quickly. I didn’t dread seeing red because I knew I wouldn’t spend hours being stuck. And that was a beautiful thought. Most of these errors, except the mobile navigation drama, were solved in less than 5 mins.&lt;/li&gt;
&lt;li&gt;AI agents are not great at following rules and &lt;strong&gt;NEED to be supervised&lt;/strong&gt;. If anyone is truly building entire production-ready applications simply describing to an agent what they want and doing nothing else, I'm really curious what defaults and presets they are using, and what exactly do they say in their prompts, because me and my agent are clearly not there yet.&lt;/li&gt;
&lt;li&gt;Those with more engineering experience will &lt;strong&gt;get more productivity&lt;/strong&gt; gains out of Cursor and AI agents at this point. If you already know what the output should look like, you'll build more robust, scalable apps with AI. If you don't, you're at the agent's mercy, and as I've demonstrated the agents are not at the point where you can trust them to make sensible engineering decisions. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I should note that at least some of the problems we ran into could have been avoided with better prompts. I did ask the agent toward the end to analyze our conversation patterns, especially around errors and miscommunication, and share with me how I can improve my prompts. It suggested several different things, but this was my favorite:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Try iterative development approach, and build in phases. &lt;br&gt;
Example prompt:&lt;br&gt;
Let's build this in phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic structure and routing&lt;/li&gt;
&lt;li&gt;Core features without optimization&lt;/li&gt;
&lt;li&gt;UI refinement&lt;/li&gt;
&lt;li&gt;Optimization and validation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please complete each phase before moving to the next.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that it wasn't asking me to prompt it with one phase at a time, where I have to review the work before allowing the agent go to the next step. The agent asked me to &lt;strong&gt;remind it&lt;/strong&gt; to work on one thing at a time, starting with basic structure and then incrementally working its way up to optimization, before it announces that the app is ready. I really liked this suggestion, and I will try using it with my next Cursor build.&lt;/p&gt;

&lt;p&gt;The more I practice pair programming with Cursor, the more I'll get the hang of it. Who knows, by the end of this month I might be one of those people building production-level apps with 1-2 sentences 🤩 &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have any tips on how I can make that happen, please share below!&lt;/strong&gt; Thank you 😊 &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Microfrontend Architecture: What You Need to Know Before You Start</title>
      <dc:creator>Katya Pavlopoulos</dc:creator>
      <pubDate>Fri, 21 Jul 2023 20:30:34 +0000</pubDate>
      <link>https://dev.to/katya_pavlopoulos/microfrontend-architecture-what-you-need-to-know-before-you-start-44a7</link>
      <guid>https://dev.to/katya_pavlopoulos/microfrontend-architecture-what-you-need-to-know-before-you-start-44a7</guid>
      <description>&lt;p&gt;As web applications continue to evolve, frontend developers face new challenges in maintaining large and complex codebases. The rise of microfrontends has emerged as a solution to address these challenges, offering a scalable and flexible architecture pattern. &lt;/p&gt;

&lt;p&gt;If you're about to migrate your monolithic app to use the microfrontend architecture, or you're developing a new project from scratch using this architecture pattern, here are some things you need to do at the start to make the process ✨easy-breezy✨ (or at least &lt;em&gt;easier&lt;/em&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Lock in all inflexible requirements
&lt;/h3&gt;

&lt;p&gt;There are many different ways to implement microfrontends. The best method for your use case depends ENTIRELY on your hard requirements. You may not be able to have &lt;em&gt;all&lt;/em&gt; the requirements locked in before you start, but to spare yourself from having to re-architecture your microfrontends system you need to at least know all your &lt;em&gt;inflexible&lt;/em&gt; requirements upfront.&lt;/p&gt;

&lt;h3&gt;
  
  
  Push for separation of concerns
&lt;/h3&gt;

&lt;p&gt;Always be mindful if what you're implementing in one microfrontend depends in some way on what's in another microfrontend. If you make a change in microfrontend &lt;em&gt;a&lt;/em&gt;, will you have to also make a change in microfrontend &lt;em&gt;b&lt;/em&gt;? Look for ways to improve separation of concerns. Note that depending on your requirements, a true separation of concerns may not be possible, but you should still try to push for maximum decoupling of microfrontends.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ignore frontend framework at the top architecture level
&lt;/h3&gt;

&lt;p&gt;To save yourself and your company many headaches down the line, keep the communication between the microfrontends minimal and framework-agnostic. If the microfrontend is built with React, the other microfrontends should be able to communicate with it even if you (or more likely, another team at a different point in time) reimplement it with Vue or Angular or something else. &lt;/p&gt;

&lt;h3&gt;
  
  
  Plan to spend &lt;del&gt;some&lt;/del&gt; a lot of time debugging in prod (especially if it's your first time implementing microfrontends)
&lt;/h3&gt;

&lt;p&gt;Even though all your microfrontends may be working together properly on your local machine, you &lt;del&gt;may&lt;/del&gt; most certainly will run into really strange issues in production. Just be mentally prepared for that, and budget in some time for your debugging party. A good place to start debugging is by looking at your config files (or, if the issues are around styling, start by investigating how your css is packaged for production).&lt;/p&gt;

&lt;p&gt;If you're about to embark on your first microfrontend architecture adventure, can I recommend a course? This is not an affiliate link (in fact, you can just look up this course by its title on udemy), but &lt;a href="https://www.udemy.com/course/microfrontend-course/" rel="noopener noreferrer"&gt;Microfrontends with React: A Complete Developer's Guide&lt;/a&gt; was a life saver for me. &lt;/p&gt;

&lt;p&gt;Have fun, and good luck!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Great Commandments of Frontend Engineering</title>
      <dc:creator>Katya Pavlopoulos</dc:creator>
      <pubDate>Tue, 15 Nov 2022 14:57:38 +0000</pubDate>
      <link>https://dev.to/katya_pavlopoulos/the-great-commandments-of-frontend-engineering-2311</link>
      <guid>https://dev.to/katya_pavlopoulos/the-great-commandments-of-frontend-engineering-2311</guid>
      <description>&lt;p&gt;I’ve been spending a lot of time recently thinking about fundamentals. Breaking complex things down to the basics. Looking for success patterns that I can replicate. Reading up on what the industry thought leaders have said about the core essentials of our field. If you have seen my previous post about &lt;a href="https://dev.to/kat_pavlopoulos/the-fundamentals-of-software-engineering-2kc5"&gt;the fundamentals of software engineering (spoiler alert, it's not data structures and algorithms)&lt;/a&gt;, you already share my context.&lt;/p&gt;

&lt;p&gt;Today I want to zero in on frontend engineering in particular, and suggest three principles that I have seen at work again and again when working with or observing top frontend developers. If I missed anything, or if you believe either of these three aren't necessary, please let me know in the comments below. Let's learn together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Love your craft&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Many people can write code, but one thing that sets the masters of their craft apart is that they care about the quality of their work so much that they will go the extra mile, always. &lt;/p&gt;

&lt;p&gt;They’re also lifelong learners. They didn’t stop acquiring knowledge when they were last promoted. They look for opportunities to learn, to improve, to grow, and this pursuit of excellence reflects in their work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Love your users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Frontend engineers in particular work very closely to the user, building the very interface the user interacts with. I noticed that the best frontend engineers think about not just the computers running the code but the people that code will interact with. Even the best practices for testing frontend code revolve around mocking user actions rather than striving for 100% code coverage.&lt;/p&gt;

&lt;p&gt;They also don’t cut corners on things like accessibility and cross-browser support. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Love yourself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Are you surprised to see this on the list? The truth is, the best frontend engineers have been in the industry for a while, which means they’ve managed to position themselves in a way that allows them to be continually challenged, recognized, and not burn out in the process. You might be able to accomplish quite a bit running on fumes, skipping meals, skipping workouts, even sacrificing your sleep, but how long will you last? &lt;/p&gt;

&lt;p&gt;Create intentional times of rest.&lt;/p&gt;

&lt;p&gt;Refuel your creative tank. &lt;/p&gt;

&lt;p&gt;Take care of your physical, mental, emotional, and spiritual wellbeing so that you can bring your best self to work every day. &lt;/p&gt;

&lt;p&gt;And have fun building awesome frontends &amp;lt;3&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Fundamentals of Software Engineering</title>
      <dc:creator>Katya Pavlopoulos</dc:creator>
      <pubDate>Mon, 07 Nov 2022 21:55:11 +0000</pubDate>
      <link>https://dev.to/katya_pavlopoulos/the-fundamentals-of-software-engineering-2kc5</link>
      <guid>https://dev.to/katya_pavlopoulos/the-fundamentals-of-software-engineering-2kc5</guid>
      <description>&lt;p&gt;Recently I was reading The Art of Doing Science and Engineering by Richard W. Hamming, and he made the case that software engineering fundamentals go beyond data structures and algorithms. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clear thinking&lt;/strong&gt; is the true fundamental of programming.&lt;/p&gt;

&lt;p&gt;This makes sense, if you think about it. The whole point of a fundamental truth or skill is that it is the basic building block of the discipline built on top of it. While data structures and algorithms are foundational to everything we do in software today, can't you imagine a scenario in some very distant future where we use &lt;em&gt;different&lt;/em&gt; data structures? A future where today's algorithms are barely even mentioned in the textbooks? (Do we still use textbooks in this distant future?)&lt;/p&gt;

&lt;p&gt;And how do we evolve into a future where we use completely different data structures and algorithms, if not by leveraging clear thinking and good problem solving skills to not only come up with solutions to tomorrow's problems, but also solve yesterday's problems more efficiently.&lt;/p&gt;

&lt;p&gt;This really stuck with me, because I'd always believed that DS&amp;amp;A are what's foundational to all software, to all job interviews, to all programming books. Perhaps that's mostly true today, but a good software developer still has to go beyond that. After all, what's the point in memorizing the Depth First Search if you don't understand when to apply it? As you can see, even today, what's actually required is clarity of thought.&lt;/p&gt;

&lt;p&gt;So keep this in mind the next time you sit down to read through that giant green Cracking the Coding Interview book (do we all have one of these at home?). And check out Richard Hamming's The Art of Doing Science and Engineering!&lt;/p&gt;

&lt;p&gt;Until next time.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building Conway's Game of Life with React and CSS</title>
      <dc:creator>Katya Pavlopoulos</dc:creator>
      <pubDate>Tue, 19 Jan 2021 23:30:37 +0000</pubDate>
      <link>https://dev.to/katya_pavlopoulos/building-conway-s-game-of-life-with-react-and-css-2l5m</link>
      <guid>https://dev.to/katya_pavlopoulos/building-conway-s-game-of-life-with-react-and-css-2l5m</guid>
      <description>&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/031e9955b5d1d70f31ef59b8b589e6dfa7e42f33a121ad18116545f42a5ff152/68747470733a2f2f6d656469612e67697068792e636f6d2f6d656469612f3456565a547654717a5252304255774e49482f67697068792e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/031e9955b5d1d70f31ef59b8b589e6dfa7e42f33a121ad18116545f42a5ff152/68747470733a2f2f6d656469612e67697068792e636f6d2f6d656469612f3456565a547654717a5252304255774e49482f67697068792e676966" alt="Conway's Game of Life formations" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life" rel="noopener noreferrer"&gt;Illustration from Wikipedia&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this project, my goal was to implement the computer science classic, John Conway's "Game of Life." I had a total of 4 days to work on it: I began the project on Monday and Friday morning I presented it to my team. &lt;/p&gt;
&lt;h2&gt;
  
  
  The Process
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Understanding the problem
&lt;/h3&gt;

&lt;p&gt;I dedicated most of Monday to reading about Game of Life in order to understand the core concepts and principles of this program. To summarize, Game of Life is a simulation of how a given population will change over time based on the following rules. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Any empty cell with 3 live neighbors becomes a live cell (reproduction)&lt;/li&gt;
&lt;li&gt;Any live cell with fewer than 2 neighbors dies (underpopulation)&lt;/li&gt;
&lt;li&gt;Any live cell with more than 3 neighbors dies (overpopulation)&lt;/li&gt;
&lt;li&gt;Only the live cells that have 2 or 3 live neighbors survive to the next generation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The program is basically a 2D grid where cells come alive or die depending on the state of their adjacent cells (how many of them were alive or dead in the previous generation). Although John Conway originally devised this simulation in 1970, it is still studied today, with &lt;a href="https://www.conwaylife.com/forums/viewtopic.php?t=3303" rel="noopener noreferrer"&gt;new population formations still being discovered&lt;/a&gt; as recently as 2018.&lt;/p&gt;
&lt;h3&gt;
  
  
  Planning MVP
&lt;/h3&gt;

&lt;p&gt;OK, so I had the core concepts down. Next, I needed to narrow down the scope of what I was going to build. Although Game of Life only has a few hard rules, there are many variations and extra features that I could add to my implementation to make it more interesting and engaging.&lt;/p&gt;

&lt;p&gt;Another reason I like to have my scope fixed on paper ASAP is because whenever I plan a project, I leave a buffer of some free time between when I need to have it finished and the actual deadline. This way, I have time to refactor and polish my work; or, if I get stuck on something early on, I have time to catch up and still make the deadline.&lt;/p&gt;

&lt;p&gt;So far my week was going to look like this:&lt;/p&gt;

&lt;p&gt;Monday: research, narrow down the scope, plan MVP&lt;br&gt;
Tuesday and Wednesday: write code &lt;br&gt;
Thursday: buffer (polish or catch up)&lt;br&gt;
Friday morning: presentation &lt;/p&gt;

&lt;p&gt;This gave me only 2 days of actual programming time, so it was crucial to decide on what my MVP would look like and stick to it.&lt;/p&gt;

&lt;p&gt;Here's what I came up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A grid of cells where the simulation will be displayed&lt;/li&gt;
&lt;li&gt;Simulation function that shows what each generation will look like based on the rules&lt;/li&gt;
&lt;li&gt;A heading that clearly labels which generation the simulation is currently displaying (label the initial population Generation 0, the next one Generation 1, etc)&lt;/li&gt;
&lt;li&gt;Buttons to start/stop the simulation&lt;/li&gt;
&lt;li&gt;The rules of the game&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition (but still part of MVP):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A button to generate a random population on the grid &lt;/li&gt;
&lt;li&gt;Cells in the grid have to be clickable so that users can manually set any cell to be alive or dead&lt;/li&gt;
&lt;li&gt;Controls to manually step through the simulation one generation at a time (another button?)&lt;/li&gt;
&lt;li&gt;A way for the user to control the speed of the simulation (three more buttons?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In terms of appearance and aesthetic, I wanted to achieve a clean and minimalist look with the conservative feel of actual scientific software.  &lt;/p&gt;

&lt;p&gt;I had an idea for how I wanted the components to fit together visually, so I made a very basic wireframe to guide me.&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%2Fi%2Fwfeerp2ylih24qlirwx8.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwfeerp2ylih24qlirwx8.JPG" alt="My project wireframe" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tech stack: React to build the interface and handle functionality, and CSS for styling. &lt;/p&gt;
&lt;h3&gt;
  
  
  Writing code, part 1: Smooth sailing ⛵
&lt;/h3&gt;

&lt;p&gt;Building out the presentational components of this project using React and CSS was exciting and satisfying. I am very much a visual person so making UX decisions while also developing UI was a challenge I really enjoyed.&lt;/p&gt;
&lt;h4&gt;
  
  
  The grid
&lt;/h4&gt;

&lt;p&gt;The grid itself was surprisingly easy to make! It's a &lt;code&gt;div&lt;/code&gt; styled using CSS Grid, which is a 2-dimensional layout system that comes with CSS. No need to install any extra dependencies! All I had to do was add &lt;code&gt;display: grid&lt;/code&gt; and then use the &lt;code&gt;grid-template-columns&lt;/code&gt; property to control how many columns I wanted to generate and their width. Since these columns are filled with cells (grid items), I then added height, width, and a thin border around each cell and that was it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.grid-container {  
  width: 70%;
  display: grid;
  grid-template-columns: repeat(20, 3.25vw);
}

.cell {
  border: 1px solid black;
  width: 3.25vw;
  height: 3.25vw;            
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used percentages and view-width (vw) as size units because I wanted the grid to look consistent on any screen size. Toward the end of the project, I had some time to refactor and make the entire interface responsive, but more on that later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Colors
&lt;/h4&gt;

&lt;p&gt;Since I wanted my interface to look clean and minimalist, similar to real scientific software, I kept color to a minimum. &lt;/p&gt;

&lt;p&gt;For maximum attention-grabbing impact, I wanted the live cells to be represented in red (as opposed to purple or some other color), but to give this simulation the conservative look I was going for, I went with a subdued #cd5c5c. From there, I experimented with different greens to find one that would look best together with this red, and ended up going with #4caf50.&lt;/p&gt;

&lt;h4&gt;
  
  
  Controls
&lt;/h4&gt;

&lt;p&gt;In general, I really like the look of pill-shaped buttons, but for this project I wanted them to have a more business-professional feel. Rectangle-shaped buttons with sharp borders looked too strict and uninviting, so I added a small border radius, as well as a thin black border. &lt;/p&gt;

&lt;p&gt;At first I wanted to have two separate buttons to start and stop the simulation. I also needed to build in some way to reset the entire simulation back to generation 0 and an empty grid. I was going to group all three buttons together in the same row, but I didn't like the crowded look of it. That's when I got the idea to refactor the start/stop buttons into one: by default, it reads "start simulation" and on click the text changes to "stop simulation". The functionality of the button (whether it starts or pauses the simulation) also toggles based on a boolean slice of state that the app maintains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button onClick={handleSimulation} type="button"&amp;gt;
    {runningSimulation ? "stop simulation" : "start simulation"}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though my first thought was to have separate buttons to set simulation speed, I decided it was better to consolidate them into one dropdown since users can only choose one speed at a time. One dropdown replacing three buttons also made the interface look less cluttered. The speeds themselves took a bit of experimentation, but I settled on 100ms for fast, 500ms for average, and 1000ms for slow. Since users also have the option to see each generation one at a time (and to look at each frame as long as they want), I did not think it was necessary to support a speed slower than 1000ms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing code, part 2: No pain, no gain 😅
&lt;/h3&gt;

&lt;p&gt;The hardest part for me was the algorithm responsible for building the next generation of cells based on the previous one. A lot of the difficulty stemmed from &lt;em&gt;my own misunderstanding&lt;/em&gt; of how it was supposed to work (this is why understanding the problem is THE most important step in the software development process!). &lt;/p&gt;

&lt;p&gt;In my mind, as the algorithm traveled across the grid it was supposed to calculate the state of each cell based on the state of its neighbors. This part was correct. Where I went wrong was in my assumption that if the neighbors already had their new values calculated, I was supposed to use those new values. If I hadn't been so excited to start writing code and spent more time understanding the problem I would have realized that, conceptually, calculating generation y based on values from generation x &lt;em&gt;and&lt;/em&gt; y makes no sense. This algorithm that I was trying to implement was not only messy, but it resulted in new generations that looked entirely wrong -- cells died off or came alive in ways that didn't conform to the rules of the game, and within a generation or two all cells were dead no matter what the initial population looked like! &lt;/p&gt;

&lt;p&gt;I kept thinking the problem was with my code, and I kept trying to debug what was on the screen, when in reality the program I wrote did exactly what I told it to do. It was my mental model of what I was supposed to accomplish that needed debugging.&lt;/p&gt;

&lt;p&gt;I was stuck. &lt;/p&gt;

&lt;h4&gt;
  
  
  Getting unstuck
&lt;/h4&gt;

&lt;p&gt;I was growing discouraged, so I decided to look for help. After years of taking online programming classes and learning on my own, I knew that the best way for me to understand this problem was to find a code-along tutorial. There is something about having someone else go through the process with me, step by step, that really helps solidify new concepts in my mind. Half way into the code-along tutorial (I believe &lt;a href="https://www.youtube.com/watch?v=DvVt11mPuM0&amp;amp;t=1229s" rel="noopener noreferrer"&gt;it was this one&lt;/a&gt;), it finally clicked -- I needed to be calculating the new generation based on the values from previous generation &lt;em&gt;only&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;In my quest to debug this problem, I also discovered an interesting technique for calculating the neighbors of each cell. As the rules of the game state, what happens to a cell from one generation to the next depends on how many live neighbors it has. In a 2D grid, each cell can have up to 8 neighbors. To calculate what happens to each cell, I have to first count how many of its adjacent cells are live cells. The technique is to identify each neighbor cell by its (x, y) coordinates relative to the cell the value of which I'm trying to calculate. In other words, for any cell (0, 0), the neighbors will have the following possible coordinates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// this helps to calculate neighbors painlessly
  const neighborCoordinates = [
    [0, 1],
    [0, -1],
    [1, -1],
    [-1, -1],
    [1, 1],
    [-1, 1],
    [1, 0],
    [-1, 0],
  ];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So for each cell, the algorithm would take its actual (x, y) coordinates in the 2D grid, and compute the neighbors by adding the relative coordinates of each neighbor. At this point all I had to do was check if the neighbor was a live (1) or dead (0) cell, count up those values, and set the next generation of (x, y) cell to be either 0 or 1, depending on the number of live neighbors.&lt;/p&gt;

&lt;p&gt;Here is the entirety of the runSimulation() algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const runSimulation = useCallback(() =&amp;gt; {
    // increment generation
    let nextGeneration = generation + 1;
    setGeneration(nextGeneration);

    // make a new grid
    let nextGenGrid = emptyGrid();
    let oldGridCopy = [...grid];
    // iterate over the current grid
    // to calculate new values
    for (let i = 0; i &amp;lt; numRows; i++) {
      for (let j = 0; j &amp;lt; numCols; j++) {
        // count up neighbors
        let neighbors = 0;
        // calculate neighbor coordinates
        neighborCoordinates.forEach(([x, y]) =&amp;gt; {
          let newX = x + i;
          let newY = y + j;
          // if the new coordinates are in the grid
          // (not below 0 or greater than numRows/numCols limit)
          // count them as a neighbor and
          // add their value to neighbors
          if (newX &amp;gt;= 0 &amp;amp;&amp;amp; newX &amp;lt; numRows &amp;amp;&amp;amp; newY &amp;gt;= 0 &amp;amp;&amp;amp; newY &amp;lt; numCols) {
            neighbors += oldGridCopy[newX][newY];
          }
        });
        // change cell state according to game logic
        // if there are fewer than 2 or more than 3 neighbors,
        // cell dies
        if (neighbors &amp;lt; 2 || neighbors &amp;gt; 3) {
          nextGenGrid[i][j] = 0;
        }
        // any cell with exactly 3 neighbors will either
        // be born or survive from previous generation
        else if (neighbors === 3) {
          nextGenGrid[i][j] = 1;
        }
        // otherwise, the next generation looks the same
        else {
          nextGenGrid[i][j] = oldGridCopy[i][j];
        }
      }
    }
    setGrid(nextGenGrid);
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  React Hooks
&lt;/h4&gt;

&lt;p&gt;Prior to this project, I'd already had experience with React's useState, useEffect, useContext, and useReducer, as well as my own custom hooks.&lt;/p&gt;

&lt;p&gt;Since I needed the simulation algorithm to run in the background to calculate what the next generation should look like every x milliseconds (set by the simulation speed), I put the function inside a useEffect hook. This didn't give me the functionality I was going for, because each time the grid was updated, the entire component was re-created -- together with the simulation algorithm. &lt;/p&gt;

&lt;p&gt;A little more Google-fu revealed that I can use React's useCallback hook to allow my runSimulation function to persist through component re-renders. I then referenced this useCallback-supercharged function inside my useEffect hook. &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%2Fi77vxhuc40qy5j6db9jx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi77vxhuc40qy5j6db9jx.jpg" alt="it's all coming together now meme" width="680" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React's useEffect hook will run its code whenever there's a change in any of the variables listed in its dependency array. In my case, one of the dependency array items was a boolean slice of state that controlled whether the simulation was running or not. For that reason, inside the useEffect hook, I first checked to see if runningSimulation was set to false, in which case I wanted my program to do nothing and just return. Otherwise, I wanted it to continuously execute the runSimulation function at intervals of x milliseconds, where x is the speed selected by the user (defaults to "slow" or 1000ms if no selection was made). &lt;/p&gt;

&lt;p&gt;Finally, whenever setting up counters or timers like this inside of useEffect, it's important to clean them up (otherwise they keep running in the background). The clean up process is initiated by the return keyword, followed by the cleanup function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    if (runningSimulation === false) {
      return;
    }
    const timer = setInterval(() =&amp;gt; {
      runSimulation();
    }, speed);
    return () =&amp;gt; clearInterval(timer);
  }, [runSimulation, runningSimulation]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Close to the finish line
&lt;/h3&gt;

&lt;p&gt;It was Wednesday night, and I finally had a working MVP. Thursday was my buffer, and I had all day to polish my project and make it look more presentable.&lt;/p&gt;

&lt;p&gt;But when I signed off for the day on Wednesday with a working MVP, I wasn't super excited. I'd spent three whole days struggling through this project, trying to understand the requirements, working through tutorials, always with at least 10 StackOverflow tabs open, anxious to finish it on time... I wondered, &lt;em&gt;have I learned anything?&lt;/em&gt; If I had to build this again, would I be able to, without any outside help? &lt;/p&gt;

&lt;p&gt;When I woke up on Thursday morning, I knew I had to find out. I started a new create-react-app project and began to build the Game of Life simulation from scratch -- the grid, the algorithm, everything! Second time around, I felt like I had a much better understanding of how all the pieces fit together and the code I needed to write to make it all work. This also made me feel more prepared to give the presentation! I finished my second build in just a few hours (!!!) and still had plenty of time left as a buffer. I spent the extra time making the application responsive, and adding an explanation for each item in the Control Panel to improve the UX. &lt;/p&gt;

&lt;p&gt;It was this second build that I presented on Friday to my team. It's also the build that I've linked below.&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%2Fi%2Fe39d5zlp55w8ork62tbd.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe39d5zlp55w8ork62tbd.JPG" alt="Screenshot of the finished interface" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflection
&lt;/h3&gt;

&lt;p&gt;I'm very happy with how this project turned out. I was able to implement Conway's Game of Life, I found ways to unblock myself when I got stuck, and (to me, this part is the most important) I was able to see my own measurable growth as a developer when I rebuilt the project that originally took me 3 long, stressful days in only a few hours! &lt;/p&gt;

&lt;h3&gt;
  
  
  Future direction
&lt;/h3&gt;

&lt;p&gt;If I have time to return to this project in the future, I would like to add some population presets. The classical Game of Life yields some interesting population formations, such as glider guns, spaceships, and pulsars. Users might want to start with one of these special populations on the grid and observe their behavior over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it out!
&lt;/h2&gt;

&lt;p&gt;I deployed the project on Vercel. You can interact with the &lt;a href="https://game-of-life-rosy.vercel.app/" rel="noopener noreferrer"&gt;live app here&lt;/a&gt; or &lt;a href="https://github.com/kp1129/game-of-life" rel="noopener noreferrer"&gt;take a look at the code here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Thank you for reading! If you've built a Game of Life implementation as well, feel free to link to it in the comments! I'd love to take a look😊&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>webdev</category>
      <category>react</category>
      <category>css</category>
    </item>
    <item>
      <title>#1 Thing I Learned From Y-Combinator's Startup School</title>
      <dc:creator>Katya Pavlopoulos</dc:creator>
      <pubDate>Mon, 30 Nov 2020 23:47:09 +0000</pubDate>
      <link>https://dev.to/katya_pavlopoulos/1-thing-i-learned-from-y-combinator-s-startup-school-29p8</link>
      <guid>https://dev.to/katya_pavlopoulos/1-thing-i-learned-from-y-combinator-s-startup-school-29p8</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;I've always wanted to be on the cutting edge&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I remember reading and re-reading encyclopedias as a kid and thinking I'd grow up to be a scientist or an inventor of some sort. While my childhood fantasy hasn't fully manifested (yet), I did find myself working at startups and caught the discovering/inventing/building/disrupting bug again.&lt;/p&gt;

&lt;p&gt;That's how I ended up applying to Y-Combinator's Startup School for future founders. It's never too early to start thinking about your startup ideas, and I figured this course will only help me as a software engineer while I work at other people's startups.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What I thought I would learn at Startup School&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Going into this, I had some preconceived notions about what I would learn and what my main takeaways would be. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to find a cofounder&lt;/li&gt;
&lt;li&gt;How to build the founding team in general &lt;/li&gt;
&lt;li&gt;How to incorporate as a company (should you go with an LLC? At what point should your side project become a company?)&lt;/li&gt;
&lt;li&gt;How to divide company ownership between the cofounders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Etc. &lt;/p&gt;

&lt;p&gt;Notice that I was expecting to learn a lot of &lt;em&gt;how-to's&lt;/em&gt;. And Startup School does cover all of these, and more. But somewhat unexpectedly, my biggest takeaway from this experience was not a &lt;em&gt;how-to&lt;/em&gt; but a &lt;em&gt;what-to&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What should I focus on?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you work at a startup, especially if it's at an early stage, there are always a million things vying for your attention. There's always an emergency. There's always a fire to put out, and you're lucky if it's only one fire at a time. The todo list only gets longer, never shorter. Given that we are finite beings operating in finite time, what should founders focus on the most? What is the one thing you should always be doing that will give your startup the maximum chance for success?&lt;/p&gt;

&lt;p&gt;Honestly, I thought the answer to this would be &lt;em&gt;"get more investors"&lt;/em&gt;😅 It makes sense, right? After all, if you get more investors, then you have more money, and then you can hire more engineers, more salespeople, pay for more advertising, etc.&lt;/p&gt;

&lt;p&gt;So I was surprised to find out that, no, getting more investors onboard is not THE ONE THING that will help your startup succeed. &lt;/p&gt;

&lt;p&gt;Although getting millions in funding certainly doesn't hurt, the most important thing I can be doing at any time to grow the company can be summarized as &lt;em&gt;"talk to users and build the product."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Talk to users and build the product&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This doesn't mean &lt;em&gt;"never talk to investors"&lt;/em&gt;, but it does mean that you have a product that's always evolving to better meet the needs of your users before you pitch.&lt;/p&gt;

&lt;p&gt;I was also surprised to learn this doesn't necessarily mean &lt;em&gt;"hire software engineers ASAP"&lt;/em&gt;, because some of the case studies we covered had MVP's that were thrown together using free tools like Excel, Google Forms, Zoom, etc, without a single line of code written by the founders. This took me a while to process, because I've always thought that successful startups must have technical people on the team (and they do! but not always at the start).&lt;/p&gt;

&lt;p&gt;To me, this also reinforced the idea that as a software developer whether I'm working for someone else or building my own thing, I need to have an established way of communicating with my end users in some way. Maybe it's an occasional coffee with "Tell me about how our product is working out for you and what frustrations you've had with it this week?" Maybe it's a Google Form followed by a Zoom call. Maybe it's a few days a month of handling customer support. I imagine the details of how I maintain this conversation will change based on where I am. But one thing is certain, just writing good, clean, maintainable code is not enough.&lt;/p&gt;

&lt;p&gt;If none of this is a surprise to you, hey you're way ahead of me! I'm still learning😊&lt;/p&gt;

&lt;p&gt;Have you attended Startup School or worked at a startup? What were your biggest takeaways? What helped you grow? I'd love to learn more😊&lt;/p&gt;

&lt;p&gt;In the meantime, I'm off to talk to users and build product!&lt;/p&gt;

</description>
      <category>startup</category>
      <category>watercooler</category>
      <category>career</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
