<?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: Amine Amine</title>
    <description>The latest articles on DEV Community by Amine Amine (@asimplecode).</description>
    <link>https://dev.to/asimplecode</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%2F4209928%2F8ff24c82-29ae-49f4-bb22-be960649dc22.jpg</url>
      <title>DEV Community: Amine Amine</title>
      <link>https://dev.to/asimplecode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asimplecode"/>
    <language>en</language>
    <item>
      <title>Why Simplicity Wins in Software Engineering</title>
      <dc:creator>Amine Amine</dc:creator>
      <pubDate>Tue, 27 Oct 2026 05:09:26 +0000</pubDate>
      <link>https://dev.to/asimplecode/why-simplicity-wins-in-software-engineering-1noo</link>
      <guid>https://dev.to/asimplecode/why-simplicity-wins-in-software-engineering-1noo</guid>
      <description>&lt;p&gt;Every software engineer has faced it: the pull toward complexity. A new abstraction layer here, a design pattern there, a framework on top of a framework. Before you know it, a feature that should take an afternoon takes a sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Complexity Tax
&lt;/h2&gt;

&lt;p&gt;Complexity is a silent tax on every team. It slows onboarding, increases bugs, and makes refactoring feel like defusing a bomb. The most impactful engineers I've worked with aren't the ones who write the cleverest code — they're the ones who write code that anyone can understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Principles
&lt;/h2&gt;

&lt;p&gt;Over the years, I've distilled my approach into three principles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Delete before you add.&lt;/strong&gt; The best code is no code. Before writing a new utility, check if the problem can be solved by removing something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Name things for the next reader.&lt;/strong&gt; A variable called &lt;code&gt;userEmailVerificationStatus&lt;/code&gt; is better than &lt;code&gt;s&lt;/code&gt;. Verbosity in naming is not the same as verbosity in code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Optimize for change.&lt;/strong&gt; Requirements will shift. Write code that's easy to modify, not code that's "perfect" for today's spec.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where SimpleCode Came From
&lt;/h2&gt;

&lt;p&gt;SimpleCode started as a personal experiment: what if building a website were as simple as describing it? No boilerplate, no configuration, no templates to wrestle with. Just tell the AI what you want, and it builds it.&lt;/p&gt;

&lt;p&gt;That builder is still in the workshop and not ready for real users yet. Holding it back is the same principle at work: a feature earns its place by making things simpler, not by existing. In the meantime, &lt;a href="https://www.simplecode.ca" rel="noopener noreferrer"&gt;simplecode.ca&lt;/a&gt; is where I try these ideas in public.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Simplicity isn't the absence of features. It's the result of ruthless prioritization. Every line of code is a liability. Every abstraction is a bet that you'll need it again. Make those bets wisely.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.simplecode.ca/blog/why-simplicity-wins-in-software" rel="noopener noreferrer"&gt;simplecode.ca&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>cleancode</category>
      <category>career</category>
    </item>
    <item>
      <title>Building a K Command Palette (and a Fake Terminal) for My Portfolio</title>
      <dc:creator>Amine Amine</dc:creator>
      <pubDate>Tue, 27 Oct 2026 05:00:02 +0000</pubDate>
      <link>https://dev.to/asimplecode/building-a-k-command-palette-and-a-fake-terminal-for-my-portfolio-4976</link>
      <guid>https://dev.to/asimplecode/building-a-k-command-palette-and-a-fake-terminal-for-my-portfolio-4976</guid>
      <description>&lt;p&gt;Press &lt;strong&gt;⌘K&lt;/strong&gt; (or Ctrl+K) anywhere on &lt;a href="https://www.simplecode.ca" rel="noopener noreferrer"&gt;my site&lt;/a&gt; and you get a search box that jumps to any page, case study, game, blog post or Dota 2 hero. Press &lt;strong&gt;&lt;code&gt;~&lt;/code&gt;&lt;/strong&gt; and you get a terminal. Neither is essential. Both are the kind of detail that makes a developer's site feel like it was made by a developer.&lt;/p&gt;

&lt;p&gt;Here's how they're built, and the few decisions that kept them simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logic first, UI second
&lt;/h2&gt;

&lt;p&gt;Both features are mostly logic, so I wrote the logic as &lt;strong&gt;pure functions&lt;/strong&gt; with no React involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;buildItems(posts, heroes, work)&lt;/code&gt; returns a flat list of &lt;code&gt;{ group, label, url, keywords }&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filterItems(items, query)&lt;/code&gt; ranks them;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;runCommand(input)&lt;/code&gt; returns &lt;code&gt;{ lines, action }&lt;/code&gt; for the terminal, where &lt;code&gt;action&lt;/code&gt; is "navigate", "clear" or "exit";&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;complete(input)&lt;/code&gt; does tab completion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The React components only render state and call these. That made them trivial to smoke-test: "typing &lt;code&gt;wraith&lt;/code&gt; ranks Wraith King first", "&lt;code&gt;cd blog/&lt;/code&gt; goes to the blog", "&lt;code&gt;c&lt;/code&gt; + Tab doesn't complete, because it's ambiguous".&lt;/p&gt;

&lt;h2&gt;
  
  
  Ranking without a fuzzy-search library
&lt;/h2&gt;

&lt;p&gt;Fuzzy matching libraries are great, but for a hundred or so items a tiny score does the job. For each word you type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a match at the start of the label scores 0 (best);&lt;/li&gt;
&lt;li&gt;a match at the start of any word in the label scores 1;&lt;/li&gt;
&lt;li&gt;a match anywhere in the label scores 2;&lt;/li&gt;
&lt;li&gt;a match in the group or keywords scores 3;&lt;/li&gt;
&lt;li&gt;no match anywhere, and the item is out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then sort by score, keeping the original order for ties. Keywords do the quiet work: "resume" finds the Experience section, and "hire" finds the contact page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't load what nobody asked for
&lt;/h2&gt;

&lt;p&gt;Dota has 120+ heroes, and putting all of them in every page's HTML would be wasteful. The palette fetches hero names &lt;strong&gt;the first time someone opens it&lt;/strong&gt;, from an endpoint that's already cached for an hour. When the palette is empty, heroes stay hidden so the list starts with pages, not a wall of hero names.&lt;/p&gt;

&lt;h2&gt;
  
  
  The terminal
&lt;/h2&gt;

&lt;p&gt;It's a &lt;code&gt;switch&lt;/code&gt; statement with personality. &lt;code&gt;help&lt;/code&gt;, &lt;code&gt;whoami&lt;/code&gt;, &lt;code&gt;ls projects&lt;/code&gt;, &lt;code&gt;cat resume&lt;/code&gt;, &lt;code&gt;cd contact&lt;/code&gt; and &lt;code&gt;play chess&lt;/code&gt; all do something real. &lt;code&gt;sudo&lt;/code&gt; tells you that simplicity is not negotiable, and &lt;code&gt;vim&lt;/code&gt; reassures you that &lt;code&gt;exit&lt;/code&gt; works here. Arrow keys walk your history, Tab completes, and Ctrl+L clears.&lt;/p&gt;

&lt;p&gt;It uses the site's dark theme tokens, so it looks right without any one-off colours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Respecting the person typing
&lt;/h2&gt;

&lt;p&gt;I record anonymous usage events to see whether people actually use this. For the terminal, I only store the &lt;strong&gt;command word&lt;/strong&gt;, and only if it's a command I know. Anything else is recorded as &lt;code&gt;other&lt;/code&gt;. If someone types a sentence into a fake shell, it stays in their browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Open &lt;a href="https://www.simplecode.ca" rel="noopener noreferrer"&gt;simplecode.ca&lt;/a&gt;, press ⌘K and type &lt;code&gt;chess&lt;/code&gt;, or press &lt;code&gt;~&lt;/code&gt; and type &lt;code&gt;help&lt;/code&gt;. If you find a command I should add, &lt;a href="https://www.simplecode.ca/get-in-touch" rel="noopener noreferrer"&gt;tell me&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.simplecode.ca/blog/building-a-command-palette-and-a-fake-terminal" rel="noopener noreferrer"&gt;simplecode.ca&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>ux</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Verifying Every Chess Puzzle on My Home Page with a Tiny Solver</title>
      <dc:creator>Amine Amine</dc:creator>
      <pubDate>Tue, 27 Oct 2026 04:56:59 +0000</pubDate>
      <link>https://dev.to/asimplecode/verifying-every-chess-puzzle-on-my-home-page-with-a-tiny-solver-1emm</link>
      <guid>https://dev.to/asimplecode/verifying-every-chess-puzzle-on-my-home-page-with-a-tiny-solver-1emm</guid>
      <description>&lt;p&gt;My home page opens with a chess puzzle: White to play, mate in 2. It's the first thing visitors see, so it can't be wrong. A puzzle with two solutions, or one that's secretly a mate in 1, makes the whole site look sloppy.&lt;/p&gt;

&lt;p&gt;I didn't want to check positions by hand, so I made the computer do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The definition, written as code
&lt;/h2&gt;

&lt;p&gt;A mate-in-2 puzzle has &lt;strong&gt;exactly one&lt;/strong&gt; first move for White such that, whatever Black replies, White can then deliver checkmate. Written down, that's three small functions on top of the chess engine that already powers &lt;a href="https://www.simplecode.ca/games/chess-master" rel="noopener noreferrer"&gt;Chess Master&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isCheckmate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChessPosition&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generateLegalMoves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isInCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/** After White's first move: does every Black reply allow mate in one? */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;forcesMateInOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChessPosition&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isCheckmate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&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;replies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateLegalMoves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// stalemate&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generateLegalMoves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isCheckmate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;makeMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A smoke test then checks every puzzle in the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's White to move;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;no&lt;/strong&gt; legal move is an immediate checkmate (otherwise it's really a mate in 1);&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;exactly one&lt;/strong&gt; legal move passes &lt;code&gt;forcesMateInOne&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's brute force, and that's fine. Puzzle positions are small: a few dozen first moves, a few dozen replies, a few dozen follow-ups. All 35 puzzles verify in about three seconds. In the browser, the same check runs when you make a move and takes around 2ms.&lt;/p&gt;

&lt;p&gt;There's a nice side effect: the UI never compares your move against a stored answer. It asks the engine whether your move &lt;em&gt;works&lt;/em&gt;. If a position ever had a second solution, it would still accept it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting real puzzles, without downloading 300MB
&lt;/h2&gt;

&lt;p&gt;Hand-made positions look artificial, so I wanted positions from real games. The &lt;a href="https://database.lichess.org/#puzzles" rel="noopener noreferrer"&gt;Lichess puzzle database&lt;/a&gt; is released under CC0 and tags puzzles with themes like &lt;code&gt;mateIn2&lt;/code&gt;. The catch is size: around 300MB compressed, millions of rows.&lt;/p&gt;

&lt;p&gt;I only needed a few hundred candidates, so I streamed it and stopped early:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://database.lichess.org/lichess_db_puzzle.csv.zst &lt;span class="se"&gt;\&lt;/span&gt;
  | zstd &lt;span class="nt"&gt;-dc&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 600 mateIn2 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; mate2.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep -m 600&lt;/code&gt; exits after 600 matches, which closes the pipe, which stops the download. A few seconds instead of a few minutes.&lt;/p&gt;

&lt;p&gt;Then a selection script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Replays the opponent's move.&lt;/strong&gt; Lichess stores the position &lt;em&gt;before&lt;/em&gt; the opponent's last move, so I apply it to get the actual puzzle position.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filters.&lt;/strong&gt; White to move, rating 900–2000, well-liked and played often, at most 22 pieces so it reads well on a phone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifies with my engine&lt;/strong&gt;, and also checks that my engine's single key move matches Lichess's solution. Two independent sources agreeing is a good sign that both are right.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;95 positions survived. I took every third one across the rating range, added two I'd composed myself, and shuffled them with a fixed seed so easy and hard days alternate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I like about this
&lt;/h2&gt;

&lt;p&gt;The solver is a few dozen lines, and it replaces a checklist I would eventually have got wrong. When I add puzzles, the test either passes or tells me exactly which one is broken.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; weekends now get a mate in 3, verified by a generalised version of the same solver, and every past puzzle is in the &lt;a href="https://www.simplecode.ca/puzzles" rel="noopener noreferrer"&gt;archive&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you haven't yet, &lt;a href="https://www.simplecode.ca/" rel="noopener noreferrer"&gt;go solve today's puzzle&lt;/a&gt;. Your streak lives in your browser, and the share button gives you a little 🟩 to brag with.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.simplecode.ca/blog/verifying-chess-puzzles-with-a-tiny-solver" rel="noopener noreferrer"&gt;simplecode.ca&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chess</category>
      <category>typescript</category>
      <category>testing</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
