<?xml version="1.0" encoding="UTF-8"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Kisho Mahadevan - Full Stack Software Engineer</title><link>https://kisho.uk</link><description>Full Stack Developer with over 3 years of experience in building high-quality web applications using Typescript, React, Node.js, and more.</description><generator>Zola</generator><language>en</language><atom:link href="https://kisho.uk/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Fri, 20 Jun 2025 00:00:00 +0000</lastBuildDate><item><title>Gratis vs Libre Software</title><pubDate>Fri, 20 Jun 2025 00:00:00 +0000</pubDate><author>k12n</author><link>https://kisho.uk/writing/gratis-vs-libre/</link><guid>https://kisho.uk/writing/gratis-vs-libre/</guid><description xml:base="https://kisho.uk/writing/gratis-vs-libre/">&lt;p&gt;Gratis means free of charge. Libre means free to use, study, modify, and share. A lot of software is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gratis_versus_libre&quot;&gt;gratis without being libre&lt;&#x2F;a&gt;, meaning you pay nothing, but the app may track &amp;amp; store your data in a format only it can read, and can change the rules or disappear whenever its owner feels like it. Libre flips this, you get the source, you can run it on your own hardware, and you have somewhere to go if the maintainers drift.&lt;&#x2F;p&gt;
&lt;p&gt;Most of what I run is off-the-shelf &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Free_software&quot;&gt;free software&lt;&#x2F;a&gt;. Open formats, open protocols, no vendor lock-in.  Here is a short list that earns its keep:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;about.gitea.com&quot;&gt;&lt;strong&gt;Gitea&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: self-hosted git server.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.wireguard.com&quot;&gt;&lt;strong&gt;WireGuard&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: for tunnels.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mullvad.net&quot;&gt;&lt;strong&gt;Mullvad&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: the good, public VPN.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.proxmox.com&quot;&gt;&lt;strong&gt;Proxmox&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: the hypervisor. does hypervisor things.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.debian.org&quot;&gt;&lt;strong&gt;Debian&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: a very stable OS.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;immich.app&quot;&gt;&lt;strong&gt;Immich&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: photos.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description></item><item><title>Connect Four AI</title><pubDate>Sat, 02 Mar 2024 00:00:00 +0000</pubDate><author>k12n</author><link>https://kisho.uk/projects/connect-four-ai/</link><guid>https://kisho.uk/projects/connect-four-ai/</guid><description xml:base="https://kisho.uk/projects/connect-four-ai/">&lt;p&gt;An implementation of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Minimax&quot;&gt;minimax&lt;&#x2F;a&gt; applied to Connect Four. Play against the AI, or flip to two-player mode.&lt;&#x2F;p&gt;
&lt;p&gt;I first came across minimax while studying for a Game Theory module during my Economics degree, the usual setting for it is social dilemmas and rational-actor analysis (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Tragedy_of_the_commons&quot;&gt;tragedy of the commons&lt;&#x2F;a&gt; being the canonical example). Minimax also happens to be a tidy fit for two-player zero-sum board games, so once I’d seen it applied to strategic decisions the Connect Four port felt like the obvious exercise.&lt;&#x2F;p&gt;
&lt;p&gt;The board state lives in the URL. That means moves are preserved by the browser’s page history: forward&#x2F;back navigates through the game turn-by-turn, and you can share a position by copying the address bar. As a happy accident, if you tinker with the URL directly you can make &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;connect4.kisho.uk&#x2F;?r=jj&amp;amp;p=one&amp;amp;b=2221222.2211122.2111112.1111111.1112111.2112112&quot;&gt;pixel art&lt;&#x2F;a&gt; out of the board. A &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;connect4.kisho.uk&#x2F;?r=jj&amp;amp;p=one&amp;amp;b=2221222.2211122.2111112.1111111.1112111.2112112&quot;&gt;heart&lt;&#x2F;a&gt;, for instance:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2221222.2211122.2111112.1111111.1112111.2112112&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</description></item><item><title>Finfo</title><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><author>k12n</author><link>https://kisho.uk/projects/finfo/</link><guid>https://kisho.uk/projects/finfo/</guid><description xml:base="https://kisho.uk/projects/finfo/">&lt;p&gt;Finfo aggregated equities news, tickers, and basic fundamentals into a single page you could keep open during the trading day. Next.js + Chakra UI front-end pulling from a small set of free market-data and news APIs, cached aggressively to stay under rate limits.&lt;&#x2F;p&gt;
&lt;p&gt;The interesting work was less in the React and more in the normalisation layer: reconciling four sources that all disagreed about ticker suffixes, company names, and event timestamps into a single uniform feed.&lt;&#x2F;p&gt;
&lt;p&gt;Archived because the APIs I relied on have mostly paywalled. If I rebuilt it today it’d be a small CLI that piped into my existing self-hosted RSS reader, not a web app.&lt;&#x2F;p&gt;
</description></item><item><title>Galaxy Quest</title><pubDate>Mon, 10 Oct 2022 00:00:00 +0000</pubDate><author>k12n</author><link>https://kisho.uk/projects/galaxy-quest/</link><guid>https://kisho.uk/projects/galaxy-quest/</guid><description xml:base="https://kisho.uk/projects/galaxy-quest/">&lt;p&gt;A top-down space shooter built in PhaserJS where the controls come from a DualShock 4 over Web Bluetooth. You pair the pad to the tab once, then analogue sticks, triggers, and face buttons all map cleanly into the game loop as if you were using a native API.&lt;&#x2F;p&gt;
&lt;p&gt;The draw was the Web Bluetooth plumbing, not the game. Sony’s pad speaks a standard GATT HID profile but the axis centring, dead zones, and battery-level characteristic are all slightly off-spec, so a fair amount of the code is just poking at the right descriptors and normalising the values. Once that layer was solid, the actual Phaser scene was small: a handful of entities, a scrolling starfield, collision against a pool of asteroids.&lt;&#x2F;p&gt;
</description></item></channel></rss>