<?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: Haixin GUI</title>
    <description>The latest articles on DEV Community by Haixin GUI (@haixin_gui_d3b00fad431528).</description>
    <link>https://dev.to/haixin_gui_d3b00fad431528</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%2F4207574%2Fcbf0d9b5-1915-4af0-90a3-1103e6defd76.png</url>
      <title>DEV Community: Haixin GUI</title>
      <link>https://dev.to/haixin_gui_d3b00fad431528</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haixin_gui_d3b00fad431528"/>
    <language>en</language>
    <item>
      <title>Building a budget-first PC parts calculator: allocation, not selection</title>
      <dc:creator>Haixin GUI</dc:creator>
      <pubDate>Mon, 26 Oct 2026 03:07:29 +0000</pubDate>
      <link>https://dev.to/haixin_gui_d3b00fad431528/building-a-budget-first-pc-parts-calculator-allocation-not-selection-1dla</link>
      <guid>https://dev.to/haixin_gui_d3b00fad431528/building-a-budget-first-pc-parts-calculator-allocation-not-selection-1dla</guid>
      <description>&lt;p&gt;Every PC part picker I tried assumed I already knew what I wanted. You open it, and it asks: which CPU? Which motherboard? Which GPU?&lt;/p&gt;

&lt;p&gt;But if you have a fixed budget — say $900 — that is backwards. You do not want to research eight components. You want to know what $900 actually buys, and where the money should go.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://pcpartscalc.com/" rel="noopener noreferrer"&gt;Partwise&lt;/a&gt;, a budget-first PC build calculator. This post is about the two decisions that shaped it, and one mistake worth stealing.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Model allocation, not selection
&lt;/h2&gt;

&lt;p&gt;A traditional picker is a selection tool: you choose parts, it tells you if they fit. That works when the user already knows the target.&lt;/p&gt;

&lt;p&gt;A budget-first tool inverts it. The input is a total budget plus a workload (gaming, creating, work). The output is a parts list where each component gets a weight, and the weights are what the user actually cares about.&lt;/p&gt;

&lt;p&gt;The interesting code is not "is this GPU compatible" — it is "if the user raises the GPU priority, which other components give way, and by how much".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;gaming&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;psu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;case&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;board&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;creating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;psu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;case&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;board&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ratios are opinionated and I expect people to disagree. That is fine — the argument is now about allocation, not about which part to pick first.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Keep the catalog finite and say so
&lt;/h2&gt;

&lt;p&gt;The calculator uses a finite reference catalog with real prices. It will not invent a GPU to absorb the last $40 of a budget.&lt;/p&gt;

&lt;p&gt;That constraint felt like a weakness at first. It turned out to be the most trustworthy part of the product: a leftover balance is normal, and telling users "you do not have to spend everything" is more useful than padding a list.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The mistake: I shipped an interactive component too early
&lt;/h2&gt;

&lt;p&gt;The compatibility checker started as a small interactive widget: four dropdowns, instant pass/fail. It crashed on every interaction. Not sometimes — every time, with the same hydration error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NotFoundError: Failed to execute 'insertBefore' on 'Node'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server-rendered markup and the first client frame disagreed, React tried to patch a node that was not where it expected, and the page fell over. I tried three fixes: an error boundary, rendering after mount, and a client-only route. Each changed the symptom (white screen, then a missing component, then "checker failed to load") without removing the cause.&lt;/p&gt;

&lt;p&gt;What finally worked was deleting the component. The page is now four static reference tables — sockets, DDR4/DDR5, GPU clearance, PSU wattage — rendered on the server, with zero client state.&lt;/p&gt;

&lt;p&gt;It is less impressive in a demo. It is strictly better for the person who just wants to know whether a Ryzen 5 7600 fits a B650 board.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do differently
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Build the static version first, then ask whether interactivity earns its complexity.&lt;/li&gt;
&lt;li&gt;Treat hydration as a product risk, not a build warning.&lt;/li&gt;
&lt;li&gt;Write the copy for the empty state before building the feature. If the empty state is confusing, the feature is probably wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The calculator is free and needs no signup: &lt;a href="https://pcpartscalc.com/" rel="noopener noreferrer"&gt;pcpartscalc.com&lt;/a&gt;. If the allocation ratios look wrong to you, I would genuinely like to hear which ones and why — that is the part I am least sure about.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>sideprojects</category>
    </item>
  </channel>
</rss>
