<?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: Raz Chiriac</title>
    <description>The latest articles on DEV Community by Raz Chiriac (@raz_chiriac_b5dbbe8de7932).</description>
    <link>https://dev.to/raz_chiriac_b5dbbe8de7932</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F908203%2F8f7e6fb1-e96d-4daa-9b3f-d3be67575289.jpeg</url>
      <title>DEV Community: Raz Chiriac</title>
      <link>https://dev.to/raz_chiriac_b5dbbe8de7932</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raz_chiriac_b5dbbe8de7932"/>
    <language>en</language>
    <item>
      <title>I built a sudoku app where the AI coach is never allowed to be wrong</title>
      <dc:creator>Raz Chiriac</dc:creator>
      <pubDate>Mon, 05 Oct 2026 14:43:21 +0000</pubDate>
      <link>https://dev.to/raz_chiriac_b5dbbe8de7932/i-built-a-sudoku-app-where-the-ai-coach-is-never-allowed-to-be-wrong-3g03</link>
      <guid>https://dev.to/raz_chiriac_b5dbbe8de7932/i-built-a-sudoku-app-where-the-ai-coach-is-never-allowed-to-be-wrong-3g03</guid>
      <description>&lt;p&gt;I play sudoku most mornings. Every app I tried was either slow to enter digits, covered in ads, or both. So I built &lt;a href="https://kodiaksudoku.com" rel="noopener noreferrer"&gt;Kodiak Sudoku&lt;/a&gt;, and along the way I ran into three problems that turned out more interesting than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Making 81 cells feel instant
&lt;/h2&gt;

&lt;p&gt;A sudoku board is 81 cells, each with up to 9 pencil marks. If typing a digit rerenders the whole grid, you feel it, especially on a cheap phone.&lt;/p&gt;

&lt;p&gt;What worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zustand with one selector per field.&lt;/strong&gt; Each cell subscribes only to its own value, its notes and whether it's selected. Typing a 7 rerenders one cell, plus the cells that need to highlight matching 7s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes as bitmasks.&lt;/strong&gt; All 81 cells' notes live in a single &lt;code&gt;Uint16Array&lt;/code&gt;. Bit 3 set means "3 is a candidate". Toggling a note is one XOR, and comparing two cells' notes is one integer compare, which makes the memoized cell comparator trivial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard first.&lt;/strong&gt; Arrow keys or hjkl to move, digits to place, N for notes mode, U and R for undo and redo, ? for the full list. One window-level listener reads from the store directly, so there's no React state in the hot path.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// toggle candidate d (1-9) in cell i&lt;/span&gt;
&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// is d a candidate?&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;has&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. A daily puzzle you can't cheat
&lt;/h2&gt;

&lt;p&gt;The daily puzzle has a leaderboard, and a leaderboard is only worth anything if it's honest. The rule I set early: &lt;strong&gt;the solution never reaches the browser.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client gets the givens only.&lt;/li&gt;
&lt;li&gt;Hints go through a server action that looks up the stored solution, returns one cell, and records that you used a hint.&lt;/li&gt;
&lt;li&gt;When you finish, the server compares your board with the stored solution before writing a completion.&lt;/li&gt;
&lt;li&gt;Anonymous solves don't count toward the board. You can play without signing in, but the leaderboard needs an account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hints are allowed on the daily, and the board shows how many each player used. That turned out fairer than banning them. There are now weekly, monthly and all-time standings too, ranked by dailies solved and then average time.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. An AI coach that can't hallucinate a move
&lt;/h2&gt;

&lt;p&gt;This was the part I was most nervous about. I wanted a coach that looks at your actual board and says something like "look at box 5, the 4 can only go in two cells". Language models are good at that kind of explanation. They are also very good at confidently suggesting a digit that's wrong.&lt;/p&gt;

&lt;p&gt;A wrong digit on someone's board is the worst possible failure. It's silent, and it breaks trust in everything else. So the design is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The model sees the board, never the solution.&lt;/strong&gt; It has to reason about the position like a person would.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The output is a strict schema.&lt;/strong&gt; A short nudge, a one-sentence reason, and an &lt;em&gt;optional&lt;/em&gt; move (cell plus digit). Anything that doesn't parse is thrown away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every suggested move is checked server-side&lt;/strong&gt; against the stored solution and against the deterministic solver's next step. If it fails, the move is dropped and only the explanation is shown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There's a 2.5 second budget.&lt;/strong&gt; If the model is slower, the player gets a deterministic hint from the solver with a canned explanation for that technique. The panel never comes back empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The client can't redirect the check.&lt;/strong&gt; Each request verifies that the submitted board's givens match the original puzzle, so a tampered board can't point the validator at a different solution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The validation function is the most heavily tested code in the project. Rejected moves are logged, so I can see if a model update starts guessing more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teaching, not just solving
&lt;/h2&gt;

&lt;p&gt;The coach works best when the player knows the vocabulary, so I added a Technique Journey: 15 short lessons from naked singles to swordfish. Each lesson is a real, verified puzzle you solve in place, and the same boards show up inside the &lt;a href="https://kodiaksudoku.com/blog" rel="noopener noreferrer"&gt;blog posts&lt;/a&gt;, so you can try an &lt;a href="https://kodiaksudoku.com/blog/x-wing-sudoku" rel="noopener noreferrer"&gt;x-wing&lt;/a&gt; right next to the explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Next.js 15 (App Router), React 19, Supabase for Postgres and auth, Drizzle with hand-written SQL migrations, Zustand, Zod at every server boundary. Hosted on Vercel. Payments are Stripe Checkout called with plain &lt;code&gt;fetch&lt;/code&gt;, no SDK. Puzzles come from a public dataset of 3 million rated sudokus, bucketed into four difficulty levels, and every one is checked by the solver for a unique solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it pays for itself
&lt;/h2&gt;

&lt;p&gt;The game, the daily, the leaderboards and the lessons are free with no ads. Kodiak Plus adds the AI coach, AI post-game debriefs and unlimited quick play. Everyone else still gets solver-based hints. There's also an Android app.&lt;/p&gt;

&lt;p&gt;If you play, I'd love to hear how the keyboard controls feel and whether Hard is actually hard. The daily puzzle resets at midnight UTC.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>ai</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>How I built the sudoku site I always wanted (Next.js 15, Supabase, keyboard-first)</title>
      <dc:creator>Raz Chiriac</dc:creator>
      <pubDate>Sun, 10 May 2026 15:17:14 +0000</pubDate>
      <link>https://dev.to/raz_chiriac_b5dbbe8de7932/how-i-built-the-sudoku-site-i-always-wanted-nextjs-15-supabase-keyboard-first-4pbp</link>
      <guid>https://dev.to/raz_chiriac_b5dbbe8de7932/how-i-built-the-sudoku-site-i-always-wanted-nextjs-15-supabase-keyboard-first-4pbp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Every sudoku site I've ever used has the same two problems: ads everywhere, and a mouse-only UI that makes fast solving feel clunky. I play sudoku to think, not to fight with my browser.&lt;/p&gt;

&lt;p&gt;So I built my own. It's called &lt;strong&gt;Kodiak Sudoku&lt;/strong&gt; — free, no ads, keyboard-first, with vim bindings and a leaderboard that doesn't lie. Here's what went into it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 15&lt;/strong&gt; with the App Router&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React 19&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; throughout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase&lt;/strong&gt; for the database (auth, leaderboard storage, daily puzzle state)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drizzle ORM&lt;/strong&gt; on top of Supabase&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailwind CSS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; for hosting + Edge Config for feature flags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing exotic — just a stack I could move fast with and trust in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three things I actually cared about
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Free with no ads
&lt;/h3&gt;

&lt;p&gt;This sounds simple but it shapes every decision. No ad SDK to load, no layout shift, no third-party trackers. The page is fast because there's nothing slowing it down. I'm covering hosting costs out of pocket for now — Vercel and Supabase's free tiers go surprisingly far for a side project at this scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Keyboard-first, with vim bindings
&lt;/h3&gt;

&lt;p&gt;Most sudoku sites are built for mouse/touch. Clicking individual cells is fine on mobile, but on desktop it's slow. I wanted to navigate the board the way I navigate everything else — with hjkl, or arrow keys, or number keys to fill in digits instantly.&lt;/p&gt;

&lt;p&gt;The input handling ended up being one of the more interesting parts of the build. React's synthetic event system and the browser's native focus behavior don't always agree, especially when you're trying to make a grid feel like a text editor. Getting vim-style navigation to feel snappy without fighting the DOM took a few iterations.&lt;/p&gt;

&lt;p&gt;If you're into this kind of thing — keyboard-driven UIs, focus management, accessibility — I'd love to hear how you've solved similar problems.&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%2Fx1p8hsx6z9zkuc8xtgkc.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%2Fx1p8hsx6z9zkuc8xtgkc.png" alt="Kodiak Sudoku Home Page" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Honest leaderboards
&lt;/h3&gt;

&lt;p&gt;This one bugged me about every other sudoku leaderboard I've seen: hint-assisted times compete directly against pure runs. Someone who used three hints finishing in 4 minutes shouldn't outrank someone who solved it clean in 5.&lt;/p&gt;

&lt;p&gt;Kodiak separates the two. Pure runs and hint-assisted runs are ranked independently. It's a small thing but it changes how the leaderboard actually feels — it's something you can be proud of, not just a number.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interesting technical bits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Daily puzzle state at the edge
&lt;/h3&gt;

&lt;p&gt;The daily puzzle is the same for everyone, every day. I'm using Vercel Edge Config to store and serve the active puzzle, which means the puzzle data is globally distributed and available with essentially zero latency. State per-user (progress, timer, hints used) lives in Supabase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drizzle + Supabase
&lt;/h3&gt;

&lt;p&gt;I'd used Prisma before and wanted to try Drizzle. The type inference is excellent and the query builder feels closer to writing SQL, which I prefer. The integration with Supabase was smooth — I'm using Supabase for auth and RLS policies, with Drizzle handling the query layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puzzle generation vs. curation
&lt;/h3&gt;

&lt;p&gt;I ended up curating puzzles rather than generating them on the fly. Generated puzzles can technically be valid but feel mechanically similar. Hand-selected (or at least filtered) puzzles have more character. For the daily puzzle specifically, I wanted something people would actually enjoy solving, not just a valid grid.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I used Claude for
&lt;/h2&gt;

&lt;p&gt;Claude was my pair-programmer throughout. Not in a "it wrote the whole thing" way — more like having a senior dev available to rubber-duck architecture decisions, catch edge cases in my input handling logic, and help me move faster on the parts I found tedious (writing marketing copy, mostly).&lt;/p&gt;

&lt;p&gt;The parts that required actual judgment — how to structure the leaderboard, how to handle timer state across tab visibility changes, how to make the keyboard UX feel right — those were conversations, not prompts. Worth being honest about the difference.&lt;/p&gt;




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

&lt;p&gt;The site is live now at &lt;strong&gt;&lt;a href="https://kodiaksudoku.com" rel="noopener noreferrer"&gt;kodiaksudoku.com&lt;/a&gt;&lt;/strong&gt;. Daily puzzles, leaderboards, full keyboard support including vim bindings.&lt;/p&gt;

&lt;p&gt;Things I'm thinking about for v2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mobile experience improvements (touch is functional but not delightful yet)&lt;/li&gt;
&lt;li&gt;Puzzle difficulty ratings based on solving technique, not just time&lt;/li&gt;
&lt;li&gt;A "practice mode" for specific techniques (naked pairs, X-wing, etc.)&lt;/li&gt;
&lt;li&gt;A Loom walkthrough once I've seen how real users actually play&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build keyboard-first apps, care about honest UX, or just play a lot of sudoku — I'd genuinely love to hear from you. What would make this better?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Next.js, Supabase, Drizzle, Tailwind, and Vercel. Pair-programmed with Claude.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>typescript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Console Wrangling</title>
      <dc:creator>Raz Chiriac</dc:creator>
      <pubDate>Sun, 14 Aug 2022 16:15:05 +0000</pubDate>
      <link>https://dev.to/raz_chiriac_b5dbbe8de7932/console-wrangling-2k2p</link>
      <guid>https://dev.to/raz_chiriac_b5dbbe8de7932/console-wrangling-2k2p</guid>
      <description>&lt;h2&gt;
  
  
  Have you ever console logged the console?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---c5xEVXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihj627kwiml7gk0gqo80.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---c5xEVXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihj627kwiml7gk0gqo80.jpg" alt="Thanos console" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you know the good ol’ &lt;code&gt;console.log()&lt;/code&gt; ? &lt;/p&gt;

&lt;p&gt;Well, that’s not the only thing the console can do, it’s only the most basic. &lt;/p&gt;

&lt;p&gt;Have you ever used the console to log the console? No? You should try it. &lt;/p&gt;

&lt;p&gt;The console will show you what the console can do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KxdmH5d1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0q4ve5ihlkpof7x4q5bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KxdmH5d1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0q4ve5ihlkpof7x4q5bj.png" alt="console console" width="560" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today we’ll talk about two of the functions available on the console object:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;console.table()&lt;/code&gt; and &lt;code&gt;console.trace()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets say we have two objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;carA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ford&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F150&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2018&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;carB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ford&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F250&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2016&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we wanted to do some debugging and had to print these objects out to the console we could use &lt;code&gt;console.log()&lt;/code&gt; but it wont look too nice.&lt;/p&gt;

&lt;p&gt;Look how neat &lt;code&gt;console.table()&lt;/code&gt; can display the two objects:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YmmVbIg4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bs04i5n1ekoact10x5fb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YmmVbIg4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bs04i5n1ekoact10x5fb.png" alt="console table" width="536" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can even sort the two rows by column just by clicking on the headers!&lt;/p&gt;

&lt;p&gt;One other console function we’ll talk about today is &lt;code&gt;console.trace()&lt;/code&gt;. This will output a stack trace to the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y3CvRRt1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag4apxwdgre4514w38l9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y3CvRRt1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag4apxwdgre4514w38l9.png" alt="console trace" width="512" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s all for today.&lt;/p&gt;

&lt;p&gt;I hope I’ve helped make your debugging a little less boring. Now go show off your new console skills in your next stand-up.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Object Equality in JavaScript</title>
      <dc:creator>Raz Chiriac</dc:creator>
      <pubDate>Sat, 13 Aug 2022 16:33:00 +0000</pubDate>
      <link>https://dev.to/raz_chiriac_b5dbbe8de7932/object-equality-in-javascript-2k96</link>
      <guid>https://dev.to/raz_chiriac_b5dbbe8de7932/object-equality-in-javascript-2k96</guid>
      <description>&lt;p&gt;Howdy! Here’s a simple way to check for object equality.&lt;/p&gt;

&lt;p&gt;Let’s say we have two objects:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const carA = {make: 'Ford', model: 'F150', year: '2018', color: 'white'}&lt;br&gt;
const carB = {make: 'Ford', model: 'F150', year: '2018', color: 'white'}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can see that &lt;code&gt;carA&lt;/code&gt; is the same as &lt;code&gt;carB&lt;/code&gt;. So we would expect &lt;code&gt;carA === carB&lt;/code&gt; to return true but it does not. This is because JavaScript checks for equality on non-primitive types like Objects, Arrays and Dates by reference.  This means, JavaScript checks if the two objects point to the same place in memory, not if they have the same key-value pairs.&lt;/p&gt;

&lt;p&gt;One way to check for key-value equality of two objects, without the use of an external  library or much coding is by converting the objects to strings using &lt;code&gt;JSON.stringify()&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;&lt;code&gt;carA == carB // =&amp;gt; false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;carA === carB // =&amp;gt; false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;JSON.stringify(carA) === JSON.stringify(carB) // =&amp;gt; true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keep in mind that this approach only works if the key-value pairs are in the same order on both objects. We could go into sorting object entries by key and other approaches in future posts.&lt;/p&gt;

&lt;p&gt;Cheers! 🫖&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
