<?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: Nando Rama</title>
    <description>The latest articles on DEV Community by Nando Rama (@nando_rama_67753ecb8e0e6d).</description>
    <link>https://dev.to/nando_rama_67753ecb8e0e6d</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%2F3456482%2F56c076eb-0926-472a-be93-34885f18c20b.jpg</url>
      <title>DEV Community: Nando Rama</title>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nando_rama_67753ecb8e0e6d"/>
    <language>en</language>
    <item>
      <title>Day 12 — Do well by doing good</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Sat, 30 Aug 2025 01:19:10 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/day-12-do-well-by-doing-good-16ei</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/day-12-do-well-by-doing-good-16ei</guid>
      <description>&lt;p&gt;&lt;em&gt;Me&amp;gt; Let’s wire up Stripe so managers bring their own merchant account; we skim a tiny, grandma-safe platform fee, and bake T&amp;amp;C consent into checkout—visible, not buried.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AI&amp;gt; Wow—you’re on a roll, Nando. I’ve tightened the plan; nudge any line and we’ll start shipping.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 12 — Do well by doing good
&lt;/h1&gt;

&lt;p&gt;Before today, running a Squares game meant the &lt;strong&gt;host had the least fun&lt;/strong&gt;.&lt;br&gt;
You know the dance: spreadsheets and DMs, “Which square is mine?”, “Did you get my payment?”, “When are numbers drawn?”, “Who pays who?” Then the fourth-quarter scramble to calculate winners, move money, and explain the rules—again. The person trying to make game day more fun becomes the unofficial accountant, referee, and customer-support desk.&lt;/p&gt;

&lt;p&gt;Today we fixed the two biggest hassles: &lt;strong&gt;collecting money&lt;/strong&gt; and &lt;strong&gt;proving who paid&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before vs. After
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Players call dibs in a chat; the grid drifts out of date.&lt;/li&gt;
&lt;li&gt;Payments arrive in five different apps with six different emojis.&lt;/li&gt;
&lt;li&gt;Host manually marks “paid,” chases stragglers, and prays the math adds up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After (what we shipped today)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manager links &lt;strong&gt;their own Stripe account&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Players &lt;strong&gt;pick a square → pay → get marked “paid” automatically&lt;/strong&gt;, all in one flow.&lt;/li&gt;
&lt;li&gt;The app keeps a clean ledger; the host keeps their sanity.&lt;/li&gt;
&lt;li&gt;I take a &lt;strong&gt;tiny per-transaction platform fee&lt;/strong&gt; (low enough not to scare anyone), and the money itself goes &lt;strong&gt;straight to the manager&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s the old motto: &lt;strong&gt;do well by doing good&lt;/strong&gt;. Make the host’s life easier, and the whole party gets better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why “bring your own Stripe”?
&lt;/h2&gt;

&lt;p&gt;Control and clarity. The manager is the merchant of record; funds land in their Stripe right away. I’m not holding prize money or sitting in the middle—I’m just &lt;strong&gt;orchestrating&lt;/strong&gt; a smoother path from “I want that square” to “Paid.” That single decision removes a ton of compliance and reduces support emails to “How do I link Stripe?” (Answer: one button.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize mode on the horizon
&lt;/h2&gt;

&lt;p&gt;This ties directly into the next unlock: &lt;strong&gt;Prize mode&lt;/strong&gt;.&lt;br&gt;
Once payments are clean and verified, fulfilling prizes stops being a spreadsheet ritual and starts becoming a button press. Winners can be confirmed by the app; payouts can be structured; confusion disappears. That’s when the game starts to feel…professional.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we work (still vibing)
&lt;/h2&gt;

&lt;p&gt;The rhythm is the same every day:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A spark (“What if we just let managers bring Stripe?”)&lt;/li&gt;
&lt;li&gt;A quick vibe-storm with AI&lt;/li&gt;
&lt;li&gt;An implementation outline&lt;/li&gt;
&lt;li&gt;Build the smallest thing that changes reality&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’m learning Stripe as I go—dashboards, settings, the boring bits—because I’ll need those instincts when real users arrive. &lt;strong&gt;Vibe now, understand deeply later.&lt;/strong&gt; If we hit our two-month goal and go commercial, I’ll be ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;Tomorrow: &lt;strong&gt;wire up Prize mode&lt;/strong&gt;—the skeleton first, the polish later.&lt;br&gt;
Make the host’s job lighter, make game day smoother, and keep shipping while the idea’s hot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short version:&lt;/strong&gt; We turned “host-as-accountant” into &lt;strong&gt;tap → pay → play&lt;/strong&gt;. Fun leads again.&lt;/p&gt;

&lt;p&gt;About this journey&lt;br&gt;
I’m a former embedded coder who left Lockheed in the mid-1990s and haven’t seriously coded since. Beyond reading about today’s platforms, I came into this project knowing nothing about React, Next.js, Firebase, Vercel, or modern web app infrastructure. My goal is to have ChatGPT handle 99% of the coding while I guide the design, test the app, and provide feedback. What you’re reading is a day-by-day journal of building “Squares” — a commercial-ready sports squares app — with AI as my development partner.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Day 11 — Vibe the hard thing while you’re excited</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Thu, 28 Aug 2025 21:07:54 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/day-11-vibe-the-hard-thing-while-youre-excited-1plg</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/day-11-vibe-the-hard-thing-while-youre-excited-1plg</guid>
      <description>&lt;p&gt;Love it. Here’s a lightly polished, tighter pass that keeps your voice, jokes, and rhythm—just cleans up flow, headings, and formatting.&lt;/p&gt;




&lt;h1&gt;
  
  
  Day 11 — Do the hard thing while you’re excited
&lt;/h1&gt;

&lt;p&gt;Big idea today: &lt;strong&gt;when an idea pops up, go for it.&lt;/strong&gt; Start with a vibe brainstorm session then dive in on the implementation.  Do the complicated thing &lt;em&gt;while the spark is hot&lt;/em&gt;. We leaned straight into two gnarly threads—&lt;strong&gt;prize mode&lt;/strong&gt; and &lt;strong&gt;deeper Stripe integration&lt;/strong&gt;—because future-me never has more energy than present-me.&lt;/p&gt;

&lt;p&gt;I’ll keep saying it: for &lt;strong&gt;Squares&lt;/strong&gt;, the &lt;strong&gt;UI *is&lt;/strong&gt;* the product. Nail the feel and everything else (emails, backend, automation) lines up behind it. That’s why we shipped the &lt;strong&gt;multi-game invite&lt;/strong&gt; selector and left the email as a polite placeholder. Pixels first; paragraphs later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactor without guilt
&lt;/h3&gt;

&lt;p&gt;When a control wants to live in more than one place (hello, &lt;strong&gt;Time Zone&lt;/strong&gt;), pull it out and make it a component. Consistency is mercy.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Ricky Gervais PhD in Time Zones
&lt;/h3&gt;

&lt;p&gt;I’m basically writing a dissertation in “Optimal Human Time Selection.” Why are there &lt;strong&gt;so many&lt;/strong&gt; time-zone IDs when there are only 24 hours? Because every city council since 1912 tried remixing daylight saving like a DJ with commitment issues. Now we have hundreds of IDs so computers can remember that one summer in 1977 when a mayor declared “extra sunlight for morale.” Ricky would shrug: “I don’t care.” Users do—so we make it painless.&lt;/p&gt;

&lt;h3&gt;
  
  
  How we vibe (even writing this)
&lt;/h3&gt;

&lt;p&gt;This whole project—and this blog—is &lt;strong&gt;vibe-driven storytelling&lt;/strong&gt; with just enough structure to ship.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I &lt;strong&gt;brain-dump&lt;/strong&gt; messy voice notes (bad spelling, worse metaphors) and ask AI to make it into a blog using what it know we did today.&lt;/li&gt;
&lt;li&gt;AI does a &lt;strong&gt;formal first pass&lt;/strong&gt;. I roll my eyes, laugh, then steer it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AI first pass (too stiff):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Day 11 activities, emphasizing payment orchestration via Stripe Connect, UI refinements to the time zone selector, and preliminary specifications for prize-mode workflows. Subsequent iterations will address email templating and fulfillment operations.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;My reprompt (translation: vibe up, suit off):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Way less detail. High-level, philosophical, funny. Keep the Ricky Gervais / PhD-in-time-zone-picker joke. Conversational. Short beats. Pixels first; backend later.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;I then vibe up the Cover Image Chat.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;give me cover art for this blog post, keep my hair from yesterday mostly bald but put a bit on the front.  Have the AI say "I Don't care" in one of the frames.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;then about 10 iterations latter I settle.  Vibing is not without its frustrations.  Trying to get that UI to be perfect...might have to change courses, there are other options&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What we ship:&lt;/strong&gt;&lt;br&gt;
You’re reading it—&lt;strong&gt;“Do the hard thing while you’re excited.”&lt;/strong&gt; Pixels first, payouts next, jokes intact.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We &lt;strong&gt;co-edit fast&lt;/strong&gt;: keep the weird, trim the wobble, delete anything that smells like a status report.&lt;/li&gt;
&lt;li&gt;We hit &lt;strong&gt;publish while the idea’s warm&lt;/strong&gt;. No over-polishing, no ceremony—&lt;strong&gt;Build → Feel → Adjust&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Same loop for code: extract the gnarly piece, refactor without guilt, make it reusable.&lt;/li&gt;
&lt;li&gt;And yes, AI helps—but it’s a &lt;strong&gt;brilliant toddler&lt;/strong&gt;. I’m the adult in the room setting boundaries and taste.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  North star for the next lap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;#1 Stripe end-to-end&lt;/strong&gt; (connect, charge, fee).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prize mode skeleton&lt;/strong&gt; behind a flag—max prizes, simple categories; redemption later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-game invites&lt;/strong&gt; wired to real delivery once the screens settle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Short version of Day 11:&lt;/strong&gt; chase the spark, extract the gnarly bits, keep the jokes, and let the pixels lead.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 10)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Wed, 27 Aug 2025 17:40:22 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-10-567p</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-10-567p</guid>
      <description>&lt;h1&gt;
  
  
  Day 10 — Vibe Coding, Smarter Hand-offs, and Using Downtime Well
&lt;/h1&gt;

&lt;p&gt;Today’s theme was &lt;strong&gt;orchestrating&lt;/strong&gt; the work between a human and AI so neither of us just… waits.&lt;/p&gt;

&lt;h2&gt;
  
  
  What worked today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smarter chat hand-offs.&lt;/strong&gt; When I start a new chat, &lt;strong&gt;I&lt;/strong&gt; first ask the old chat to update its memory with what we just shipped. Then I open the new chat with a crisp question &lt;strong&gt;and&lt;/strong&gt; share context—like the current file tree or a single file. The AI shouldn’t guess what’s in my repo; &lt;strong&gt;I&lt;/strong&gt; give it the exact source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always upload the current file.&lt;/strong&gt; Before asking for edits, &lt;strong&gt;I&lt;/strong&gt; upload the file I’m about to change and then re-ask for the change on that file. This avoids “ghost edits.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pictures beat paragraphs.&lt;/strong&gt; Screenshots were a cheat code for quickly converging on the time-zone picker UI. The AI and the human both see the same thing, so feedback is concrete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systemic editing, not YOLO.&lt;/strong&gt; &lt;strong&gt;I&lt;/strong&gt; open files via the file manager first, then let AI propose edits. Flow: open → propose → apply → verify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brainstorm first, code second.&lt;/strong&gt; For thorny UX or policy choices, &lt;strong&gt;I&lt;/strong&gt; ask AI for a brief, no-code brainstorm to align on best practices. Then we implement. Fewer rewrites, faster merges.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Vibe coding = use the gaps
&lt;/h2&gt;

&lt;p&gt;There are natural pauses: a long code render, or a Vercel build (mine is ~1:30 now and will grow). Instead of staring at a spinner:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do a tiny chore (dishes, vacuum, reset your brain).&lt;/li&gt;
&lt;li&gt;Or open a &lt;strong&gt;parallel chat&lt;/strong&gt; to explore adjacent ideas. Today I used side chats to compare domains and sketch how managers might collect card fees. Progress compounds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My working playbook (repeatable)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Close the loop:&lt;/strong&gt; Ask old chat to “save what we did today” to memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New chat kickoff:&lt;/strong&gt; Post a clear question + paste the &lt;strong&gt;current file&lt;/strong&gt; or a &lt;strong&gt;file tree&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If visuals matter:&lt;/strong&gt; Drop a screenshot; ask the AI to react to what it sees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brainstorm (no code):&lt;/strong&gt; Align on approach, edge cases, and UX first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targeted edits:&lt;/strong&gt; Request a single-file change against the uploaded file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify quickly:&lt;/strong&gt; Run it, screenshot if needed, iterate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use downtime:&lt;/strong&gt; Chore or parallel chat—never idle.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tiny gotchas logged
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ZIP uploads:&lt;/strong&gt; Too large to be useful; stick to single files or short bundles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context drift:&lt;/strong&gt; Don’t assume the AI remembers your repo layout—paste it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI clarity:&lt;/strong&gt; Regional noise in time zones is real; we curated canonical zones and a “nearby” slice to keep the list readable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scaffolding &amp;amp; drift (new lesson)
&lt;/h2&gt;

&lt;p&gt;Sometimes the AI’s &lt;strong&gt;response scaffolding&lt;/strong&gt; (how it structures diffs/sections internally) can get out of sync with a long discussion. That’s when previously fixed screen widths reappear, or a “diff” doesn’t match the current file. This should improve as AI evolves—but the practical fix &lt;strong&gt;right now&lt;/strong&gt; is a stricter “Do It” hand-off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My “Do It” packet before any code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exact target(s):&lt;/strong&gt; File path(s) and only those files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decisions recap:&lt;/strong&gt; Bullet points from the brainstorm (UX choices, constraints, widths).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acceptance criteria:&lt;/strong&gt; What success looks like (e.g., “matches Manager width,” “time-zone list shows ‘nearby’ first”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source of truth:&lt;/strong&gt; Paste the &lt;em&gt;current&lt;/em&gt; file contents (even if we edited earlier).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No extras:&lt;/strong&gt; Ask AI to touch nothing outside the stated files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;strong&gt;I&lt;/strong&gt; collect and paste that packet, the AI’s output is consistent, the diffs line up, and the “wrong code showed up” problem disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;Vibe coding isn’t about rushing; it’s about &lt;strong&gt;keeping both the human and the AI in flow&lt;/strong&gt;. Small, well-framed tasks; tight feedback; and making the most of the quiet moments—plus a clean “Do It” packet—made Day 10 surprisingly productive.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 9)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Tue, 26 Aug 2025 16:51:31 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-9-99</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-9-99</guid>
      <description>&lt;h1&gt;
  
  
  Day 9 — Pairing With an AI (Without Losing the Plot)
&lt;/h1&gt;

&lt;p&gt;Today wasn’t about a giant feature drop—it was about &lt;strong&gt;how&lt;/strong&gt; a human–AI pair worked together to ship the right things and get un-stuck fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The jam session, not the checklist
&lt;/h2&gt;

&lt;p&gt;Instead of obsessing over a bullet list of UI widgets, the pair treated the work like a jam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;human&lt;/strong&gt; set the product intent (“Invites should feel native, not tacked on.”).&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;AI&lt;/strong&gt; sketched options and trade-offs (what to gate, what to defer).&lt;/li&gt;
&lt;li&gt;The conversation stayed anchored to &lt;strong&gt;the user flow&lt;/strong&gt;, not code golf.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That rhythm turned a rough “Create Square” form into a coherent flow with invites and helpful copy—without spiraling into yak-shaving.&lt;/p&gt;

&lt;h2&gt;
  
  
  React errors &amp;amp; the “don’t hallucinate” rule
&lt;/h2&gt;

&lt;p&gt;Opaque React errors (those minified numbers) are where an AI can drift—proposing plausible but irrelevant fixes. The &lt;strong&gt;human&lt;/strong&gt; pulled the &lt;strong&gt;AI&lt;/strong&gt; back to the &lt;strong&gt;actual render path&lt;/strong&gt; and insisted on proof.&lt;/p&gt;

&lt;p&gt;Shared debugging playbook:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reproduce&lt;/strong&gt; on the real route that breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary-search&lt;/strong&gt; the UI: swap custom parts with native tags to isolate the culprit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stub first, re-introduce slowly.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;console breadcrumbs&lt;/strong&gt;, not vibes.&lt;/li&gt;
&lt;li&gt;Touch &lt;strong&gt;only&lt;/strong&gt; files on the execution path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That discipline turned “mystery #130” into a straightforward fix; the build went green the moment a misplaced file was moved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the chat history
&lt;/h2&gt;

&lt;p&gt;A surprise hero was the &lt;strong&gt;saved chat&lt;/strong&gt;. Earlier sessions had removed &lt;code&gt;'use client'&lt;/code&gt; in specific places—on purpose. Having the receipts stopped regression and prevented undoing good changes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mini-practice: keep a tiny changelog inside the chat—what changed, why, and whether it’s final or experimental.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Vibe-coding is a partnership
&lt;/h2&gt;

&lt;p&gt;“Vibe-coding” works when &lt;strong&gt;the human&lt;/strong&gt; leads with product intuition and reality checks, and &lt;strong&gt;the AI&lt;/strong&gt; proposes concrete options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The human set guardrails (“don’t chase files we didn’t touch”).&lt;/li&gt;
&lt;li&gt;The human kept the flow honest (“Manager → Create → Form”).&lt;/li&gt;
&lt;li&gt;The human made the calls on UX semantics (invites can be staged but only send after the square exists).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;AI&lt;/strong&gt; moved fast, but &lt;strong&gt;the human&lt;/strong&gt; decided what mattered. That’s how a tight loop ships useful code instead of clever detours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns to keep
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gate actions on existence.&lt;/strong&gt; No sending invites until a square exists. Predictable and safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inform, don’t block.&lt;/strong&gt; Grey “already invited” contacts but keep them selectable for re-send.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline education.&lt;/strong&gt; Tiny “i” helpers and context-aware copy beat long docs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neutral language.&lt;/strong&gt; Tools support fundraisers or margin—UI doesn’t moralize.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One path at a time.&lt;/strong&gt; If a file wasn’t changed, don’t debug it today.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why today worked
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A shared mental model of the flow.&lt;/li&gt;
&lt;li&gt;Ruthless focus when errors popped up.&lt;/li&gt;
&lt;li&gt;Chat as living documentation.&lt;/li&gt;
&lt;li&gt;Quick product decisions (what to gate, grey, or default).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tomorrow’s polish will layer on (max squares per player, post-create sending, small UX flourishes), but the real win today was the &lt;strong&gt;process&lt;/strong&gt;: ship with intent, debug with evidence, and keep the loop tight between &lt;strong&gt;human&lt;/strong&gt; and &lt;strong&gt;AI&lt;/strong&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 8 - 8.5)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Mon, 25 Aug 2025 20:34:50 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-8-85-h77</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-8-85-h77</guid>
      <description>&lt;h1&gt;
  
  
  Day 8 → 8.5: Linked Squares shipped (mostly) — and the React #130 detour that proved why “vibe coding” needs a human driver
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; fan “Squares” app (Next.js / Firebase)&lt;br&gt;
&lt;strong&gt;Theme:&lt;/strong&gt; shipping a new &lt;strong&gt;Linked Squares&lt;/strong&gt; concept, then spending the back half untangling a gnarly React error in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The fun part (morning): Linked Squares 🧩
&lt;/h2&gt;

&lt;p&gt;We added a &lt;strong&gt;Linked Squares&lt;/strong&gt; model so managers can spin up a series of identical grids that share configuration and (optionally) a shared pot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Square → auto-creates &lt;strong&gt;Series S&lt;/strong&gt; + first &lt;strong&gt;Square P1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If demand exceeds capacity, auto-create &lt;strong&gt;P2, P3…&lt;/strong&gt; with same grid, numbers, teams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared pot&lt;/strong&gt; (series-level) vs &lt;strong&gt;per-square&lt;/strong&gt; payouts (single grid): we picked shared pot for linked series; lottery fallback if a single grid has unclaimed hits&lt;/li&gt;
&lt;li&gt;Redirect after create to the square page with a &lt;code&gt;?created=1&lt;/code&gt; banner and a copy-link / invite CTA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All green locally. Then we hit &lt;strong&gt;React error #130&lt;/strong&gt; in Preview.&lt;/p&gt;




&lt;h2&gt;
  
  
  The not-so-fun part (afternoon): React #130 and the loop of doom
&lt;/h2&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Minified React error #130 (“Element type is invalid: expected a string (for built-in components) or a class/function…”)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;First instinct (my AI pair):&lt;/strong&gt;&lt;br&gt;
Chase &lt;code&gt;/pools/[poolId]&lt;/code&gt; show page. We stubbed the page to raw HTML and still saw #130. We started combing wrappers, layouts, and error boundaries. Lots of motion, not enough progress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What changed the game:&lt;/strong&gt;&lt;br&gt;
We traced the &lt;strong&gt;actual user flow&lt;/strong&gt; end-to-end (Manager ➝ Create ➝ Form ➝ Save ➝ Redirect) and stubbed &lt;strong&gt;where the app actually was&lt;/strong&gt; when it crashed: the &lt;strong&gt;CreateSquareForm&lt;/strong&gt;. With a two-line stub we proved the route was fine. Then we restored sections incrementally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real root cause:&lt;/strong&gt;&lt;br&gt;
Our custom &lt;strong&gt;&lt;code&gt;Textarea&lt;/code&gt;&lt;/strong&gt; import resolved to &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; in Preview (Linux, case-sensitive FS). The file/export didn’t match the import casing/shape, so React tried to render &lt;code&gt;undefined&lt;/code&gt; as a component → &lt;strong&gt;#130&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Switching to the native &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; made the page render immediately, confirming the hypothesis. We then added a proper &lt;code&gt;components/ui/Textarea.tsx&lt;/code&gt; (correct casing, &lt;code&gt;"use client"&lt;/code&gt;, named export) and the form rendered.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this took longer than it should have
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error boundary masked the real throw.&lt;/strong&gt; Our custom error page broke too, which kept us staring at #130 instead of the underlying message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mac vs Linux gotcha.&lt;/strong&gt; Locally, case-insensitive FS lets &lt;code&gt;Textarea&lt;/code&gt; vs &lt;code&gt;textarea&lt;/code&gt; pass; Vercel Preview fails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vibe coding stall.&lt;/strong&gt; We were iterating on the wrong surface (/pools page) while the failure happened earlier (create form).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; AI can brainstorm quickly, but &lt;strong&gt;humans must steer&lt;/strong&gt; when we start looping. A small, targeted hypothesis (“let’s stub the form itself”) beat broad scanning.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The fix, boiled down
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prove it’s the form:&lt;/strong&gt; stub the component to pure HTML; if the error persists, it’s higher up. It disappeared → it &lt;strong&gt;was&lt;/strong&gt; the form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a one-line import sanity check:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[CSF imports]&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;Textarea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Input&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;// Anything undefined? That’s your #130.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Swap to native &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;&lt;/strong&gt; to unblock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restore custom UI&lt;/strong&gt; with correct path + export:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;File: &lt;code&gt;components/ui/Textarea.tsx&lt;/code&gt; (PascalCase, &lt;code&gt;"use client"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Export: &lt;code&gt;export function Textarea(...) { ... }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Import: &lt;code&gt;import { Textarea } from "@/components/ui/Textarea"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tiny process improvements we adopted
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Human “stall detector.”&lt;/strong&gt; If we repeat a hypothesis twice without new signal, &lt;strong&gt;change layers&lt;/strong&gt; (stub, log, or isolate).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental re-introduction.&lt;/strong&gt; Re-add components one at a time until the error returns; that’s the culprit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case-sensitive audits&lt;/strong&gt; before shipping: &lt;code&gt;grep&lt;/code&gt; for &lt;code&gt;@/components/ui/textarea&lt;/code&gt; vs &lt;code&gt;Textarea&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Diff markers that don’t collide with code.&lt;/strong&gt; Instead of &lt;code&gt;+&lt;/code&gt; / &lt;code&gt;-&lt;/code&gt; (which you might paste into files), use your custom markers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;-!*&amp;amp;&lt;/strong&gt; = remove&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;+&amp;amp;%&lt;/strong&gt;  = add&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error boundary toggle.&lt;/strong&gt; Temporarily rename &lt;code&gt;app/error.tsx&lt;/code&gt; / &lt;code&gt;global-error.tsx&lt;/code&gt; to reveal the true stack trace.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  A simple debugging playbook (copy/paste)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stub&lt;/strong&gt; the exact component where the crash shows up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log&lt;/strong&gt; &lt;code&gt;typeof&lt;/code&gt; of imported UI components — any &lt;code&gt;undefined&lt;/code&gt; means wrong path/export.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap to native HTML&lt;/strong&gt; for suspect components (e.g., &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;) to confirm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check casing&lt;/strong&gt; on paths; Vercel is case-sensitive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn off custom error UIs&lt;/strong&gt; to see the real runtime error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add back code in small chunks&lt;/strong&gt; until the break reappears.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  “Vibe coding” requires a human co-pilot
&lt;/h2&gt;

&lt;p&gt;This was a classic example of why AI + human works best when the human is ready to &lt;strong&gt;change tactics&lt;/strong&gt;. An engineer who can read console output, stub components, and reason about app flow can keep the session from going in circles. Without that, vibe coding risks getting stuck in a hallucinated hypothesis loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we still shipped today ✅
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Linked Squares concept &amp;amp; series model&lt;/li&gt;
&lt;li&gt;Shared-pot payout approach (with single-grid lottery fallback)&lt;/li&gt;
&lt;li&gt;Create flow + invites writing&lt;/li&gt;
&lt;li&gt;UI consistency (Accordion layout, mobile-friendly form)&lt;/li&gt;
&lt;li&gt;Fixed &lt;code&gt;Textarea&lt;/code&gt; component &amp;amp; eliminated the React #130 blocker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tomorrow: Refine the create square and manager dashboard UI for linked squares.  Onward.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 7)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Sun, 24 Aug 2025 21:18:40 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/-building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-7-3jc1</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/-building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-7-3jc1</guid>
      <description>&lt;h2&gt;
  
  
  About this journey
&lt;/h2&gt;

&lt;p&gt;I’m a former embedded coder who left Lockheed in the mid-1990s and haven’t seriously coded since. Beyond reading about today’s platforms, I came into this project knowing nothing about React, Next.js, Firebase, Vercel, or modern web app infrastructure. My goal is to have ChatGPT handle 99% of the coding while I guide the design, test the app, and provide feedback. What you’re reading is a day-by-day journal of building &lt;strong&gt;“Squares”&lt;/strong&gt; — a commercial-ready sports squares app — with AI as my development partner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 7: Email-Link Auth that Actually Works + Safer Preview Testing on Vercel
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Theme:&lt;/strong&gt; untangling Firebase Email-Link auth on Vercel, aligning domains and env vars, and adding a guarded “dev login” for Preview so I can iterate without hitting quotas.&lt;/p&gt;

&lt;h3&gt;
  
  
  What broke (and why)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;auth/unauthorized-continue-uri&lt;/code&gt;&lt;/strong&gt;: Magic links failed because my runtime app was pointed at the &lt;strong&gt;wrong Firebase project&lt;/strong&gt; (env mismatch), even though the allowlisted domain looked right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local &lt;code&gt;.env*&lt;/code&gt; confusion&lt;/strong&gt;: Repo had &lt;code&gt;.env.local&lt;/code&gt;, &lt;code&gt;.env.staging&lt;/code&gt;, &lt;code&gt;.env.production&lt;/code&gt;. Vercel uses its own Environment Variables; those files were misleading the build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quota exceeded&lt;/strong&gt;: Rapid testing hit &lt;code&gt;auth/quota-exceeded&lt;/code&gt;, which pushed me to add a Preview-only bypass.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The fixes that stuck
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Make the continue URL deterministic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build &lt;code&gt;continueUrl&lt;/code&gt; from &lt;code&gt;NEXT_PUBLIC_AUTH_RETURN_BASE&lt;/code&gt; (Preview uses &lt;code&gt;https://squares-staging.vercel.app&lt;/code&gt;), falling back to &lt;code&gt;window.location.origin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Log &lt;strong&gt;runtime Firebase config&lt;/strong&gt; (apiKey/projectId/authDomain) and the final &lt;strong&gt;continueUrl&lt;/strong&gt; for instant visibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2) Use Vercel envs as the source of truth
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Verified &lt;strong&gt;Preview&lt;/strong&gt; variables:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NEXT_PUBLIC_FIREBASE_API_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEXT_PUBLIC_FIREBASE_PROJECT_ID&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEXT_PUBLIC_AUTH_RETURN_BASE=https://squares-staging.vercel.app&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Moved local &lt;code&gt;.env*&lt;/code&gt; files &lt;strong&gt;out of the app tree&lt;/strong&gt; to avoid accidental use during builds.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3) Map the domain to the right environment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vercel → &lt;strong&gt;Project → Settings → Domains&lt;/strong&gt;
Connected &lt;code&gt;squares-staging.vercel.app&lt;/code&gt; to &lt;strong&gt;Preview&lt;/strong&gt; (branch &lt;code&gt;staging&lt;/code&gt;).
Result: magic links that land on &lt;code&gt;/auth&lt;/code&gt; resolve in the &lt;strong&gt;same&lt;/strong&gt; environment that sent them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4) “Remember this device” and route after sign-in
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set Firebase persistence to &lt;code&gt;browserLocalPersistence&lt;/code&gt; so signed-in users skip auth on revisit.&lt;/li&gt;
&lt;li&gt;Email-link completion reads &lt;code&gt;?role=manager|player&lt;/code&gt; and routes accordingly.&lt;/li&gt;
&lt;li&gt;If already signed in and &lt;strong&gt;not&lt;/strong&gt; on a link-complete URL, route to the last chosen role.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5) Preview-only dev login (no email needed)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client flag:&lt;/strong&gt; &lt;code&gt;NEXT_PUBLIC_BYPASS_MAGIC_LINK=true&lt;/code&gt; (Preview only).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server route:&lt;/strong&gt; &lt;code&gt;/api/dev-login&lt;/code&gt; issues a short-lived custom token via Firebase Admin &lt;strong&gt;only if&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A secret header matches &lt;code&gt;DEV_LOGIN_SECRET&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;The request is from the &lt;strong&gt;Preview&lt;/strong&gt; deployment.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Production path is unchanged; the bypass is Preview-scoped and guarded.&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Small but meaningful UX tweaks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manager dashboard&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Added a &lt;strong&gt;Logout&lt;/strong&gt; button next to &lt;strong&gt;Create New Square&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Free tier status now:
&lt;em&gt;“Free tier • 1 square at a time until {Mon DD} • Active squares: N”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purchase&lt;/strong&gt; panel starts &lt;strong&gt;collapsed&lt;/strong&gt;; Free Tier activation appears inside the dialog (less “prototype,” more “product”).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I learned (again)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If the error says &lt;strong&gt;“domain not allowlisted,”&lt;/strong&gt; verify the &lt;strong&gt;runtime&lt;/strong&gt; Firebase project. Logging &lt;code&gt;apiKey/projectId/authDomain&lt;/code&gt; beats guessing.&lt;/li&gt;
&lt;li&gt;Vercel &lt;strong&gt;Preview vs Production&lt;/strong&gt; is mostly &lt;strong&gt;domains + env vars&lt;/strong&gt;. Map correctly, set envs correctly, and the rest gets pleasantly boring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quotas&lt;/strong&gt; are real. A guarded Preview bypass keeps velocity high without compromising production auth.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Reflections from Day 7
&lt;/h2&gt;

&lt;p&gt;This was a classic “it’s configured… just not the way you think” day. Once I surfaced the runtime values and mapped the domain to Preview, Firebase Email-Link auth behaved. The guarded dev login let me iterate without poking the quota hornet’s nest. Bonus: a couple of small UI touches made the Manager dashboard feel like a product, not a demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Next steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vibe-code the “Create New Square” flow&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Minimal form: matchup/title, grid size (5×5 / 10×10), start/end, visibility.&lt;/li&gt;
&lt;li&gt;Client validation + friendly errors.&lt;/li&gt;
&lt;li&gt;Firestore write (draft → active), with optimistic UI on create.&lt;/li&gt;
&lt;li&gt;Invite flow stub (paste emails now; deeper contact picker later).&lt;/li&gt;
&lt;li&gt;Preview-only safeguards (no billing), Prod path ready to integrate with purchasing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 6)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Sun, 24 Aug 2025 20:57:41 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-6-47of</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-day-6-47of</guid>
      <description>&lt;h1&gt;
  
  
  Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 6)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;About this journey&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I’m a former embedded coder who left Lockheed in the mid-1990s and haven’t seriously coded since. Beyond reading about today’s platforms, I came into this project knowing nothing about React, Next.js, Firebase, Vercel, or modern web app infrastructure. My goal is to have ChatGPT handle 99% of the coding while I guide the design, test the app, and provide feedback. What you’re reading is a day-by-day journal of building “Squares” — a commercial-ready sports squares app — with AI as my development partner.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Day 6: Wrestling with Vercel Deployments and Resetting to a Clean Build
&lt;/h2&gt;

&lt;p&gt;If Days 4–5 were about code quality and TypeScript discipline, Day 6 was about facing the realities of &lt;strong&gt;deployment&lt;/strong&gt;. The goal was simple: get a successful build running in Vercel and make sure the app could be accessed in a browser. The reality? A full day of chasing build errors, learning how Vercel interprets commits, and finally rolling back to a known good state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Focus Areas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stripe build errors&lt;/strong&gt;: Vercel repeatedly failed with &lt;code&gt;Module not found: Can't resolve 'stripe'&lt;/code&gt; despite the dependency being present. We experimented with postinstall checks, dynamic imports, and package.json cleanup. In the end, these fixes were less important than realizing we had drifted into a messy state with too many half-fixes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error boundaries&lt;/strong&gt;: Along the way, new errors cropped up around Next.js error pages (&lt;code&gt;/404&lt;/code&gt;, &lt;code&gt;/500&lt;/code&gt;) involving hooks like &lt;code&gt;useContext&lt;/code&gt;. Some of these were introduced while debugging Stripe, highlighting how easy it is to destabilize an otherwise clean build.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git strategy&lt;/strong&gt;: The breakthrough came from stepping back and treating Git as a safety net. I created “rescue” branches, inspected commit history, and eventually rolled &lt;code&gt;main&lt;/code&gt; back to a &lt;strong&gt;known clean build commit&lt;/strong&gt; (&lt;code&gt;dddc1ae&lt;/code&gt;). Using GitHub Desktop’s &lt;strong&gt;Force Push Origin&lt;/strong&gt;, I reset remote &lt;code&gt;main&lt;/code&gt; to the working state and re-aligned Vercel with that baseline.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel settings&lt;/strong&gt;: Verified build settings (&lt;code&gt;npm ci&lt;/code&gt; for install, &lt;code&gt;next build&lt;/code&gt; for build, Node 22.x) and used &lt;strong&gt;Clear build cache&lt;/strong&gt; to avoid stale state. The preview deployment of the clean commit built flawlessly and was promoted to production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Workflow Lessons
&lt;/h3&gt;

&lt;p&gt;Today was less about code and more about &lt;strong&gt;process&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep commits clean and frequent. If I had checkpointed before diving into Stripe debugging, rolling back would have been even easier.
&lt;/li&gt;
&lt;li&gt;Understand how Vercel ties deployments to Git commits. “Redeploy” builds the same commit; if that commit is bad, only a reset or new commit will fix it.
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;force push with care&lt;/strong&gt;. It’s not something you do lightly, but when you know exactly which commit is good, it’s the fastest way to reset the project’s source of truth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reflections from Day 6
&lt;/h3&gt;

&lt;p&gt;This was a frustrating but ultimately &lt;strong&gt;empowering&lt;/strong&gt; day. The Stripe build errors consumed hours, but the real win was learning to manage Git branches, commits, and force pushes in a way that gave me back control. By evening, I had the app cleanly deployed on Vercel and accessible in a browser — a milestone worth celebrating.  &lt;/p&gt;

&lt;p&gt;More importantly, I realized this: &lt;strong&gt;not every problem is solved by more code&lt;/strong&gt;. Sometimes the smartest move is to stop, roll back, and protect the integrity of the project. That’s a lesson both in software engineering and in working with AI partners.&lt;/p&gt;




&lt;p&gt;✅ Next steps: With the clean build now live on Vercel, the focus shifts to &lt;strong&gt;testing access from a web browser&lt;/strong&gt; and validating end-to-end flows (auth, Firebase, Stripe stubs). Once stable, I’ll circle back to payments and subscriptions with a fresh perspective.  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Days 4–5)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Sun, 24 Aug 2025 20:44:23 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-days-4-5-4bmo</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-days-4-5-4bmo</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;About this journey&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I’m a former embedded coder who left Lockheed in the mid-1990s and haven’t seriously coded since. Beyond reading about today’s platforms, I came into this project knowing nothing about React, Next.js, Firebase, Vercel, or modern web app infrastructure. My goal is to have ChatGPT handle 99% of the coding while I guide the design, test the app, and provide feedback. What you’re reading is a day-by-day journal of building “Squares” — a commercial-ready sports squares app — with AI as my development partner.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Days 4–5: Debugging, Refactoring, and Preparing for Deployment
&lt;/h2&gt;

&lt;p&gt;After the whirlwind of Days 1–3 where we got a local prototype running in under 72 hours, the next phase (Days 4–5) was less about flashy new features and more about hardening the codebase, fixing TypeScript/ESLint issues, and preparing for a production-grade deployment on Vercel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Focus Areas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linting and TypeScript strictness&lt;/strong&gt;: We encountered dozens of &lt;code&gt;any&lt;/code&gt; type warnings and unused imports across files like &lt;code&gt;firebase.ts&lt;/code&gt;, &lt;code&gt;auth/page.tsx&lt;/code&gt;, &lt;code&gt;crypto.ts&lt;/code&gt;, and graphics components like &lt;code&gt;FlyingBall.tsx&lt;/code&gt; and &lt;code&gt;SquaresGridDemo.tsx&lt;/code&gt;. Rather than ignoring these errors, we systematically replaced them with explicit, strongly typed definitions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crypto utilities&lt;/strong&gt;: Refactored &lt;code&gt;lib/crypto.ts&lt;/code&gt; to properly track salts using &lt;code&gt;WeakMap&lt;/code&gt; instead of mutating &lt;code&gt;CryptoKey&lt;/code&gt; objects with &lt;code&gt;any&lt;/code&gt;. This eliminated &lt;code&gt;no-explicit-any&lt;/code&gt; warnings and ensured cleaner key handling.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error boundaries&lt;/strong&gt;: Updated &lt;code&gt;error.tsx&lt;/code&gt; and &lt;code&gt;global-error.tsx&lt;/code&gt; to use properly typed props (&lt;code&gt;Error &amp;amp; { digest?: string }&lt;/code&gt;) instead of &lt;code&gt;any&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firestore timestamps&lt;/strong&gt;: Standardized on &lt;code&gt;serverTimestamp()&lt;/code&gt; for &lt;code&gt;createdAt&lt;/code&gt;, &lt;code&gt;updatedAt&lt;/code&gt;, and &lt;code&gt;joinedAt&lt;/code&gt; fields in &lt;code&gt;pools.ts&lt;/code&gt;, &lt;code&gt;subscriptions.ts&lt;/code&gt;, and other data files. This improves consistency and avoids mixing client and server clocks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe setup&lt;/strong&gt;: Fixed missing dependency issues (&lt;code&gt;Module not found: Can't resolve 'stripe'&lt;/code&gt;) by installing Stripe properly and ensuring it was listed in &lt;code&gt;package.json&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase Admin&lt;/strong&gt;: We reclassified &lt;code&gt;firebase-admin&lt;/code&gt; as a &lt;code&gt;devDependency&lt;/code&gt; where appropriate to resolve build issues but also ensured runtime dependencies are in the right place for Vercel.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-commit hooks&lt;/strong&gt;: Cleaned up Husky’s &lt;code&gt;pre-commit&lt;/code&gt; script to run linting without blocking commits (warnings don’t prevent progress, but errors are still flagged).
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Workflow Refinement
&lt;/h3&gt;

&lt;p&gt;We also refined &lt;strong&gt;how ChatGPT provides code changes&lt;/strong&gt;. Instead of sending full rewritten files (hard to track) or plain prose (easy to miss changes), we settled on &lt;strong&gt;diff-style updates with &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;-&lt;/code&gt; prefixes&lt;/strong&gt;. This way, I can copy changes directly into Atom, delete the &lt;code&gt;+&lt;/code&gt; symbols, and apply them efficiently. It feels like pair programming with a very fast, meticulous partner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflections from Days 4–5
&lt;/h3&gt;

&lt;p&gt;This stretch wasn’t about rapid new features — it was about &lt;strong&gt;quality and confidence&lt;/strong&gt;. Every &lt;code&gt;any&lt;/code&gt; eliminated, every unused import cleaned, and every build warning squashed made the app feel more production-ready. It was also when I really saw the rhythm of this collaboration take shape: I provide direction and context, ChatGPT does 99% of the coding, and we iterate until things are stable.  &lt;/p&gt;

&lt;p&gt;It’s a different kind of software engineering — more like &lt;strong&gt;orchestrating and testing&lt;/strong&gt; than sitting down and grinding through syntax. And frankly, it feels like the future.  &lt;/p&gt;




&lt;p&gt;✅ Next steps: With linting and type safety under control, the focus shifts to &lt;strong&gt;deploying on Vercel with staging Firebase projects&lt;/strong&gt; and tackling subscription/payment flows end-to-end.  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building “Squares” with ChatGPT: From Prompts to a Commercial-Ready App (Day 1 -3)</title>
      <dc:creator>Nando Rama</dc:creator>
      <pubDate>Sun, 24 Aug 2025 20:42:28 +0000</pubDate>
      <link>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-33ma</link>
      <guid>https://dev.to/nando_rama_67753ecb8e0e6d/building-squares-with-chatgpt-from-prompts-to-a-commercial-ready-app-33ma</guid>
      <description>&lt;h1&gt;
  
  
  Vibe coding with ChatGPT (Days 1–3)
&lt;/h1&gt;

&lt;p&gt;I’m not a professional web developer. In fact, I haven’t coded seriously since the mid-1990s, when I left Lockheed as an embedded systems programmer. Since then, I’ve worked in other domains, and while I kept up with reading about technology trends, I had zero practical experience with modern platforms like React, Next.js, Firebase, or Vercel.  &lt;/p&gt;

&lt;p&gt;My goal: have ChatGPT write &lt;strong&gt;99%+ of the code&lt;/strong&gt; while I provide design ideas, product concepts, and do the testing.  &lt;/p&gt;

&lt;p&gt;In just 3 days we had a working local prototype. Here’s what we achieved.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 From Zero to Prototype in 3 Days
&lt;/h2&gt;

&lt;p&gt;With ChatGPT guiding me step by step, we had a local working prototype in just 3 days. That included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A functional auth flow with magic links (passwordless login).
&lt;/li&gt;
&lt;li&gt;A Manager Dashboard with accordion-based UI for Active Squares, Past Squares, Manage Contacts, and Purchase Options.
&lt;/li&gt;
&lt;li&gt;Mock data for testing without a database.
&lt;/li&gt;
&lt;li&gt;A Firestore schema drafted to handle managers, players, contacts, invites, and payouts:contentReference[oaicite:0]{index=0}.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each time I got stuck — whether it was a linting error, a missing dependency, or “where do we put this string?” — ChatGPT provided not only code fixes but best-practice explanations about why modern apps are structured this way.&lt;/p&gt;




&lt;h2&gt;
  
  
  🖼️ The Accordion UI: Prompt-Driven Design
&lt;/h2&gt;

&lt;p&gt;One of the most satisfying outcomes was the accordion-driven dashboard.&lt;/p&gt;

&lt;p&gt;I suggested:&lt;br&gt;&lt;br&gt;
&lt;em&gt;“Wouldn’t it be better if purchase options were expandable lists, so the UI can scale as we add bundles and sales?”&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;ChatGPT translated that into React components using Tailwind, complete with nested accordions and purchase dialogs. It wasn’t just code — it was a &lt;strong&gt;scalable UI design pattern&lt;/strong&gt; that will handle future growth without rewrites.&lt;/p&gt;

&lt;p&gt;This became a theme: I provided the vision in plain English, ChatGPT provided drop-in file replacements (like full &lt;code&gt;page.tsx&lt;/code&gt; files), and together we iterated until it felt right:contentReference[oaicite:1]{index=1}.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Database Schema: Modernizing My 1990s Mindset
&lt;/h2&gt;

&lt;p&gt;Coming from embedded systems, I thought in terms of tables and rows. ChatGPT helped me modernize that thinking into Firestore’s document-oriented design.&lt;/p&gt;

&lt;p&gt;We ended up with a schema that balances manager-centric contact lists with player-centric identity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managers with contact/payment IDs and their owned Squares.
&lt;/li&gt;
&lt;li&gt;Players with unique UIDs, multiple emails (primary + alternates), and payment preferences.
&lt;/li&gt;
&lt;li&gt;Squares with grid mappings, costs, payout %, and invites.
&lt;/li&gt;
&lt;li&gt;Contacts searchable by prefixes, powered by a helper script.
&lt;/li&gt;
&lt;li&gt;Invites to reconcile pending and claimed squares, even if emails change:contentReference[oaicite:2]{index=2}.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I learned how modern identity systems use UIDs as the stable key (instead of emails, which can change). ChatGPT explained trade-offs I wouldn’t have thought of on my own.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Helpers and Developer Experience
&lt;/h2&gt;

&lt;p&gt;We also built scripts to support real-world development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seeder scripts to populate mock data.
&lt;/li&gt;
&lt;li&gt;Backfill scripts for search indexes.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;help.js&lt;/code&gt; — a custom CLI helper that documents all npm run scripts and explains why and when to use them:contentReference[oaicite:3]{index=3}.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This last one was a game-changer. Instead of scrolling through &lt;code&gt;package.json&lt;/code&gt; or pasting old ChatGPT answers, I can now just run &lt;code&gt;npm run help&lt;/code&gt; and get a living developer guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Dealing with Chat Memory Limits
&lt;/h2&gt;

&lt;p&gt;One surprising challenge wasn’t technical at all: ChatGPT’s &lt;strong&gt;memory window&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As the project grew, the chat slowed down, and responses became less focused. To solve this, I worked with ChatGPT to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;strong&gt;context snapshots&lt;/strong&gt; (summaries and even scripts like &lt;code&gt;make-ai-context.mjs&lt;/code&gt;) to carry between chats.
&lt;/li&gt;
&lt;li&gt;Save project summaries and architecture notes as Word/Markdown files.
&lt;/li&gt;
&lt;li&gt;Restart fresh chats without losing continuity:contentReference[oaicite:4]{index=4}.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process let me keep momentum — even when the conversation hit the AI’s limits.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 From Lockheed to Vercel
&lt;/h2&gt;

&lt;p&gt;When I left Lockheed in the ’90s, deploying meant burning code into ROM or distributing binaries. Now, with ChatGPT walking me through, I’m deploying with a couple of clicks on &lt;strong&gt;Vercel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The staging workflow we set up:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub repo connected to Vercel.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env.staging&lt;/code&gt; with Firebase credentials.
&lt;/li&gt;
&lt;li&gt;Firebase console configured for email-link auth and domain whitelisting.
&lt;/li&gt;
&lt;li&gt;Automatic redeploys on &lt;code&gt;git push&lt;/code&gt;:contentReference[oaicite:5]{index=5}.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The contrast couldn’t be more stark: 3 days to a working web app with global hosting, compared to months of setup in the old world.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 What We’ve Achieved So Far
&lt;/h2&gt;

&lt;p&gt;✅ Mobile-friendly auth and dashboard UIs.&lt;br&gt;&lt;br&gt;
✅ Database schema and helpers.&lt;br&gt;&lt;br&gt;
✅ Mock data + seeding scripts.&lt;br&gt;&lt;br&gt;
✅ Deployment pipeline (GitHub → Vercel → Firebase).&lt;br&gt;&lt;br&gt;
✅ Developer ergonomics (help.js, husky hooks).&lt;br&gt;&lt;br&gt;
✅ A working prototype I can demo to real users — in under a week:contentReference[oaicite:6]{index=6}.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Replace mock data with live Firestore queries.
&lt;/li&gt;
&lt;li&gt;Build out claiming and payment validation flows.
&lt;/li&gt;
&lt;li&gt;Test end-to-end notifications (email during games, win alerts).
&lt;/li&gt;
&lt;li&gt;Continue refining UI polish for both managers and players.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
