{
	"version": "https://jsonfeed.org/version/1.1",
	"title": "Developer Blog",
	"language": "en",
	"home_page_url": "https://hackodes.com/",
	"feed_url": "https://hackodes.com/feed/feed.json",
	"description": "A personal developer blog about software, security and the projects I build.",
	"author": {
		"name": "hackodes",
		"url": "https://hackodes.com/about/"
	},
	"items": [
		{
			"id": "https://hackodes.com/blog/2017/08/13/first-post/",
			"url": "https://hackodes.com/blog/2017/08/13/first-post/",
			"title": "First Post",
			"content_html": "<p>Right now, I'm using WordPress to manage and host all the content for this blog. I'm mostly going to use this space for content writing, post ideas, updates on projects and anything else that comes to mind.</p>\n<p>The design for this site is still in progress. I still have some work to do on the template for this blog so that it fits perfectly with the rest of the site. There are various customisation options so it will be nice to try out different things to figure out what works well etc.</p>\n<p>That's all for now, see you in the next update.</p>\n",
			"date_published": "2017-08-13T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2017/08/16/useful-tools/",
			"url": "https://hackodes.com/blog/2017/08/16/useful-tools/",
			"title": "Useful Tools",
			"content_html": "<p>I just thought that I should make a post about some useful software that I use regularly. I highly recommend these tools because they are free and useful. I'll probably update this post at some point in the future if I come across any more useful tools.</p>\n<h2 id=\"keepass\" tabindex=\"-1\">Keepass <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2017/08/16/useful-tools/#keepass\">#</a></h2>\n<p>This is a useful tool for managing and storing all passwords in one single secure database. I find this useful because you do not need to remember all your different passwords for various websites. The software also features a password generator. There is also a mobile app available which keeps everything easy to manage. The best thing about it is that it's open-source software. You can learn more about Keepass <a href=\"https://keepass.info/\">here</a>.</p>\n<h2 id=\"draw-io\" tabindex=\"-1\">Draw.io <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2017/08/16/useful-tools/#draw-io\">#</a></h2>\n<p>When I was looking for a software to design a map for a game project I was working on, I found Draw.io. I personally think that this is probably the best free to use drawing tool available. It’s open-source, easy to use and supports most web browsers. The interface is quite nice and you can export your finished product to a wide range of different file formats. You cannot have any complaints. You can learn more about Draw.io <a href=\"https://www.diagrams.net/\">here</a>.</p>\n<h2 id=\"cyberduck\" tabindex=\"-1\">Cyberduck <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2017/08/16/useful-tools/#cyberduck\">#</a></h2>\n<p>I have used this tool for some months now and it works great. I’ve used this to transfer files to cloud storage as well as make changes to my files quickly. It’s pretty useful if you want to make changes to files in real-time, saved files are updated automatically. It also features a bookmark section which can be used to save and connect easily. You can learn more about Cyberduck <a href=\"https://cyberduck.io/\">here</a>.</p>\n",
			"date_published": "2017-08-16T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2017/08/17/changing-themes/",
			"url": "https://hackodes.com/blog/2017/08/17/changing-themes/",
			"title": "Changing Themes",
			"content_html": "<p>Since the last post, I've decided to change into a different blog theme. The previous one looked too complex and I decided to go for something much simpler. I've also enabled comments so there should be a way to post a comment at the bottom of each post now.</p>\n<p>Have fun commenting!</p>\n",
			"date_published": "2017-08-17T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2017/08/22/practicing-concepts/",
			"url": "https://hackodes.com/blog/2017/08/22/practicing-concepts/",
			"title": "Practicing Concepts",
			"content_html": "<p>Recently, I have been trying to learn Java by building a small project using object-oriented programming concepts. I think this is a good exercise for me to familiarise myself with Java's syntax and structure while building a practical application.</p>\n<p>As for the small project, it's a turn-based role-playing game with three distinct playable heroes - a warrior, a magician and an archer. Each hero has its own strengths and weaknesses which should make the game interesting and strategic. These heroes will be able to explore different areas within the game, finding unique items while battling various enemies.</p>\n<p>So far, I'm working on building, setting up and linking areas together. A useful way to design maps is through diagrams, these can save a lot of time when you actually work on the code making it easier to figure out how the areas are connected to each other. Ideally, I want the game to have around 50 unique areas with different types of zones. Some zones are safe, some have a chance to encounter an enemy and red areas are supposed to be not safe at all!</p>\n<p>As of now, the game is still in its early stages but I plan to add more features depending on time.</p>\n",
			"date_published": "2017-08-22T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2017/09/02/some-progress/",
			"url": "https://hackodes.com/blog/2017/09/02/some-progress/",
			"title": "Some Progress",
			"content_html": "<p>The small project that I've been working on has made some good progress. I've managed to script the main interactions such as character movement, inventory and switching between heroes. Movement is done using the interface or with 'N', 'S', 'E', 'W' keys. Pressing these keys will make the character move into another location (North, South, East, and West). There is also an 'Examine' command that can be used to explore the character's current location in more detail. This includes finding out more information on where the character is, enemy activity level and if there are any items nearby etc.</p>\n<p>I'm quite happy with the way the inventory system turned out. I've separated out the inventory for each character, ensuring each individual hero carries their own items and there's an inventory space cap to restrict how many items can be carried at one time. In future, my plan is to add multiple choices within the inventory such as use, sell, and destroy like most role-playing games. Don't like an item in your inventory? Simply destroy it.</p>\n<p>My next goal is to work on the enemy battle system once the inventory is fully completed. That will be on my list next.</p>\n",
			"date_published": "2017-09-02T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2017/09/19/project-update/",
			"url": "https://hackodes.com/blog/2017/09/19/project-update/",
			"title": "Project Update",
			"content_html": "<p>The area exploration and the battle system for the game is now finished. Specific enemy types now spawn in a certain area. There will be some designated areas for boss battles which are going to be more challenging fights but the rewards will be greater than defeating the usual enemies.</p>\n<p>I am currently prioritising my work on three things:</p>\n<ul>\n<li>Creating a detailed character information sheet in the game. Its purpose is to show extra information about each character to make the game feel more immersive. The current one could do with some improvements so I'll probably need to do some rework in this area.</li>\n<li>Battle system is complete, however I am not 100% convinced that it will work once the characters advance to higher levels. It can get quite easy once the characters become stronger therefore I may need to make a few improvements to make it a challenge and keep the game remain challenging.</li>\n<li>Selling items. I plan to add this feature to the game, I think there should be a way to earn something instead of destroying items to reduce inventory limit! I’m thinking of adding a marketplace in the main town, this can possibly be an area to sell items.</li>\n</ul>\n<p>There is still work to be done, however I'll probably aim to get these done in the next few weeks or so. Stay tuned.</p>\n",
			"date_published": "2017-09-19T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2017/10/14/new-features/",
			"url": "https://hackodes.com/blog/2017/10/14/new-features/",
			"title": "New Features",
			"content_html": "<p>Since the last post, I've added a lot of new features into the game and I'll briefly write some new additions that I have made.</p>\n<ul>\n<li>\n<p>A saving system. This allows the current state of the game to be saved and loaded. I thought about adding this a while ago. Now you can reload and continue the game from where you left. To save the game, all three heroes need to be in the Town Hall location.</p>\n</li>\n<li>\n<p>A marketplace location. In an earlier post, I was planning to add a place where characters can sell items. I've now finished adding this into the game. Each character has an individual inventory, containing their current gold and items. Visiting the marketplace will allow the character to sell items and this will be a good way to earn some gold while getting rid of items which may no longer be needed.</p>\n</li>\n<li>\n<p>Boss battles. This is a major part of the game, the heroes will be able to fight strong and powerful bosses for unique items. Each boss has a special location within the game, these are secret zones which can be discovered by exploring the map.</p>\n</li>\n</ul>\n<p>Those are some of the features that I thought about mentioning, there are more additions that I've made but I'll possibly make another post about those in future.</p>\n",
			"date_published": "2017-10-14T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2019/09/24/new-platform/",
			"url": "https://hackodes.com/blog/2019/09/24/new-platform/",
			"title": "New Platform",
			"content_html": "<p>After a lengthy hiatus, the blog is back! 🎉</p>\n<p>I've finally had the time to build a new blog site. WordPress is good, but I always wanted to create a fully customizable site that is fast and productive. There are plenty of alternatives out there, but I opted to go with GitHub Pages because you can host websites straight from a GitHub repository and it's completely free.</p>\n<p>If you're wondering, this current version of the site is built using Jekyll - a simple, blog-aware, static site generator. It integrates really well with GitHub, making publishing new content really easy. Instead of using databases to store content, Jekyll renders Markdown templates and creates a complete, static website ready to be served by a web server. This means the website has faster loading times because there is little server-sided scripting to serve the content. You can read more about Jekyll <a href=\"https://jekyllrb.com/\">here</a>.</p>\n<p>You may have also noticed that the commenting platform that I am using for this site is different. I am using the Disqus comments plug-in to set up a commenting system without needing a web server at all.</p>\n<p>Like the old site, I plan to use this one to write about a wide range of things like tech topics, current projects and more. I'm still in the process of moving content and posts from the old site to this one so it may take some time until it's all complete. In the coming weeks, I'll post more frequently just like before. That's all for now.</p>\n<p>Thanks for reading.</p>\n",
			"date_published": "2019-09-24T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2019/10/08/storing-passwords-securely/",
			"url": "https://hackodes.com/blog/2019/10/08/storing-passwords-securely/",
			"title": "Storing Passwords Securely",
			"content_html": "<p>Most websites nowadays require an account to be registered before you can use their services. That means you need to provide at least an email, a password and potentially other personal information with it. I'm self-conscious about registering my details on too many websites because you can never be too sure if the data will be kept safe and secure. Trust is important because the expectation is that the information will be handled responsibly. Unfortunately, a data breach can happen at any moment which means that with more account registrations over time, the risk of being affected by a data breach becomes more likely.</p>\n<p>That's where websites like <a href=\"https://haveibeenpwned.com\">Have I Been Pwned?</a> become useful because it lets you check if your email has been discovered in any data breaches. It has all kinds of information like what type of breach it was, the date of breach and the kind of information that was leaked. If you notice any of your accounts have been breached then the first action is to change your password. We should be smart about the passwords we use, make them as complex and lengthy as possible but definitely <strong>do not</strong> use the same password for every website! Data breaches give us a good idea why using the same password is not a good idea. When passwords are compromised in data breaches, they are usually leaked in hashed form. If a common password is used then it becomes vulnerable to techniques like rainbow table attacks. This technique uses a precomputed table containing a list of common hashed passwords which can then be used to quickly decrypt and gain access to accounts.</p>\n<p>Best way to manage complex passwords is with a reliable password manager which can be used to store passwords for all websites so you don't need to write them down or remember them at all. Generally, the password manager requires a master password that unlocks access to all stored passwords. As it is the key to all your other passwords, it's important to make this password as lengthy and complex as possible.</p>\n",
			"date_published": "2019-10-08T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2019/10/22/errors-in-interfaces/",
			"url": "https://hackodes.com/blog/2019/10/22/errors-in-interfaces/",
			"title": "Errors in Interfaces",
			"content_html": "<p>Design decisions are important as it relates to building good interfaces. It's not the user's fault when an error happens but the designer's responsibility for making sure there aren't any flaws in the design. The designers are responsible for building interfaces that feel natural and work within the limits of human cognition. This means that if a user makes an error, it could be that there are flaws in the design which don't work with human thought processes.</p>\n<p>For example, if a button placement or label is confusing then the user might end up clicking the wrong option unintentionally. If the instructions are poorly written or there's a lack of feedback then it can lead to the user making an error which ends up causing frustration. Instructions should be clear - use plain language and understandable visual cues. One important thing to consider is that users can experience cognitive load. This happens when the task requires a lot of mental effort or when the information being displayed exceeds the user's cognitive capacity. It's better to show less information at a time.</p>\n",
			"date_published": "2019-10-22T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2019/11/08/the-knapsack-problem/",
			"url": "https://hackodes.com/blog/2019/11/08/the-knapsack-problem/",
			"title": "The Knapsack Problem",
			"content_html": "<p>The knapsack problem is a classic problem that is simple to explain but surprisingly tricky to solve well. It's all about making the best choice when you have limited space and too many things to choose from.</p>\n<p>Imagine you're packing a knapsack (or backpack) for a trip. The knapsack can only carry a limited weight and you have a pile of items to choose from. Each item has its own weight and its own value. You can't take everything, so the goal is to pick the items that give you the highest total value without going over the weight limit.</p>\n<ul>\n<li><strong>Items:</strong> each one has a weight and a value.</li>\n<li><strong>Capacity:</strong> the maximum total weight the knapsack can carry.</li>\n<li><strong>Goal:</strong> get the highest total value without going over the capacity.</li>\n</ul>\n<h2 id=\"a-small-example\" tabindex=\"-1\">A small example <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2019/11/08/the-knapsack-problem/#a-small-example\">#</a></h2>\n<p>Let's say the knapsack can carry a maximum weight of 7 and there are four items to choose from.</p>\n<table>\n<thead>\n<tr>\n<th>Item</th>\n<th>Weight</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>A</td>\n<td>1</td>\n<td>1</td>\n</tr>\n<tr>\n<td>B</td>\n<td>3</td>\n<td>4</td>\n</tr>\n<tr>\n<td>C</td>\n<td>4</td>\n<td>5</td>\n</tr>\n<tr>\n<td>D</td>\n<td>5</td>\n<td>7</td>\n</tr>\n</tbody>\n</table>\n<p>An obvious approach is to pick the items that give the most value for their weight first. Item D has the best ratio (7 value for 5 weight) so that goes in first. That leaves room for 2 more weight so the only thing that fits is item A. The total value is 7 + 1 = 8.</p>\n<p>But the best answer is actually B and C. Their weight adds up to exactly 7 and their value is 4 + 5 = 9. So picking the best looking item each time doesn't always give the best result which is what makes this problem interesting. A choice that looks great early on can leave you without enough room for a better combination later.</p>\n<h2 id=\"solving-it\" tabindex=\"-1\">Solving it <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2019/11/08/the-knapsack-problem/#solving-it\">#</a></h2>\n<p>You could try every possible combination of items and see which one is best, but the number of combinations doubles with every item added. This is fine for four items but it becomes way too slow with a large number of items.</p>\n<p>A better way is to use dynamic programming. The idea is to solve smaller versions of the problem first and reuse those answers instead of working them out again and again. We can build a table where each cell stores the best value we can get using the first <code>i</code> items with a capacity of <code>w</code>. For each item, there are only two options: leave it out or take it (if it fits) and add its value to the best result we had with the remaining capacity.</p>\n<pre class=\"language-python\" tabindex=\"0\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">knapsack</span><span class=\"token punctuation\">(</span>weights<span class=\"token punctuation\">,</span> values<span class=\"token punctuation\">,</span> capacity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    n <span class=\"token operator\">=</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>values<span class=\"token punctuation\">)</span>\n    dp <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span> <span class=\"token keyword\">for</span> _ <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span>capacity <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">for</span> _ <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span>n <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n\n    <span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> n <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">for</span> w <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span>capacity <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">if</span> weights<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;=</span> w<span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># Take the best of leaving the item out or putting it in</span>\n                dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>w<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">max</span><span class=\"token punctuation\">(</span>dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>w<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>w <span class=\"token operator\">-</span> weights<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> values<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># The item is too heavy so we have to leave it out</span>\n                dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>w<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>w<span class=\"token punctuation\">]</span>\n\n    <span class=\"token keyword\">return</span> dp<span class=\"token punctuation\">[</span>n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>capacity<span class=\"token punctuation\">]</span>\n\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>knapsack<span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  <span class=\"token comment\"># 9</span></code></pre>\n<p>Running it with the items above gives us 9 which matches what we found by hand. The table has one row per item and one column per capacity so the amount of work depends on both the number of items and the capacity.</p>\n<h2 id=\"where-this-shows-up\" tabindex=\"-1\">Where this shows up <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2019/11/08/the-knapsack-problem/#where-this-shows-up\">#</a></h2>\n<p>The same idea applies to plenty of other situations where something limited has to be shared out, such as choosing which projects to fund with a fixed budget, or deciding which files to fit onto a disk of limited size. Each project or file has a cost (weight) and a benefit (value) and the aim is to get as much benefit as possible out of what you have.</p>\n",
			"date_published": "2019-11-08T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2019/12/05/an-adventure-begins/",
			"url": "https://hackodes.com/blog/2019/12/05/an-adventure-begins/",
			"title": "An Adventure Begins!",
			"content_html": "<p>Building a game can be fun. It's also a good exercise for creativity and there's so many different elements involved, from coming up with a good storyline and building characters to implementing gameplay mechanics and designing the game environments itself. Unity is a well-known game engine that is used by indie developers to major game publishers. Recently, I've been playing around with Unity for a game idea that I've been wanting to build for a while now. My experience so far has been good, Unity has plenty of example games and there's documentation covering most areas on what I need to know.</p>\n<p>In this post, I'll give a brief overview of the game project that I'm currently working on and the initial ideas that I've come up with.</p>\n<h2 id=\"introduction\" tabindex=\"-1\">Introduction <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2019/12/05/an-adventure-begins/#introduction\">#</a></h2>\n<p>The concept of the game is that it's a fast-paced dungeon crawler where the main objective is to adventure as deep into a dungeon as possible and progress through a variety of levels with varying complexity and challenges. The player's point of view is through a controllable hero on screen. A hero can perform different types of movement actions such as walking, aiming, shooting and a special unique ability that can be used to help with progressing through the game environment. The gameplay mechanics are inspired by games such as Enter the Gungeon and Soul Knight. I am yet to decide on the type of art style for this game but I'm considering 2D, retro pixel art graphics that are similar to these games.</p>\n<h2 id=\"premise\" tabindex=\"-1\">Premise <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2019/12/05/an-adventure-begins/#premise\">#</a></h2>\n<p>The game world fiction is set in a starting room called the cellar. Think of the cellar as a safe area where the controllable hero can prepare their gear before venturing into the dungeon via a trapdoor. The heroes need to explore the dungeons, fight against evil forces and rescue characters that have been trapped. Once they enter the trapdoor, they will find themselves inside a dungeon level. Each dungeon level consists of several rooms, and these rooms may have enemies, traps or chests that can be interacted with. The further into the dungeon the player explores, the levels increase in difficulty. The levels will also become larger in size, and there will be stronger enemy encounters with different abilities.</p>\n<h2 id=\"level-design\" tabindex=\"-1\">Level Design <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2019/12/05/an-adventure-begins/#level-design\">#</a></h2>\n<p>Since the game mainly focuses on exploring a dungeon level, there will be multiple rooms per level. Each room will consist of exit points that lead to other rooms. The rooms will be designed to look like a maze, the purpose is to make it confusing but challenging to navigate through. Within a single room, there can be several different types of objects or non-playable characters that the player can interact with. There will collectable objects like coins (to buy things from the in-game shop), health potions (to recover health), weapons etc. Whenever a player enters a room, if there are enemies present in that room then all exits will be blocked off until the player manages to defeat all enemies in the room. Once defeated, the exits will be unlocked. The reason for this environmental feature is to prevent the player from &quot;escaping&quot; or moving into another room without clearing all enemies first.</p>\n<p>Players will have a choice on how to play the game in their own way. They will have the option to take a risk and try to complete every room in the dungeon level to earn plenty of coins to purchase items from the shop or they can play it safe and move on to the next level as soon as they find the exit. These are my initial ideas on the game. While there's still a lot work to be done, I'm interested in working on this new project and look forward to posting updates as the game development progresses.</p>\n",
			"date_published": "2019-12-05T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2020/01/03/learning-goals/",
			"url": "https://hackodes.com/blog/2020/01/03/learning-goals/",
			"title": "Learning Goals",
			"content_html": "<p>It's the start of a new year. I've got a few learning goals I want to achieve this year for my own personal development and growth. Here are the key goals that I want to focus on for this year:</p>\n<h2 id=\"unity\" tabindex=\"-1\">Unity <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/01/03/learning-goals/#unity\">#</a></h2>\n<p>Building a game can be fun. It's also a good exercise for creativity and there's so many different elements involved, from coming up with a good storyline and building characters to implementing gameplay mechanics and designing game environments itself. Unity is a well-known game engine that is used by indie developers to major game publishers. Recently, I've been playing around with Unity for a game idea that I've been wanting to build for a while now. My experience so far has been good, Unity has plenty of example games and there's documentation covering most areas on what I need to know. It uses C# as the programming language of choice which makes it ideal for me as I have prior knowledge of Java which should help with the transition as both languages share some common similarities. I'm hoping to finish a game project soon so expect some updates on this space.</p>\n<h2 id=\"flutter\" tabindex=\"-1\">Flutter <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/01/03/learning-goals/#flutter\">#</a></h2>\n<p>A mobile development framework that has been growing in popularity called Flutter is something that I would like to invest some time to learn. It's a cross-platform framework that allows both iOS and Android apps to be built using a single codebase, reducing the need to have multiple versions of an application for both platforms. It also comes with a number of different pre-made widgets making development fast and easy. Plus, it's backed by Google so it's not going to disappear anytime soon. Although I don't expect to make any mobile apps anytime soon, I am thinking of exploring Flutter's capabilities and gain some skills in a new area.</p>\n",
			"date_published": "2020-01-03T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2020/01/22/project-update/",
			"url": "https://hackodes.com/blog/2020/01/22/project-update/",
			"title": "Project Update",
			"content_html": "<p>The game project's progress has been moving at a steady pace. In this post, I'll cover the art style that I'm planning to use and what I'm currently working on.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/oMttBomwSj-552.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/oMttBomwSj-552.webp\"><img src=\"https://hackodes.com/img/oMttBomwSj-552.png\" alt=\"An image of the cellar's game environment.\" loading=\"lazy\" decoding=\"async\" width=\"552\" height=\"258\"></picture></p>\n<p>For the art style, I'm using a complete set of free assets which can be found <a href=\"https://0x72.itch.io/dungeontileset-ii\">here</a>. I like the look of this art style, it's simple and matches with the theme of my game. Plus, the pixel art size isn't too detailed which makes it easy to modify it and still keep the art style consistent.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/Wp_MqKV_2--427.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/Wp_MqKV_2--427.webp\"><img src=\"https://hackodes.com/img/Wp_MqKV_2--427.png\" alt=\"Animator for the hero called knight.\" loading=\"lazy\" decoding=\"async\" width=\"427\" height=\"282\"></picture></p>\n<p>I've started working with these assets to build the game environments and characters. These assets have different types of animations which easily integrates with Unity's Animator. For this game, there will be various animations to show different types of actions that the player or enemy are doing at the time of gameplay. Player characters have an idle, walking, jumping, and hurt animations. The state changes based on player input and game events. Over the next few days, I'm looking forward to animating the rest of the characters and traps including spikes and arrows. Once that's done and if there's time then I'll start looking into a procedural generation system for creating dungeon levels. Stay tuned.</p>\n",
			"date_published": "2020-01-22T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2020/03/09/secret-magic-links/",
			"url": "https://hackodes.com/blog/2020/03/09/secret-magic-links/",
			"title": "Secret Magic Links",
			"content_html": "<p>Magic links are interesting. The idea is that it's a completely password-less authentication system where you don't need to remember passwords at all. The way it works is that a unique link is sent to the user's email once they enter their email or username to log in. The user then receives an email with a special link that verifies their identity before granting them access to their account without having to enter a password.</p>\n<p>The benefits of this approach is that it improves security by reducing password-related vulnerabilities like weak passwords as there is no need to go through the hassle of creating and managing passwords. Simply log in with just a few clicks, the process is much more user-friendly. It's a good alternative that aims to make the whole authentication process simplified for the user but it does come with some security risks that should be considered. One issue is that if the user's email account is somehow compromised then it defeats the security entirely. It may not be suitable for all use cases especially apps that have a strict security requirement.</p>\n",
			"date_published": "2020-03-09T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2020/03/26/player-retention/",
			"url": "https://hackodes.com/blog/2020/03/26/player-retention/",
			"title": "Player Retention",
			"content_html": "<p>A game needs to have a way to keep players engaged so that they keep playing. There needs to be something for them to keep coming back for more. This can be achieved through different methods depending on the type of game but the main premise remains the same. There needs to be long-term value for the player for them to invest their time.</p>\n<h2 id=\"what-motivates-players\" tabindex=\"-1\">What Motivates Players? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/03/26/player-retention/#what-motivates-players\">#</a></h2>\n<p>Players are motivated by feeling a sense of accomplishment after achieving a goal or objective. This means designing a system that rewards players for their time and effort. This could involve long-term objectives such as unlocking new characters, acquiring new tools, earning new achievements etc. The key is to make progress feel meaningful, make the players motivated to continue to reach the next milestone. The player should be able to perceive their progression within the game so that it makes them feel that they are getting better at the game.</p>\n<h2 id=\"avoiding-repetition\" tabindex=\"-1\">Avoiding Repetition <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/03/26/player-retention/#avoiding-repetition\">#</a></h2>\n<p>For my dungeon exploration game, I initially thought about making premade levels with different environments and encounters. This approach would work however I realised that the game can become stale if it becomes too repetitive. Plus, manually creating the levels and connecting all the rooms together including the starting room and finish room takes time. After a single playthrough, the game can quickly become predictable and lacks replay value. Without new challenges, the players might question the incentive to revisit the game. Due to these reasons, I decided to implement a procedural generation system for the game's levels.</p>\n<h2 id=\"generating-uniqueness\" tabindex=\"-1\">Generating Uniqueness <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/03/26/player-retention/#generating-uniqueness\">#</a></h2>\n<p>The benefits of going with a procedural generation approach is that it creates a unique experience every time the game is played. This makes the game less predictable and more interesting. This could be a new dungeon level layout with potentially more rooms or less rooms. There is more flexibility and customizable options which makes procedural generation a really good option to use. I also found that it helped me to refine the other core gameplay mechanics like combat and character progression instead of spending time building each dungeon level manually.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/J614wV26oc-612.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/J614wV26oc-612.webp\"><img src=\"https://hackodes.com/img/J614wV26oc-612.png\" alt=\"The layout of a procedurally generated dungeon level.\" loading=\"lazy\" decoding=\"async\" width=\"612\" height=\"312\"></picture></p>\n<p>Offloading level designs to algorithms does work but there are also drawbacks like balancing game difficulty and making sure the experience isn't broken. For example, you don't want the starting room and the finish room to be connected together. Testing is a key part of this process so there's some tweaks that need to be made in certain areas. In my case, I had to define rules and constraints for the procedural generation to follow such as having restrictions on minimum and maximum dungeon level sizes. Rules are important to make sure that there is a baseline of quality and prevent nonsensical layouts that can break a game.</p>\n",
			"date_published": "2020-03-26T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/",
			"url": "https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/",
			"title": "Five Worlds of Computational Complexity",
			"content_html": "<p>There is a famous open-ended question in computer science called P vs NP. In simple terms, it asks whether every problem that can be <em>checked</em> quickly can also be <em>solved</em> quickly. Most people believe the answer is no but nobody has been able to prove it. In 1995, a computer scientist called Russell Impagliazzo came up with a nice way of thinking about what the answer would mean for us. He described five possible &quot;worlds&quot; that we could be living in depending on how the question turns out.</p>\n<p>I find this interesting because it connects something very abstract to things we use every day like passwords and encryption.</p>\n<h2 id=\"algorithmica\" tabindex=\"-1\">Algorithmica <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/#algorithmica\">#</a></h2>\n<p>This is the world where P = NP, or close enough to it. Every problem that can be checked quickly can also be solved quickly. This sounds great at first. Scheduling and optimisation problems would all become easy to solve for example.</p>\n<p>However the problem is that this is the world where security falls apart. Modern cryptography relies on the idea that some problems are easy to do in one direction but extremely hard to undo. If every hard problem was suddenly easy, anyone could work out your password from its hash, decrypt private messages and forge digital signatures. Nothing that relies on a secret would be safe. Out of the five worlds, this is the one that stands out to me as the dangerous one.</p>\n<h2 id=\"heuristica\" tabindex=\"-1\">Heuristica <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/#heuristica\">#</a></h2>\n<p>In this world, P is not equal to NP so there are problems that are hard to solve in the worst case. However, those hard cases are rare and difficult to even find. For problems that come up in real life, a good algorithm would solve them quickly almost every time. The theory says &quot;hard&quot; but in practice, things work out.</p>\n<h2 id=\"pessiland\" tabindex=\"-1\">Pessiland <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/#pessiland\">#</a></h2>\n<p>Many people think of this as the worst of the five worlds. In this world, there are problems that are hard to solve even on average so we cannot rely on algorithms to solve them. But this means we also cannot use those hard problems for anything useful. We have no way to turn them into cryptography. So we get the downsides of both. Hard problems exist but they can't be used to keep anything secret.</p>\n<h2 id=\"minicrypt\" tabindex=\"-1\">Minicrypt <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/#minicrypt\">#</a></h2>\n<p>In Minicrypt, one-way functions exist. These are functions that are easy to compute but very hard to reverse. This is enough to build a lot of useful tools such as hash functions, secure random number generators, digital signatures and also private-key (symmetric) encryption where both people share the same secret key.</p>\n<p>What's missing is public-key cryptography. Two people who have never met couldn't agree on a secret over an open channel which is something we do every time we visit a secure website.</p>\n<h2 id=\"cryptomania\" tabindex=\"-1\">Cryptomania <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/#cryptomania\">#</a></h2>\n<p>This is the best case for security. Not only do one-way functions exist, but public-key cryptography is possible too. It's the world most of the internet is built on. Secure online shopping, encrypted messaging and HTTPS all depend on it.</p>\n<h2 id=\"which-world-do-we-live-in\" tabindex=\"-1\">Which world do we live in? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/04/15/five-worlds-of-computational-complexity/#which-world-do-we-live-in\">#</a></h2>\n<p>Nobody knows. Most researchers think we are somewhere towards the Cryptomania end because so much of modern security assumes it. But this is an assumption and not a proven fact. We can't actually prove that P is not equal to NP so we can't completely rule out the dangerous world either. I think this is what makes these five worlds worth knowing about. Whenever we use a password or send something encrypted, we are trusting that some problems really are as hard as we believe they are.</p>\n",
			"date_published": "2020-04-15T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2020/05/06/my-learnings/",
			"url": "https://hackodes.com/blog/2020/05/06/my-learnings/",
			"title": "My Learnings",
			"content_html": "<p>I've learned a lot of things from building a game. From coming up with an idea to building the full product, the overall process can be overwhelming but I think the final result makes it worthwhile.</p>\n<h2 id=\"regular-feedback\" tabindex=\"-1\">Regular Feedback <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/05/06/my-learnings/#regular-feedback\">#</a></h2>\n<p>One thing I've learned is getting regular feedback. It's important to get users to test the game regularly after major updates. The user feedback is important because it gives insight into how a player interacts with the game and identify areas for improvement. As a developer, there might be some things that are fun and interesting for me but it doesn't necessarily mean that it will be the same experience for the players. Moreover, user testing helps to find bugs that might have been missed during development.</p>\n<h2 id=\"refine-things\" tabindex=\"-1\">Refine Things <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/05/06/my-learnings/#refine-things\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/eDFYYG_EGu-592.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/eDFYYG_EGu-592.webp\"><img src=\"https://hackodes.com/img/eDFYYG_EGu-592.png\" alt=\"The player battling with multiple enemies within a room.\" loading=\"lazy\" decoding=\"async\" width=\"592\" height=\"330\"></picture></p>\n<p>Another aspect is refining the game. There's always room for improvement. Even the small details could make the game much better. For my game specifically, I've made use of Unity's particle effects for telling the player whenever they have shot an enemy and whether damage was dealt or not. When a player shoots an enemy, the enemy splatters grey or white particles indicating that they have been hurt. The enemy sprite's colour changes slightly to red which indicates that they have been hit. These small details are important because it is noticeable and makes the overall game experience better.</p>\n<h2 id=\"experiment\" tabindex=\"-1\">Experiment <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/05/06/my-learnings/#experiment\">#</a></h2>\n<p>Spend more time experimenting and trying out new things instead of restricting yourself to a blueprint.</p>\n<h2 id=\"final-thoughts\" tabindex=\"-1\">Final Thoughts <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2020/05/06/my-learnings/#final-thoughts\">#</a></h2>\n<p>Overall, I am satisfied with the project's progress and the final version of the game. I think working with Unity has helped to make the development process easier especially with the built-in tools and features that it has. This game project that I've been working on is completely open-source and if you are interested in the source code, you can find it on <a href=\"https://github.com/hackodes/Mini-Dungeons\">GitHub</a>.</p>\n",
			"date_published": "2020-05-06T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2023/09/20/the-null-problem/",
			"url": "https://hackodes.com/blog/2023/09/20/the-null-problem/",
			"title": "The Null Problem",
			"content_html": "<p>If you write C# for long enough, you will eventually come across a <code>NullReferenceException</code>. It's one of the most common errors there is and it's usually the first one people learn to recognise. I got curious about why it's so common which led me to a surprising story about where null came from.</p>\n<h2 id=\"the-billion-dollar-mistake\" tabindex=\"-1\">The billion-dollar mistake <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2023/09/20/the-null-problem/#the-billion-dollar-mistake\">#</a></h2>\n<p>The null reference was invented in 1965 by Tony Hoare while he was designing a programming language called ALGOL W. His reason for adding it was that it was so easy to implement. Decades later in a talk in 2009, he called it his &quot;billion-dollar mistake&quot;. He said it probably caused countless errors, vulnerabilities and system crashes over the years.</p>\n<p>The idea may sound harmless since Null is a special value that means &quot;there's nothing here&quot;. The problem is that it can be put in the place of any object so any variable could secretly hold nothing at all. Traditional compilers won't be able to tell you until it's too late.</p>\n<pre class=\"language-csharp\" tabindex=\"0\"><code class=\"language-csharp\"><span class=\"token class-name\">Person</span> person <span class=\"token operator\">=</span> <span class=\"token function\">FindPerson</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"nobody\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// returns null if no one is found</span>\nConsole<span class=\"token punctuation\">.</span><span class=\"token function\">WriteLine</span><span class=\"token punctuation\">(</span>person<span class=\"token punctuation\">.</span>Name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>         <span class=\"token comment\">// NullReferenceException</span></code></pre>\n<p>Nothing looks wrong with that code. It compiles and it only fails when it runs and only when <code>FindPerson</code> doesn't find anyone. This means it can work in testing for weeks and then crash in production because of one unexpected value.</p>\n<h2 id=\"defending-against-it\" tabindex=\"-1\">Defending against it <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2023/09/20/the-null-problem/#defending-against-it\">#</a></h2>\n<p>The usual fix is to check for null before using something:</p>\n<pre class=\"language-csharp\" tabindex=\"0\"><code class=\"language-csharp\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>person <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    Console<span class=\"token punctuation\">.</span><span class=\"token function\">WriteLine</span><span class=\"token punctuation\">(</span>person<span class=\"token punctuation\">.</span>Name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>This is defensive programming and it's a good idea to do it. But it can be tedious to check for null everywhere. This also means the checks can pile up fast. Soon they can be everywhere across a codebase. Some places check and some places assume the value is never null so it's hard to tell which is which. There's also the question of what null even means. Does a method return null because it found nothing, because something went wrong or because no one has set a value yet? Null can mean all of those things at once.</p>\n<h2 id=\"what-modern-c-does-about-it\" tabindex=\"-1\">What modern C# does about it <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2023/09/20/the-null-problem/#what-modern-c-does-about-it\">#</a></h2>\n<p>C# has been adding tools to make this less painful. The <code>?.</code> operator stops the call if the value is null, and <code>??</code> lets you give a fallback value.</p>\n<pre class=\"language-csharp\" tabindex=\"0\"><code class=\"language-csharp\">Console<span class=\"token punctuation\">.</span><span class=\"token function\">WriteLine</span><span class=\"token punctuation\">(</span>person<span class=\"token punctuation\">?.</span>Name <span class=\"token operator\">??</span> <span class=\"token string\">\"Unknown\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>The bigger change is <strong>nullable reference types</strong>, which arrived in C# 8. When it's turned on (it's on by default in new projects since .NET 6), a normal <code>Person</code> is no longer allowed to be null and a <code>Person?</code> is a value that might be. The compiler then keeps track of it for you. With the example above, using <code>Person?</code> makes the compiler warn about the line that would have crashed:</p>\n<pre class=\"language-csharp\" tabindex=\"0\"><code class=\"language-csharp\"><span class=\"token class-name\">Person<span class=\"token punctuation\">?</span></span> person <span class=\"token operator\">=</span> <span class=\"token function\">FindPerson</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"nobody\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nConsole<span class=\"token punctuation\">.</span><span class=\"token function\">WriteLine</span><span class=\"token punctuation\">(</span>person<span class=\"token punctuation\">.</span>Name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// warning CS8602: Dereference of a possibly null reference</span></code></pre>\n<p>This moves the problem from runtime to build time which is much better. The one thing to watch out for is that these are warnings and not errors so the code still builds and still crashes if the warning is ignored. You can turn warnings into errors if you want to be strict.</p>\n<h2 id=\"takeaways\" tabindex=\"-1\">Takeaways <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2023/09/20/the-null-problem/#takeaways\">#</a></h2>\n<ul>\n<li>Treat null as a decision and not a default. If something can be missing, make it clear in the type with <code>?</code>.</li>\n<li>Return an empty list instead of null when a method has no results.</li>\n<li>Turn on nullable reference types and take the warnings seriously.</li>\n</ul>\n<p>Null probably isn't going away but it's definitely much easier to deal with now that the compiler can help. Other languages went further. For example, Rust has no null at all and uses an <code>Option</code> type to say a value might be missing so you have to handle both cases before the code will compile.</p>\n",
			"date_published": "2023-09-20T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2024/03/07/embracing-change/",
			"url": "https://hackodes.com/blog/2024/03/07/embracing-change/",
			"title": "Embracing Change",
			"content_html": "<p>Welcome to the new design for this site. I'm now using Eleventy (11ty) as the static site generator and hopefully this one will be around for a while longer than the last! To get started quickly, I picked one of the many templates available for 11ty.</p>\n<p>The one I used was the <a href=\"https://github.com/11ty/eleventy-base-blog\">Eleventy Base Blog v8</a>, a simple starter that had the foundations of a blogging site already set up. Using this template helped me save a lot of time instead of building completely from scratch. But, it lacked some of the features of my original blog so I made a couple of modifications to it. I felt the default styling just didn't quite match what I wanted, so I used Tailwind, a popular CSS framework to give the site a modern yet minimal look and feel.</p>\n<h2 id=\"why-now\" tabindex=\"-1\">Why now? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/03/07/embracing-change/#why-now\">#</a></h2>\n<p>I've been thinking of moving away from Jekyll for a number of reasons now. The most obvious reason is the dependency on Ruby. Having to deal with its dependencies and versioning just to maintain my static site felt cumbersome at times. Although Jekyll has been reliable for some years now, I wanted something that can be managed using a familiar package management tool such as NPM. 11ty is available as an NPM package which makes it the ideal choice for my needs. It's also highly configurable and has excellent documentation covering most areas.</p>\n<h2 id=\"what-next\" tabindex=\"-1\">What next? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/03/07/embracing-change/#what-next\">#</a></h2>\n<p>I still need to migrate all of the old content which should be straightforward enough as it's all written in Markdown. However, there needs to be some manual adjustments done to make sure the layout and formatting is consistent with its frontmatter metadata. Expect to see the old content migrated to this new setup in the coming weeks. In terms of this site redesign, I still have a few remaining features that I'm working on so this is far from the final product and there's still some things yet to come. More on that in the next update.</p>\n",
			"date_published": "2024-03-07T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2024/03/16/an-extension-for-productivity/",
			"url": "https://hackodes.com/blog/2024/03/16/an-extension-for-productivity/",
			"title": "An Extension for Productivity",
			"content_html": "<p>The major web browsers such as Google Chrome and Microsoft Edge surprisingly don't seem to have an option to customize keyboard shortcuts for switching tabs. While the default tab cycling keyboard shortcuts might be useful for some, I personally wanted a different set of controls because it just doesn't work well with my workflow preferences.</p>\n<p>If you're wondering the default shortcut options are set to <code>Ctrl + Tab</code> (change to next tab) and <code>Ctrl + Shift + Tab</code> (change to previous tab) as the keyboard shortcuts.</p>\n<p>Despite this, there are workarounds available with the use of browser extensions. Some time back, I thought this would be a good opportunity for me to look up how extensions work and potentially build one of my own for learning purposes. So, I ended up creating a simple extension that uses custom keyboard shortcuts for switching tabs, pinning tabs and adding tab groups. It doesn't require any special permissions and maintains user privacy by not collecting any personal data or browsing history. The extension can be installed for both Chrome and Edge.</p>\n<p>For those that are interested in exploring the source code, feel free to check out the GitHub repository <a href=\"https://github.com/hackodes/shortcut-tabs-extension\">here</a>. You'll find detailed instructions on the installation and development setup there.</p>\n",
			"date_published": "2024-03-16T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2024/04/24/early-preview-on-project-idx/",
			"url": "https://hackodes.com/blog/2024/04/24/early-preview-on-project-idx/",
			"title": "Early Preview on Project IDX",
			"content_html": "<p>Some time last year, Google announced an experimental browser-based development environment called Project IDX. It uses cloud-based infrastructure using virtual machines that aims to make it easier to build and deploy multi-platform applications fast. The promise of a browser-based development environment seemed interesting enough so I registered in the waitlist for early preview and recently got access to the cloud development environment.</p>\n<p>The good thing about Project IDX is that there is no need to go through any local installations or setting up environment configurations unlike traditional IDEs that need to be installed on your computer before you can start working on a project. From the dashboard in Project IDX, there are a number of built-in templates you can choose from such as Flutter, Node Express, Next.js, Go, Python Flask and more. You can also bring an existing project over from GitHub instead. Just a few clicks in the Project IDX dashboard and you're ready to start working on a project. The idea is to spend less time with setting up a development environment and more time writing code.</p>\n<figure><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/eKUhsAqhMC-1755.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/eKUhsAqhMC-1755.webp\"><img src=\"https://hackodes.com/img/eKUhsAqhMC-1755.png\" alt=\"The home dashboard of Project IDX.\" loading=\"lazy\" decoding=\"async\" width=\"1755\" height=\"872\"></picture><figcaption>The home dashboard of Project IDX.</figcaption></figure>\n<p>When you open a project in Project IDX, you'll be greeted by a web interface that combines the project files, code editor and a preview panel. IDX is built on top of Code OSS, the open-source version of Visual Studio Code, sharing its common functionalities and user interface. This makes it comfortable for developers that are already used to VS Code.</p>\n<p>The built-in preview functionality is where you can preview your application across various platforms such as web and android. This allows you to see how the application will look and function on different devices without needing to set up separate environments. All of this can be done within the browser, which is quite convenient. This is likely to benefit developers with limited hardware resources that may not be able to run specific emulators simultaneously or even individually.</p>\n<figure><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/nvQypNah-q-1916.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/nvQypNah-q-1916.webp\"><img src=\"https://hackodes.com/img/nvQypNah-q-1916.png\" alt=\"The development workspace of Project IDX.\" loading=\"lazy\" decoding=\"async\" width=\"1916\" height=\"938\"></picture><figcaption>The development workspace of Project IDX.</figcaption></figure>\n<p>One useful feature of Project IDX is the AI integration. It comes with Gemini in IDX (formerly IDX AI), an AI programming assistant that can help developers write code faster by providing real-time suggestions and code completions similar to GitHub's Copilot. Gemini has access to the internet so it can search for up-to-date information such as the latest versions of a specific library. You can also start a conversation with Gemini through the chat sidebar. One thing to note is that the prompts sent to IDX AI are used for training data so keep in mind the information that you share, especially if it's confidential or private.</p>\n<p>Project IDX is a promising new cloud-based development environment with potential that is still in the early stages of development. Due to its experimental nature, it's not recommended for building production-based applications at this time. It excels for small projects but its cloud-based virtual machines might not be fully optimized for handling high workloads yet. It's definitely worth keeping an eye on but it remains to be seen whether it becomes widely adopted as the tool for future development needs.</p>\n",
			"date_published": "2024-04-24T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2024/06/11/beyond-passwords/",
			"url": "https://hackodes.com/blog/2024/06/11/beyond-passwords/",
			"title": "Beyond Passwords",
			"content_html": "<p>In a <a href=\"https://hackodes.com/blog/2019/10/08/storing-passwords-securely/\">previous post</a>, I went over how to store passwords safely, and in another I looked at <a href=\"https://hackodes.com/blog/2020/03/09/secret-magic-links/\">magic links</a> as a way to avoid passwords altogether. Both had the same underlying problem. Passwords are a weak way to prove who you are. Yet we still use them almost everywhere.</p>\n<p>The newest attempt to replace them is called passkeys, and they're a lot better than I expected.</p>\n<h2 id=\"whats-wrong-with-passwords\" tabindex=\"-1\">What's wrong with passwords? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/06/11/beyond-passwords/#whats-wrong-with-passwords\">#</a></h2>\n<p>The problem is that a password is a shared secret. You know it and the website knows it, which creates a few weaknesses:</p>\n<ul>\n<li>People reuse them so one breach can unlock many accounts.</li>\n<li>They can be guessed or cracked from a leaked database.</li>\n<li>They can be phished. If you type your password into a fake site, the attacker has it.</li>\n</ul>\n<p>Magic links get rid of the password but they move the problem to your email account. If someone has access to your inbox, they have access to everything.</p>\n<h2 id=\"how-passkeys-work\" tabindex=\"-1\">How passkeys work <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/06/11/beyond-passwords/#how-passkeys-work\">#</a></h2>\n<p>A passkey replaces the shared secret with a pair of cryptographic keys. When you create one for a website, your device generates a <strong>private key</strong> and a <strong>public key</strong>. The website only gets the public key and the private key never leaves your device.</p>\n<p>When you log in, the website sends a random challenge. Your device signs it with the private key and sends it back. The website checks the signature using the public key and lets you in. To approve the signing on your device, you would use a fingerprint, face scan or PIN but this only unlocks the key on your device and is never sent to the website.</p>\n<p>Passkeys are built on the WebAuthn standard, which is part of FIDO2.</p>\n<h2 id=\"why-this-is-better\" tabindex=\"-1\">Why this is better <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/06/11/beyond-passwords/#why-this-is-better\">#</a></h2>\n<p>There are two big improvements. First, there's nothing valuable on the server. If a website is breached then the attacker only gets public keys and those are useless for logging in. Second, passkeys are tied to the website they were created for. So your device won't use them on a fake site. That makes them resistant to phishing which passwords can't be.</p>\n<h2 id=\"so-why-hasnt-everything-switched\" tabindex=\"-1\">So why hasn't everything switched? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/06/11/beyond-passwords/#so-why-hasnt-everything-switched\">#</a></h2>\n<p>Apple, Google, Microsoft and GitHub all support passkeys now but passwords are still everywhere. I think there are a few reasons:</p>\n<ul>\n<li><strong>Recovery:</strong> if you lose your device, how do you get back in? Many services fall back to email or a password reset which brings the weakness back. An attacker can just go for the fallback.</li>\n<li><strong>Syncing:</strong> passkeys are usually stored by the platform such as iCloud Keychain or Google Password Manager. Moving between ecosystems isn't always smooth although password managers are starting to support them.</li>\n<li><strong>The long tail:</strong> a lot of websites and older systems haven't added support and they're not in a hurry to unless they have to.</li>\n<li><strong>Understanding:</strong> people are used to passwords. &quot;Log in with your face&quot; is a big change and many people aren't sure what it means or whether it's safe. Besides, would you want to give away your privacy to a company that you don't trust?</li>\n</ul>\n<h2 id=\"final-thoughts\" tabindex=\"-1\">Final thoughts <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/06/11/beyond-passwords/#final-thoughts\">#</a></h2>\n<p>Passkeys fix real problems and I think they're the best option we have so far. But as long as a password can still be used as a fallback, an account is only as safe as that fallback. Until services are willing to remove passwords completely, I don't think they're going anywhere.</p>\n",
			"date_published": "2024-06-11T00:00:00Z"
		}
		,
		{
			"id": "https://hackodes.com/blog/2024/10/21/serverless-github-notifications/",
			"url": "https://hackodes.com/blog/2024/10/21/serverless-github-notifications/",
			"title": "Serverless GitHub Notifications",
			"content_html": "<p>Automation is everything and we want to save time by eliminating as much manual work as possible. If you've found yourself thinking, &quot;I just need a small bit of code to run in response to an event&quot;, then you are probably thinking about serverless without even realising it. It's a simple way to run code without managing servers - write code, deploy it and let the cloud provider handle the infrastructure. No servers, no maintenance, just code that runs when it needs to.</p>\n<p>Serverless functions have been around for a while now and it's easy to see why they're so popular. They allow developers to focus on writing code without worrying about the underlying infrastructure. You can write functions in various programming languages, deploy them to a cloud provider and it automatically scales based on demand. You only pay for the compute time functions use which makes it cost-effective for many use cases.</p>\n<p>That's what drew me to serverless functions when I started working on a project to send GitHub notifications to a Discord channel about new commits. Every time someone pushes code to a repository, GitHub can send a webhook event. But what can you do with that event? For me, it meant using a serverless function to catch those webhook events by listening to incoming requests. Then I could process the data and send formatted messages to Discord. Why pay for a server to run a script that only needs to run when a webhook event is received? Serverless functions are perfect for this kind of task. There's plenty of cloud providers that offer serverless functions but I ended up using Vercel, a platform that makes it easy to deploy serverless functions for free with a generous free tier (this is not sponsored, I just like the service).</p>\n<h2 id=\"what-about-the-built-in-integration\" tabindex=\"-1\">What about the built-in integration? <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/10/21/serverless-github-notifications/#what-about-the-built-in-integration\">#</a></h2>\n<p>GitHub already has a way to post to Discord. You can add <code>/github</code> to the end of a Discord webhook URL and GitHub will send its events straight to the channel. It works, but the messages are quite basic. You get a short commit message and an author, and that's about it. I wanted to see how big a change was without having to open the commit, so I wanted the number of files changed, the lines added and removed, the time of the commit and any co-authors.</p>\n<figure><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/B3sF7Ziti8-820.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/B3sF7Ziti8-820.webp\"><img src=\"https://hackodes.com/img/B3sF7Ziti8-820.png\" alt=\"A Discord embed showing a single commit with its author, files changed, additions and deletions.\" loading=\"lazy\" decoding=\"async\" width=\"820\" height=\"478\"></picture><figcaption>A notification for a single commit.</figcaption></figure>\n<h2 id=\"how-it-works\" tabindex=\"-1\">How it works <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/10/21/serverless-github-notifications/#how-it-works\">#</a></h2>\n<p>The function is a small TypeScript project. Vercel treats anything inside the <code>api</code> folder as a serverless function, so a request to <code>/api/github</code> runs <code>api/github.ts</code>. GitHub tells you what kind of event it is in the <code>x-github-event</code> header, so the function reads that and decides what to do with it:</p>\n<pre class=\"language-ts\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'x-github-event'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">case</span> <span class=\"token string\">'push'</span><span class=\"token operator\">:</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">handlePushEvent</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">break</span>\n  <span class=\"token keyword\">case</span> <span class=\"token string\">'pull_request'</span><span class=\"token operator\">:</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">handlePullRequestEvent</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">break</span>\n  <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">400</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Unsupported event type'</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The push handler works through each commit in the payload, builds a Discord embed from them and posts it to the webhook URL.</p>\n<h2 id=\"getting-the-details-github-doesnt-send\" tabindex=\"-1\">Getting the details GitHub doesn't send <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/10/21/serverless-github-notifications/#getting-the-details-github-doesnt-send\">#</a></h2>\n<p>A push event tells you which commits were pushed, but it doesn't tell you how many lines changed. To get that, the function makes a second request for every commit, to GitHub's API, and reads the stats from the response. This is why the project needs a GitHub access token. A fine-grained token with read-only access to the repository contents is enough.</p>\n<p>Co-authors are handled in a slightly cheeky way. When you add someone as a co-author, GitHub stores that as a <code>Co-Authored-By:</code> line at the bottom of the commit message. So the function pulls those lines out with a regular expression, shows the names in the notification and removes the lines from the message so they don't show up twice.</p>\n<h2 id=\"working-around-discords-limits\" tabindex=\"-1\">Working around Discord's limits <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/10/21/serverless-github-notifications/#working-around-discords-limits\">#</a></h2>\n<p>Discord is strict about how big a message can be. A single embed can only have 4,096 characters in its description and a message can only have 10 embeds. A push with a lot of commits can easily go over both. So the code splits long descriptions into chunks and splits the embeds into groups of ten. When a push is split up, the title tells you which part you're looking at, e.g. <code>(1/2)</code>.</p>\n<figure><picture><source type=\"image/avif\" srcset=\"https://hackodes.com/img/Y2ctnDzf1Y-811.avif\"><source type=\"image/webp\" srcset=\"https://hackodes.com/img/Y2ctnDzf1Y-811.webp\"><img src=\"https://hackodes.com/img/Y2ctnDzf1Y-811.png\" alt=\"A Discord embed listing several commits from a single push.\" loading=\"lazy\" decoding=\"async\" width=\"811\" height=\"681\"></picture><figcaption>A notification for a push with multiple commits.</figcaption></figure>\n<p>I later added pull request support as well. The embed colour changes depending on whether the pull request has been opened, closed or merged, and the colours can be changed in a <code>config.json</code> file along with the bot's name and avatar.</p>\n<h2 id=\"setting-it-up\" tabindex=\"-1\">Setting it up <a class=\"header-anchor\" href=\"https://hackodes.com/blog/2024/10/21/serverless-github-notifications/#setting-it-up\">#</a></h2>\n<p>Setting it up takes a few minutes. You import the repository into Vercel, add your Discord webhook URL and GitHub token as environment variables and then add a webhook to the repository you want to follow. The full steps are in the <a href=\"https://github.com/hackodes/GitHub-to-Discord-Notifier-Webhook\">README</a> if you want to try it yourself.</p>\n",
			"date_published": "2024-10-21T00:00:00Z"
		}
		
	]
}
