<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>asbedb.dev/ | Musings</title><description/><link>https://www.asbedb.dev/</link><language>en</language><item><title>Untangling Bureaucracy with RAG IM2026</title><link>https://www.asbedb.dev/musings/innovation-month-2026/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/innovation-month-2026/</guid><description>A summary and recap of my entry to the Innovation Month 2026 build a bureaucrat bot event

</description><pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;aside aria-label=&quot;Important&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Important&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;The views and material below are purely my own and do not represent an authority or body of any sort - all output and information should be clarified and not taken as advice or an official stance&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;It’s currently &lt;a href=&quot;https://www.apsprofessions.gov.au/resources/innovation-hub/innovation-month-2025-risk-resolve-results&quot;&gt;innovation month&lt;/a&gt; across the Australian Public Sector - as part of the festivities a challenge was set to “build a bureaucrat bot”.&lt;/p&gt;
&lt;p&gt;I thought it apt to give the challenge a “fair shake of the sauce bottle” . It was a good excuse for me to dive into something new and untested, maybe learn a thing or two along the way. I wanted to summarise the journey - not necessarily in my usual deep dive technical style, but approachable enough to get an idea, with some relevant links to code.&lt;/p&gt;
&lt;p&gt;If you want to poke at it yourself, the &lt;a href=&quot;https://github.com/polycy-bot&quot;&gt;repo’s here&lt;/a&gt; with a &lt;a href=&quot;https://polycy-bot.netlify.app/&quot;&gt;live demo here&lt;/a&gt; and if you spot something I’ve done badly (very possible), I’d love to hear about it.&lt;/p&gt;
&lt;p&gt;And a summary of what the bot does below (excuse my artistry.😊)
&lt;img alt=&quot;polycy-bot-card&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;1000&quot; src=&quot;https://www.asbedb.dev/_astro/polycybot-card.DdFgiPdR_295NBd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;challenge&quot;&gt;Challenge&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Innovation month similar to a hackathon is a good way to platform and provide opportunity to showcase - &lt;em&gt;dare I say it&lt;/em&gt; - innovation in delivering smarter outcomes in what I’m going to coin “good public service”. With the theme “Ready or not” the primary focus this year is around harnessing the capabilities of AI (in all forms) without losing sight of the goals aforementioned. The “Build a Bureaucrat Bot” event took this theme and provided a tangible category for all to participate.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Can you build a helpful bot for a real public service problem? Use generative AI to create an interactive bot that helps public servants, senior leaders or citizens. No coding experience needed - no-code, low-code and prompt-based builds are welcome.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In addition the bot could sit in primarily one of the below categories.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Chief AI Officers Aide&lt;/strong&gt;: Tools that support strategic decision-making, adoption planning, governance, maturity assessment, prioritisation, risk framing or executive briefings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Workday Wingmate:&lt;/strong&gt; Drafting, planning, summarising, navigating internal guidance, preparing meetings, improving correspondence, supporting teams, or making routine work less painful&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Cobber Bot:&lt;/strong&gt; Citizen-facing or public-facing ideas that make services, obligations, forms, decisions, entitlements or processes easier to understand and engage with.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Complexity Tamer:&lt;/strong&gt; Tools for policy, research, modelling, simulation, evidence synthesis, system mapping, scenario testing or making trade-offs more visible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The AI Trailblazer:&lt;/strong&gt; Move from curiosity to responsible practice: identifying opportunities, designing experiments, working through risks, building confidence, planning implementation, or scaling what works&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;approach&quot;&gt;Approach&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The Complexity Tamer&lt;/strong&gt; category instantly lit up for me. Untangling bureaucracy can be an art form, particularly when trying to administer and uphold laws.The immediate scenario which came to mind was navigating &lt;a href=&quot;https://www.ato.gov.au/about-ato/ato-advice-and-guidance/ato-guidance-products/law-administration-practice-statements&quot;&gt;Law Administration Practice Statements&lt;/a&gt; (PS LAs).&lt;/p&gt;
&lt;p&gt;A PS LA is an article that provides direction to Public Service workers on approaches to take when performing duties which involve the Superannuation and Tax laws being administered. Whilst the PS LAs themselves are not law or public ruling, they are used to help undertake technical direction in various matters. This “abstraction” layer above the law, certainly is in the category of taming complexity - but there were a few “bottle necks” in analysing a practice statement that I wanted to try and test.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The abstraction of law means that the language or legal ease is still going to be present in the directions provided - how can this become more accessible to someone less technical.&lt;/li&gt;
&lt;li&gt;Drawing parallels between articles is currently difficult unless directly referenced in the statement itself - In some scenarios there may be multiple PS LAs covering various technical topics - “GST Rulings” can appear across three PS LAs with two of them withdrawn.&lt;/li&gt;
&lt;li&gt;Searching and using the PS LAs as reference is currently relegated to a public facing website with the content being in HTML/Static Web - it works, but outside of reading the PS LAs themselves you would need additional uplift to use the data in other environments.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;the-idea&quot;&gt;The Idea&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;My idea was to implement a retrieval augmented generation tool (RAG) to quickly sift through PS LAs based on a user’s prompt and provide a highly tailored response to the user. I’ll try and provide a simple step by step example of a RAG assisted result.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User prompts tool in simple language to try and gather information on making a technical decision.&lt;/li&gt;
&lt;li&gt;Prior to our call going to our preferred generative model we ensure that our prompt is searched against a database of information housing all of our PS LA knowledge.&lt;/li&gt;
&lt;li&gt;If a PS LA is found its crafted into a &lt;strong&gt;context payload&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The personality of our model is heavily guarded - it can &lt;strong&gt;only&lt;/strong&gt; talk about PS LAs, it is given strict instructions to &lt;strong&gt;use the context provided&lt;/strong&gt; and any request outside of PS LAs is rebuffed.&lt;/li&gt;
&lt;li&gt;We stuff the &lt;strong&gt;context&lt;/strong&gt; between our guard rails (&lt;strong&gt;prompt stuffing&lt;/strong&gt;) and tell the model this is its &lt;strong&gt;primary subject&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;A simple representation of RAG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1053&quot; height=&quot;557&quot; src=&quot;https://www.asbedb.dev/_astro/simple_rag_diagram.By1ovUQX_ZUiJMM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;And there you have it - a retrieved piece of information has augmented our prompt and resulted in a pointed generation!&lt;/p&gt;
&lt;p&gt;Initially, I was imagining a Saturday and Sunday at best to build, test and deploy - leaving me plenty of time to write this piece. How wrong I was (apologies for any grammar or spelling mistakes in advance 🙃).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-plan&quot;&gt;The Plan&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The project is broken into two repositories - the ingestion engine and the presentation layer or “front end”.&lt;/p&gt;
&lt;p&gt;For this project to show promise it was important to fine tune both - not only were they reliant on each other but also each in its own right drastically changed the user experience outcomes.&lt;/p&gt;
&lt;p&gt;Ensuring good data stewardship is going to dictate the success of outcomes - and to some degree this holds true for any technology program in the not too distant future. I will go through and break out both the ingestion pipeline and front end into interesting challenges and learnings, however, if you want to review the full code its open source and &lt;a href=&quot;https://github.com/polycy-bot&quot;&gt;available on GitHub here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Below is an outline of the initial ingestion flowing into a full stack interactive web interface.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Website with PS LA content (Public Facing Website)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;┌───────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ Ingestion Engine Pipeline │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  • Converts HTML to MD    │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  • Parses metadata        │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  • Sanitizes URLs/Dates   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└─────────────┬─────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[ knowledge.json ] (DB Artifact)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;┌───────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│     SvelteKit Backend     │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  (api/library/server.ts)  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│                           │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   ┌───────────────────┐   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   │  • Context Search │   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   │  • Filter Stops   │   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   │  • Score Relevance│   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   │  • Stuff Prompt   │   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   └─────────┬─────────┘   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└─────────────┼─────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[API Payload] (Stuffed Prompt to Model)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;┌───────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│    SvelteKit Frontend     │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│                           │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  ┌─────────────────────┐  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  │  uiState.svelte.ts  │  │ (Global UI state)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  └──────────┬──────────┘  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│             │             │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  ┌──────────▼──────────┐  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  │ • Display Chats     │  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  │ • Search DB/Context │  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  │ • Prompt            │  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  │ • Detail &amp;#x26; timeline │  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  └─────────────────────┘  │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└───────────────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;ingestion&quot;&gt;Ingestion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Ingestion has been broken down into a few parts - I want to thank whoever built and maintaned the website housing PS LAs, there are some key patterns I relied on throughout the ingestion phase and without them, I don’t think I would have finished this project in time.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;crawling&quot;&gt;Crawling&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Each PS LA has a unique URL, lets take one as an example:&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;https://www.ato.gov.au/law/view/document?docid=PSR/PS19981/NAT/ATO/00001&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Removing the static parts of the URL we can review only this section:&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;PS{year}{sequence}/NAT/ATO/00001&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rather then copy pasting each URL my first automation was to build a quick request resolver to go through a range of years to scan valid links within that year. If you are interested in the code you can &lt;a href=&quot;https://github.com/polycy-bot/ingestion-engine/blob/main/utilities/url_builder.py&quot;&gt;review it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For each successfully resolved URL it was appended to a text document called &lt;code dir=&quot;auto&quot;&gt;verified_urls.txt&lt;/code&gt; in the &lt;code dir=&quot;auto&quot;&gt;/data&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;A few things I learnt from this feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not all websites expect a friendly header to let the web administrator know what your crawler is doing (I’m assuming some Cloudflare technology trend) just rejected my requests when I had something along the lines of &lt;code dir=&quot;auto&quot;&gt;Crawler-Innovation-Month&lt;/code&gt; in my header. &lt;em&gt;Sorry admin.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Graceful delays and timeouts help reduce gaps in the data hammering a request isn’t the most efficient way to gather and validate evidence.&lt;/li&gt;
&lt;li&gt;Reliable patterns make for good automation - and allow not only for an easier approach to administration but also for external parties to integrate and extend your product.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;scraping&quot;&gt;Scraping&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;I am of the firm belief that one of the top sought after skills in the next 5-10 years will be centred around the ability to write good documentation, in addition to being able to write it in markdown.&lt;/p&gt;
&lt;p&gt;Generative models are good at this, yet when it comes to articles that are extremely nuanced or not in the public domain - it’s on us to build that layer to help get to outcomes faster.&lt;/p&gt;
&lt;p&gt;Scraping a website isn’t ground breaking - however - translating a website from HTML markup to markdown is where it gets interesting. Thankfully the web administrators once again were gracious enough to clearly mark the PS LA webpage with easy to understand id’s tied to the various markup elements. It was on me to translate those elements into a markdown format  - &lt;a href=&quot;https://github.com/polycy-bot/ingestion-engine/blob/main/utilities/psla_parser.py&quot;&gt;the python utility responsible for this can be reviewed here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Doing this during ingestion made sense, we could have reserved it for the front end however that also complicates the prompt stuffing - LLM’s are a lot better at understanding markdown as context then they are HTML.&lt;/p&gt;
&lt;p&gt;During this parsing stage I created a key value data structure to return which would be appended to a &lt;code dir=&quot;auto&quot;&gt;.json&lt;/code&gt; file. The return object looks like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;return {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;doc_id&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;doc_id&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;title&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;category&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;category&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;raw_text_content&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;markdown_content&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;revision_history&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;revision_history&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Learnings from this feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stripping elements and cleaning the ingestion data was critical - we didn’t need images, contact details or scripts. Purely the content relevant to the task&lt;/li&gt;
&lt;li&gt;By preserving the HTML in its markdown equivalent presenting this back in a front end was much easier to manage. i.e. a title denoted with &lt;code dir=&quot;auto&quot;&gt;#&lt;/code&gt; was easy to render as a &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;h1&gt;&lt;/code&gt; using a markdown parser.&lt;/li&gt;
&lt;li&gt;Breaking up the parsed data into metadata attributes allowed us to create faster searches across documents (and expand out capability to include other sources in the future).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;persistencestoring&quot;&gt;Persistence/Storing&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Finally should there be no data ingested, the application will create and store the results in two files, one which houses all the valid URLs, and one which will be the main source of truth artifact to our full stack web app (&lt;code dir=&quot;auto&quot;&gt;knowledge.json&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;I built a persistence service to check if the files existed and only run the service if they didn’t. This was primarily to rapidly test but also not recrawl URLs if I had a fully valid list and only wanted to update the database with new tags/content.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-application&quot;&gt;The Application&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With the ingestion engine reliably producing &lt;code dir=&quot;auto&quot;&gt;knowledge.json&lt;/code&gt;, the other half of the problem was giving that data somewhere to live that didn’t feel like reading a legal document with extra steps. I decided to go back to my tried and tested friend &lt;a href=&quot;https://svelte.dev/docs/kit/introduction&quot;&gt;SvelteKit&lt;/a&gt; - if you are interested in my feelings about it you can &lt;a href=&quot;https://asbedb.dev/musings/scapedle-game/#sveltekit&quot;&gt;read more here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Similar to my reasonings for that project I wanted to have a quick and easy way to deliver both front and back end without splitting infrastructure and inflating cost.&lt;/p&gt;
&lt;p&gt;The front end has two main responsibilities, I won’t go into the technical detail of the UI implementation as this post is more focussed on the “RAG” side of things however it provides the user with.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A way to communicate to the chatbot through a common chat interface&lt;/li&gt;
&lt;li&gt;A way to browse all of the context available, and, prompt based on a PS LA as a starting point to a conversation.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h3 id=&quot;models&quot;&gt;Models&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;For the generative engine I did test both a local model using llama 3.1 4B and Google Gemini’s cloud model. I ended up choosing Gemini as it’s free and one less hosting problem to consider - that said the system is fully capable of slotting in and out models. Currently the hosted version is using &lt;code dir=&quot;auto&quot;&gt;gemini-3.1-flash-lite&lt;/code&gt; which I found perfect for a tech demo.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;context-search&quot;&gt;Context Search&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Once &lt;code dir=&quot;auto&quot;&gt;knowledge.json&lt;/code&gt; existed, the job of the backend was fairly simple to &lt;em&gt;state&lt;/em&gt; and much less simple to get right: take whatever a user typed, work out which PS LA (if any) it’s actually about, and only then let the model open its mouth. I’ll admit up front - there’s no embedding model or vector database sitting behind this thing. &lt;code dir=&quot;auto&quot;&gt;getContextByKeyword&lt;/code&gt; is doing keyword scoring, plain and simple.&lt;/p&gt;
&lt;p&gt;Every document in the knowledge base gets a score based on a handful of signals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Does the raw query appear verbatim in the text (+10).&lt;/li&gt;
&lt;li&gt;Does it appear in the title or doc ID (+20).&lt;/li&gt;
&lt;li&gt;Word-by-word matches against title, doc ID and body content at smaller weights.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There’s a small bit of nuance in there for our &lt;code dir=&quot;auto&quot;&gt;PS LA 1998/1&lt;/code&gt; style references specifically - if a query word contains a slash and matches the doc ID (think someone pasting in &lt;code dir=&quot;auto&quot;&gt;PS 1998/1&lt;/code&gt; or similar), it gets bumped harder than a generic word match, because that’s about as close to a direct citation as a user is going to give us.&lt;/p&gt;
&lt;p&gt;Anything that doesn’t clear a minimum match ratio (at least a quarter of the query’s meaningful words showing up somewhere relevant) or a minimum score gets discarded, and I only ever pass the top three scoring matches through to the model.&lt;/p&gt;
&lt;p&gt;Stop words get filtered out before any of this even starts, otherwise “what does the ATO say about GST” would spend most of its scoring budget matching “the” and “about” against every document in the library. We don’t want to score these words as they are just part of common lexicon and will appear everywhere.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/polycy-bot/polycy-fe/tree/main/src/routes/api/chat&quot;&gt;/api/chat&lt;/a&gt; is home to this functionality, specifically &lt;code dir=&quot;auto&quot;&gt;context.ts&lt;/code&gt; doing the scoring and searching.&lt;/p&gt;
&lt;p&gt;Learnings from this feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keyword scoring is unglamorous but it’s transparent - I can look at any result and explain in one sentence why it scored the way it did.&lt;/li&gt;
&lt;li&gt;The slash-matching quirk exists purely because of how PS LAs are referenced in the wild (&lt;code dir=&quot;auto&quot;&gt;1998/1&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;2011/27&lt;/code&gt;, etc.) - a generic RAG implementation wouldn’t have thought to weight that, but knowing your data’s shape earns you these small wins.&lt;/li&gt;
&lt;li&gt;Capping at three matches was a deliberate guardrail on context size as much as anything else - Gemini doesn’t need six PS LAs shoved into a system prompt to answer a question about GST rulings, and neither does the person asking it.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;prompt-stuffing&quot;&gt;Prompt Stuffing&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The personality of the agent is fine tuned in &lt;a href=&quot;https://github.com/polycy-bot/polycy-fe/blob/main/src/routes/api/chat/policyAssistant.ts&quot;&gt;this file&lt;/a&gt;. Here you can see its personality and instructions. I wrote a custom function which takes whatever came back from the context search and does one of two things.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If nothing matched, the model gets &lt;code dir=&quot;auto&quot;&gt;AGENT_INSTRUCTIONS&lt;/code&gt; plus a &lt;code dir=&quot;auto&quot;&gt;POLICY_NOT_FOUND_GAURDRAIL&lt;/code&gt; block which tells it, in no uncertain terms, that it doesn’t get to freelance an answer about tax law from its own training data.&lt;/li&gt;
&lt;li&gt;If something did match, it gets &lt;code dir=&quot;auto&quot;&gt;AGENT_INSTRUCTIONS&lt;/code&gt; plus &lt;code dir=&quot;auto&quot;&gt;POLICY_FOUND_INSTRUCTION&lt;/code&gt;, followed by every matched document wrapped in its own clearly delimited block - source link, doc reference number, title, and the full markdown content, separated by a run of equals signs so the model has an unambiguous way of telling one PS LA from another when more than one comes back.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the “prompt stuffing” I mentioned earlier made real - the model’s personality and its subject matter are being assembled fresh on every single request, out of instructions I control and content that’s been vetted by the scoring step above.&lt;/p&gt;
&lt;p&gt;Learnings from this feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Separating “found” and “not found” instructions turned out to matter more than I expected. Early on I was using one instruction set and telling the model to “use context if provided” - it would occasionally still have a go at answering from general knowledge when nothing matched. Splitting the guardrail language into its own explicit branch closed that gap.&lt;/li&gt;
&lt;li&gt;Labelling each context block with a document reference number (&lt;code dir=&quot;auto&quot;&gt;#1&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;#2&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;#3&lt;/code&gt;) rather than just dumping raw text back to back gave the model something concrete to cite back to the user, which matters a lot when someone’s asking about a topic that spans a withdrawn PS LA and its replacement.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;model-calls&quot;&gt;Model Calls&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;+server.ts&lt;/code&gt; is the thin layer that actually talks to Gemini - and deliberately thin. It pulls the API key, validates the incoming message array, pulls the last user message out as the query, and hands it to &lt;code dir=&quot;auto&quot;&gt;getContextByKeyword&lt;/code&gt;. From there it’s mostly plumbing: build the system instruction, reshape the conversation history into the &lt;code dir=&quot;auto&quot;&gt;user&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;model&lt;/code&gt; roles Gemini expects (SvelteKit and the frontend are happy calling it “assistant”, Gemini is not), and open a streaming connection with &lt;code dir=&quot;auto&quot;&gt;generateContentStream&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The response comes back chunk by chunk through a &lt;code dir=&quot;auto&quot;&gt;ReadableStream&lt;/code&gt;, which gets piped straight to the client as plain text rather than waiting for the full generation to finish - useful for anything constrained to an edge runtime, and it’s the difference between a user staring at a blank screen for a few seconds versus watching an answer arrive. One small addition I was glad I made early: an &lt;code dir=&quot;auto&quot;&gt;x-context-retrieved&lt;/code&gt; header on the response, set to whether any PS LA actually matched. It’s a cheap way for the frontend to know, before it’s even parsed a word of the streamed answer, whether it’s looking at a grounded response or a guardrail refusal.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;library-endpoint&quot;&gt;Library Endpoint&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Sitting alongside all of this is &lt;code dir=&quot;auto&quot;&gt;/api/library&lt;/code&gt;, a much simpler read-only endpoint that just flattens the entire knowledge base into an array - id, title, category, content, source URL and revision history per document. This is what lets the frontend browse the full PS LA library independently of any chat interaction, which turned out to matter once I started thinking about the “detail &amp;#x26; timeline” view - being able to look at a PS LAs revision history directly, without needing to have asked the chatbot a question first.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I thought a “Saturday and Sunday” session would be all it took, here we are finishing this piece 2 days before the deadline, which is probably the most honest lesson from Innovation Month: taming complexity is itself complex.&lt;/p&gt;
&lt;p&gt;If you want to poke at it yourself, the &lt;a href=&quot;https://github.com/polycy-bot&quot;&gt;repo’s here&lt;/a&gt; with a &lt;a href=&quot;https://polycy-bot.netlify.app/&quot;&gt;live demo here&lt;/a&gt; and if you spot something I’ve done badly (very possible, see grammar disclaimer above), I’d love to hear about it.&lt;/p&gt;</content:encoded><category>AI</category><category>WebDev</category></item><item><title>CSS June Roundup</title><link>https://www.asbedb.dev/musings/melb-css-june/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/melb-css-june/</guid><description>A round up of all things CSS I found interesting in the month of June!

</description><pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;It’s best to view this post using the Chrome browser as a lot of the features discussed are experimental and not baseline to browsers like Firefox.&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;I’ve been lucky enough to &lt;a href=&quot;https://youtu.be/EB62o1lCip0?si=sWL1th_VOSgts2qI&quot;&gt;present at&lt;/a&gt; and help organise the local &lt;a href=&quot;https://melbcss.com/&quot;&gt;CSS meetup&lt;/a&gt;. This article is companion to a talk I gave showcasing some community updates and fun features either experimental or widely available in CSS!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;tldr&quot;&gt;TLDR&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If you just want to jump around to links see the high level recap below (best viewed with chrome to see all non baseline features). Please note the title link scrolls to the section and the &lt;em&gt;external link&lt;/em&gt; will take you to the relevant page!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#melbcss-community-themes&quot;&gt;MelbCSS Community Themes&lt;/a&gt; - &lt;a href=&quot;https://github.com/melbcssmeetup/website/tree/main?tab=contributing-ov-file&quot;&gt;External Link&lt;/a&gt; - The MelbCSS website has had a fresh paint job and is now ready to accept community theme submissions! Head on over to the GitHub to find out more.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#css-1d-chess&quot;&gt;CSS 1D Chess&lt;/a&gt; - &lt;a href=&quot;https://david.sojevic.com/projects/css-only-1d-chess/&quot;&gt;External Link&lt;/a&gt; - &lt;a href=&quot;https://david.sojevic.com/&quot;&gt;David Sojevic&lt;/a&gt; One of our awesome community members put together a puzzle game demo and blog post inspired by a Hacker News article in which the player solves a Chess puzzle on one dimension. The project showcases what’s possible with only CSS and HTML - It even has a 3D toggle!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#corner-shape&quot;&gt;corner-shape&lt;/a&gt; - &lt;em&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/corner-shape&quot;&gt;External Link&lt;/a&gt;&lt;/em&gt; - A new property that specifies a box’s corners within the area specified by its border-radius property!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#random&quot;&gt;random()&lt;/a&gt; - &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/random&quot;&gt;External Link&lt;/a&gt; - Brace yourself random() is coming. At the moment you can only test this feature in Safari.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#if&quot;&gt;if()&lt;/a&gt; - &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/if&quot;&gt;External Link&lt;/a&gt; - The if() function is gaining traction, perhaps if() it’s ready soon conditional checkboxes are a thing of the past?&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#lazy-loading&quot;&gt;Lazy Loading&lt;/a&gt; - &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Lazy_loading&quot;&gt;External Link&lt;/a&gt; - A HTML Attribute that helps us manage the load time of a site, but can we also make it &lt;em&gt;look good!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#sprites&quot;&gt;Sprites&lt;/a&gt; - &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Images/Implementing_image_sprites&quot;&gt;External Link&lt;/a&gt; - Using pixel art magic to have some fun!&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;melbcss-community-themes&quot;&gt;MelbCSS Community Themes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;During the last few &lt;a href=&quot;https://melbcss.com&quot;&gt;MelbCSS&lt;/a&gt; meetups we talked about putting together a neat little project to bring everyone together - I’m happy to announce it’s now ready!&lt;/p&gt;
&lt;p&gt;The aim is to provide a canvas being the MelbCSS Website as a playground for CSS creativity. We have tried to make it accessible to contribute and CSS focused, using GitHub as the platform to help manage submissions and deployment.&lt;/p&gt;
&lt;p&gt;Our &lt;a href=&quot;https://melbcss.com/?theme=chaos&quot;&gt;first official submission&lt;/a&gt; from &lt;a href=&quot;https://duck.dev/&quot;&gt;Ronvoluted&lt;/a&gt; did not disappoint! Titled &lt;code dir=&quot;auto&quot;&gt;chaos&lt;/code&gt; the swirls of buttons and emojis certainly live up to Ron’s vision with some interesting SVG filter effects being used similar to ripples on a pond! - and of course &lt;em&gt;it’s all CSS&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;MelbCSS Chaos Theme&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1306&quot; height=&quot;1030&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-chaos.DEFrUcAv_Z2szRD6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It’s been very exciting to see the pull requests coming in, as I was writing this piece up &lt;a href=&quot;https://melbcss.com/?theme=minecraft&quot;&gt;a new theme arrived&lt;/a&gt;! This one was from &lt;a href=&quot;https://github.com/LakshmiChaitanya2008&quot;&gt;LakshmiChaitanya2008&lt;/a&gt; titled &lt;code dir=&quot;auto&quot;&gt;Minecraft&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;MelbCSS Minecraft Theme&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;870&quot; height=&quot;722&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-minecraft.BCXcko_i_Z1vXu3u.webp&quot; srcset=&quot;&quot;&gt;
As I had to test some features, I did put together a &lt;code dir=&quot;auto&quot;&gt;Retro&lt;/code&gt; theme which was a homage to &lt;a href=&quot;https://melbcss.com/?theme=retro&quot;&gt;old terminals and operating systems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;MelbCSS Retro Theme&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;831&quot; height=&quot;629&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-retro.FV56Lcgq_28HRbY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/melbcssmeetup/website/tree/main?tab=contributing-ov-file&quot;&gt;contributing guide&lt;/a&gt; to get started! We are more than happy to help answer any questions in the &lt;a href=&quot;https://discord.gg/QQS82ZQfDt&quot;&gt;discord&lt;/a&gt; as well.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;css-1d-chess&quot;&gt;CSS 1D Chess&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://david.sojevic.com/projects/css-only-1d-chess/&quot;&gt;Play Here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Perched on a single-line board this mini game challenges the player to “win at chess” with the constraint. It’s ironic because the developer who made this &lt;a href=&quot;https://david.sojevic.com/&quot;&gt;David Sojevic&lt;/a&gt; has won at CSS with the constraint of not using JavaScript! There are some neat in action techniques here including the classic &lt;a href=&quot;https://css-tricks.com/the-checkbox-hack/&quot;&gt;checkbox hack&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;css-jun-chess-2d&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1128&quot; height=&quot;517&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-1d-chess-2d.DwshU1wh_Zy6ict.webp&quot; srcset=&quot;&quot;&gt;
Without spoiling too much - there’s also a 3D Easter egg purely written in CSS. I highly recommend &lt;a href=&quot;https://david.sojevic.com/posts/making-css-only-3d-2d-1d-chess/&quot;&gt;reading the full blog post on how its done&lt;/a&gt; - lots of great little techniques.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;CSS June 3D Chess&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1293&quot; height=&quot;432&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-1d-chess-3d.DgsxDVyN_Z1F5Xf1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;corner-shape&quot;&gt;corner-shape&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If you have needed to style an element beyond a simple radius of a border you’ve probably reached up to grab the humble SVG. Whilst the SVG still sits in its rightful spot of extremely flexible but a pain to master, some new CSS flags might make our lives slightly easier in the not too distant future. Meet the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/corner-shape&quot;&gt;corner-shape&lt;/a&gt;!&lt;/p&gt;
&lt;div&gt;
  &lt;p data-theme-id=&quot;dark&quot; data-height=&quot;380&quot; data-pen-title=&quot;corner-shape in action&quot; data-default-tab=&quot;css,result&quot; data-slug-hash=&quot;xbRgdMw&quot; data-user=&quot;dottys&quot;&gt;
    &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/dottys/pen/xbRgdMw&quot;&gt;
    corner-shape in action&lt;/a&gt; by dots (&lt;a href=&quot;https://codepen.io/dottys&quot;&gt;@dottys&lt;/a&gt;)
    on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
  &lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;Unlike border-radius in which borders just curve the corner-shape property provides us with actual shapes to put into each corner! By manipulating the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/superellipse&quot;&gt;superellipse()&lt;/a&gt; value we are able to create some awesome corners in inverse or standard composition. The spec also has some keywords baked in allowing for you to quickly call values without guessing. As an example &lt;code dir=&quot;auto&quot;&gt;corner-shape: squircle;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Below is a summary of the keywords available.&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Keyword&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;square&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;superellipse(infinity)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;squircle&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;superellipse(2)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;round&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;superellipse(1)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;bevel&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;superellipse(0)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;scoop&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;superellipse(-1)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;notch&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;superellipse(-infinity)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;random&quot;&gt;random()&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Computer scientists have been harping on about “true random numbers” for a &lt;a href=&quot;https://www.youtube.com/watch?v=aEJB8IAMMpA&quot;&gt;while now&lt;/a&gt;. Whilst this isn’t necessarily a discussion about that I did want to add an interesting note for those interested. True randomness is observed through physical phenomena the famous &lt;a href=&quot;https://www.cloudflare.com/learning/ssl/lava-lamp-encryption/&quot;&gt;“lava lamp wall” from Cloudflare&lt;/a&gt; is a great example of this.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;CSS June Lava Lamp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1152&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-lavalamp.HPVOiZiL_ZS1waH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;With that out of the way, It looks like CSS may be getting its very own &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/random&quot;&gt;random()&lt;/a&gt; function! I don’t believe many would dare to use it for cryptographic/security purposes but what it can do is add some fun ways to make a front end feel alive!&lt;/p&gt;
&lt;p&gt;Whether it’s cycling through colours in a range or animating edges to randomly oscillate, I think it will open a world of creativity without needing to rely on additional JavaScript!&lt;/p&gt;
&lt;p&gt;If you would like to test this feature it is currently only supported on the Safari browser.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;if&quot;&gt;if()&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The checkbox hack was a great way to bake some “logic” into the front end but what &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/if&quot;&gt;if()&lt;/a&gt; I told you (see what I did there), a new option is coming. The utility of an if statement in CSS will bring with it a host of functionality and standardisation previously obscured or reliant on frameworks/JavaScript.&lt;/p&gt;
&lt;div&gt;
	&lt;p data-theme-id=&quot;dark&quot; data-height=&quot;380&quot; data-pen-title=&quot;if() demo&quot; data-default-tab=&quot;css,result&quot; data-slug-hash=&quot;ogYYQJy&quot; data-user=&quot;dottys&quot;&gt;
	&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/dottys/pen/ogYYQJy&quot;&gt;
	if() demo&lt;/a&gt; by dots (&lt;a href=&quot;https://codepen.io/dottys&quot;&gt;@dottys&lt;/a&gt;)
	on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
	&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;One thing I’m really excited about is the ability to use single variables to conditionally update styling. This is a big win as it allows for more performant and easier to manage code that dynamically manages themes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;lazy-loading&quot;&gt;Lazy Loading&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With the loading attribute now baked into the HTML Spec there’s a fair amount of options available to make those skeletons pop! By combining the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@starting-style&quot;&gt;starting-style&lt;/a&gt; rule with a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Lazy_loading&quot;&gt;loading=“lazy”&lt;/a&gt; - there are some really neat ways to naturally transition in loading elements. Paired with an &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API&quot;&gt;intersection observer&lt;/a&gt; things like infinite scroll and load time become less reliant on JavaScript!&lt;/p&gt;
&lt;p&gt;The demo below gives a great example of what can be achieved (note - I am using JavaScript to randomly fetch 400 images to show the effect in real time!)&lt;/p&gt;
&lt;div&gt;
	&lt;p data-theme-id=&quot;dark&quot; data-height=&quot;380&quot; data-pen-title=&quot;Lazy Loading Demo&quot; data-default-tab=&quot;css,result&quot; data-slug-hash=&quot;dPOOQBq&quot; data-user=&quot;dottys&quot;&gt;
	&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/dottys/pen/dPOOQBq&quot;&gt;
	Lazy Loading Demo&lt;/a&gt; by dots (&lt;a href=&quot;https://codepen.io/dottys&quot;&gt;@dottys&lt;/a&gt;)
	on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
	&lt;/p&gt;
&lt;/div&gt;


&lt;div&gt;&lt;h1 id=&quot;sprites&quot;&gt;Sprites&lt;/h1&gt;&lt;/div&gt;
&lt;p&gt;Earlier in the year I came across a beautifully written &lt;a href=&quot;https://www.joshwcomeau.com/animation/sprites/&quot;&gt;post&lt;/a&gt; from Josh &lt;em&gt;w&lt;/em&gt; Comeau detailing the use of sprites and sprite sheets, it’s a great example of how web developers have always had neat little &lt;em&gt;hacks&lt;/em&gt; and &lt;em&gt;tricks&lt;/em&gt; web developers use to emulate functions we are familiar with. If you remember this UI.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;CSS June Macromedia Flash&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;600&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-flash.CiBmzXhI_Z1yh2cn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Were getting old&lt;/li&gt;
&lt;li&gt;You would know the pain of putting one frame after another to make an animation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I decided to get out &lt;a href=&quot;https://www.aseprite.org/&quot;&gt;asperite&lt;/a&gt; to make this funky little animation as an example!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;CSS Sprites Asperite&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3201&quot; height=&quot;774&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-asperite.CI8iQZ7K_Z19TUi7.webp&quot; srcset=&quot;&quot;&gt;
&lt;img alt=&quot;CSS Sprite Sheet&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;880&quot; height=&quot;80&quot; src=&quot;https://www.asbedb.dev/_astro/css-jun-sheet.BTRL6ctN_Zt2p3c.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;
	&lt;p data-theme-id=&quot;dark&quot; data-height=&quot;380&quot; data-pen-title=&quot;Lazy Loading Demo&quot; data-default-tab=&quot;css,result&quot; data-slug-hash=&quot;GgNWOwG&quot; data-user=&quot;dottys&quot;&gt;
	&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/dottys/pen/GgNWOwG&quot;&gt;
	Spritesheet Demo&lt;/a&gt; by dots (&lt;a href=&quot;https://codepen.io/dottys&quot;&gt;@dottys&lt;/a&gt;)
	on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
	&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;The linked article and external links in the TLDR have some examples of this but the premise is simple.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get yourself a sprite sheet.&lt;/li&gt;
&lt;li&gt;Use a cover div to effectively crop to your tile size, by setting the width and height to the sprite dimensions.&lt;/li&gt;
&lt;li&gt;Create a stepped animation function &lt;code dir=&quot;auto&quot;&gt;sprite 1s steps(&amp;#x3C;number of frames&gt;, jump-none) infinite;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Animate across or around your sprite sheet by manipulating either &lt;code dir=&quot;auto&quot;&gt;object-position&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;background-position&lt;/code&gt;’s from -&gt; to.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>WebDev</category></item><item><title>I made my own Wordle</title><link>https://www.asbedb.dev/musings/scapedle-game/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/scapedle-game/</guid><description>In this piece I go through how implementing a wordle clone gave me insight into automation, DSA and time zones.

</description><pubDate>Tue, 21 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When my friends asked how easy it would be to make a version of Wordle based on characters, items and quests from the popular game &lt;a href=&quot;https://oldschool.runescape.com/&quot;&gt;RuneScape&lt;/a&gt;. My initial answer was “It should be easy!”, I didn’t expect the architecture decisions, algorithm optimisation, and insight into trade-offs it would provide. Whilst it was a shorter fun little project, there are a few pearls worth sharing in case you too want to make your own Wordle.&lt;/p&gt;
&lt;p&gt;If you already know what RuneScape and Wordle is and you want to get straight into it - &lt;a href=&quot;#scapedle&quot;&gt;start here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to play the game you can check it out at &lt;a href=&quot;https://scapedle.com&quot;&gt;Scapedle.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This project is open to contributions and has been released fully open source under a GPL 2.0 license - &lt;a href=&quot;https://github.com/asbedb/Scapedle&quot;&gt;you can find the repository and contributing guide here&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-wordle&quot;&gt;What is Wordle&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Wordle is a guessing game in which you have to guess a five letter word in five guesses, each guess will provide you hints by displaying letters in three colours/shades.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A typical wordle game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;1021&quot; src=&quot;https://www.asbedb.dev/_astro/wordle-about.Dzt7XEce_24rtwi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Darker grey when they aren’t present in the word&lt;/li&gt;
&lt;li&gt;Orange if they are present in the word but not in the correct spot&lt;/li&gt;
&lt;li&gt;Green if they are present and in the correct spot&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-runescape&quot;&gt;What is RuneScape&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Released in 2001 RuneScape is a fantasy massively multiplayer online (MMO) game with a unique art style, point and click controls and a large (still growing) player base. When I began to look into the number of items in the game it was estimated to be close to 17,000 (that’s a lot of words!)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A RuneScape player fighting a boss in the game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;900&quot; height=&quot;492&quot; src=&quot;https://www.asbedb.dev/_astro/osrs-cerberus.CfHioE96_Z1x1oAA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;scapedle&quot;&gt;Scapedle&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;So now we mush Wordle and RuneScape’s characters, quests and items together and you have a word guessing game called &lt;a href=&quot;https://scapedle.com&quot;&gt;Scapedle&lt;/a&gt;! There are a few minor differences to note.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A screenshot of Scapedle&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;723&quot; height=&quot;1193&quot; src=&quot;https://www.asbedb.dev/_astro/scapedle-screen.Domfsnbv_1Ug3ws.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scapedle doesn’t have a five letter restriction, there are even multiple words to guess, due to this added difficulty ceiling there is an emoji hint to assist users.&lt;/li&gt;
&lt;li&gt;Some words are unique to the world of RuneScape so having prior knowledge of the game is also essential.&lt;/li&gt;
&lt;li&gt;Finally in addition to the emoji hints a user can “give up” one guess for an extra hint in the form of text.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;the-architecture&quot;&gt;The Architecture&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At a high level a typical game of Wordle is comprised of the following functions and features.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Word of the day&lt;/strong&gt; - a word is chosen after a nominated time period, these words seem to have a method around being chosen as they generally have a unique word number when being shared as solved.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dictionary&lt;/strong&gt; - when users guess words there is a dictionary lookup ensuring the word being guessed is in the English language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stateful&lt;/strong&gt; - a game of Wordle can be played all day, a user can walk away and close the app/website and come back to play it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile Friendly&lt;/strong&gt; - generally Wordle users are playing on a mobile device, it’s a fun little time passer and gets on average ~5-10 minutes screentime per day. The UI should be intuitive and touch friendly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The architecture and design phase actually came to be the most surprising and fulfilling part of this project. I wanted to “think like the team behind Wordle”, a team that supports an estimated 10-14.5 million active players per day. This meant making choices that allowed for scale, flexibility, automation, integrity (anti-cheat) and accuracy. In hindsight I am extremely happy I approached it this way as choices were easier to make when you are constrained.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;sveltekit&quot;&gt;SvelteKit&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;After careful consideration and pre-empting the work required for processes like “generating a daily word” and “managing user and game state”. I settled on &lt;a href=&quot;https://svelte.dev/&quot;&gt;SvelteKit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wanted a framework that could fill the role of both client and server side logic, but also stay within the realms of reasonable performance for a simple single page application. My experience with frameworks like NextJS left me with an impression that choosing it would be “overkill” for this project. The routing and SSR features whilst great for larger, more complex applications, would bring with it a performance hit for a simple word guessing game.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Svelte Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;730&quot; height=&quot;487&quot; src=&quot;https://www.asbedb.dev/_astro/svelte-logo.C8oT6lHE_NHmvU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Svelte was a great choice for this particular project and here’s why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Global State management for Game and Player&lt;/strong&gt; - I can just use runes to manage things across multiple components without having to worry about prop drilling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple HTML&lt;/strong&gt; - I just wanted the UI to work Svelte has a similar feel to Astro where it leans into the HTML feeling like HTML!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic file-based routing&lt;/strong&gt; - The routes of the API are defined by the file structures in codebase making it easier to manage functions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;On build server functions&lt;/strong&gt; - Every rebuild of the static site required an automation of word processing to happen, Svelte type safe load functions provide a neat interface to manage this.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;theming-and-design&quot;&gt;Theming and Design&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I also needed to ensure theming and design was on brand to invoke that nostalgic RuneScape feeling, I found the &lt;a href=&quot;https://osrs.design/&quot;&gt;OSRS Design System by milkbar designs&lt;/a&gt; as a great reference point helping keep colours, fonts and components consistent across my project.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSRS Design System Screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1109&quot; height=&quot;880&quot; src=&quot;https://www.asbedb.dev/_astro/osrs-design.BkKyUvyS_Z1E5K6D.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using tailwind 4 theme syntax, declarations means that the &lt;code dir=&quot;auto&quot;&gt;color&lt;/code&gt; property will be available across text, backgrounds and more. (see snippet below).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;@theme&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--font-osrs-small: &apos;RuneScape Small&apos;, &lt;/span&gt;&lt;span&gt;ui-sans-serif&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--font-osrs: &apos;RuneScape UF&apos;, &lt;/span&gt;&lt;span&gt;ui-sans-serif&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-yellow: &lt;/span&gt;&lt;span&gt;#ffcf3f;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-gold: &lt;/span&gt;&lt;span&gt;#e6a519;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-brown: &lt;/span&gt;&lt;span&gt;#694d23&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-dark-brown: &lt;/span&gt;&lt;span&gt;#382d1a&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-black: &lt;/span&gt;&lt;span&gt;#0f0f0f&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-green: &lt;/span&gt;&lt;span&gt;#00ff00&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-red: &lt;/span&gt;&lt;span&gt;#ff0000;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-blue: &lt;/span&gt;&lt;span&gt;#0088ff&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-chat: &lt;/span&gt;&lt;span&gt;#00ffff&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-background: &lt;/span&gt;&lt;span&gt;#2e2c29&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-border: &lt;/span&gt;&lt;span&gt;#474745&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--color-osrs-panel: &lt;/span&gt;&lt;span&gt;#46433a&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;scaling&quot;&gt;Scaling&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;There are two ways to check a users input against the correct answer. We either ship the answer in the client and test against it or we host the answer on a server and use some sort of middleware to check if the encrypted guess matches the encrypted answer. Shipping it with the client comes at the cost of making it way easier to cheat, and hosting it with a server comes at the cost of added infrastructure, complexity and management.&lt;/p&gt;
&lt;p&gt;I decided to keep the word of the day a client side feature and focussed on making it harder to cheat (It’s impossible to stop cheating client side).&lt;/p&gt;
&lt;p&gt;This decision also means that theoretically the load of 14.5 million active users playing has significantly reduced as the majority of compute is client side. Sure bandwidth is a concern but the over the wire requirements are not as taxing as 14.5 million API requests to a back end.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;wordlist&quot;&gt;Wordlist&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Originally the wordlist was built with some help from those beautiful guessing machines we have come to love. The file houses an array of objects and within each object we have a &lt;code dir=&quot;auto&quot;&gt;itemName&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;emojiHint&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;wordHint&lt;/code&gt;. I am currently in the process of refining this list and pushing updates per skill.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;server/wordList.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WORD_LIST&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// ============================================================&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// MINING&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// ============================================================&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ itemName: &lt;/span&gt;&lt;span&gt;&apos;Clay&apos;&lt;/span&gt;&lt;span&gt;, emojiHint: &lt;/span&gt;&lt;span&gt;&apos;🧱🏺⚒️&apos;&lt;/span&gt;&lt;span&gt;, wordHint: &lt;/span&gt;&lt;span&gt;&apos;ceramic&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ itemName: &lt;/span&gt;&lt;span&gt;&apos;Rune Essence&apos;&lt;/span&gt;&lt;span&gt;, emojiHint: &lt;/span&gt;&lt;span&gt;&apos;⚪⛏️🪨🪄&apos;&lt;/span&gt;&lt;span&gt;, wordHint: &lt;/span&gt;&lt;span&gt;&apos;Aubury&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Nothing particularly groundbreaking here, just a simple structure to help house all of our words!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;routing&quot;&gt;Routing&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The fun part of choosing a word comes from utilising Svelte file based routing system to dynamically load words from this list on every re-build (more to come in automation).&lt;/p&gt;
&lt;p&gt;Within the &lt;code dir=&quot;auto&quot;&gt;src&lt;/code&gt; folder which houses all of the logic that builds up the application, by nominating a &lt;code dir=&quot;auto&quot;&gt;routes&lt;/code&gt; folder you effectively tell Svelte to build pages based on folders and files.&lt;/p&gt;
&lt;p&gt;As an example, If there was a folder called &lt;code dir=&quot;auto&quot;&gt;src/routes/lumbridge&lt;/code&gt; and within that there’s a file called &lt;code dir=&quot;auto&quot;&gt;+page.svelte&lt;/code&gt;. After building the website a user navigating to &lt;code dir=&quot;auto&quot;&gt;scapedle.com/lumbridge&lt;/code&gt; (not a real link), would be greeted with the content in that route. In addition to this a route can also have a &lt;code dir=&quot;auto&quot;&gt;+page.server.js&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;+page.server.ts&lt;/code&gt; this is telling Svelte router that the load function for this particularly page can only run on the server and not the client.&lt;/p&gt;
&lt;p&gt;I am only shipping the daily word, hint and emojis to the client - I do not want the entire wordlist. The idea was to house the wordlist in a dedicated &lt;code dir=&quot;auto&quot;&gt;src/server&lt;/code&gt; (this route is a dedicated back end/build route) folder which tells Svelte to never include that in the client and access it through a server load function in &lt;code dir=&quot;auto&quot;&gt;+page.server.ts&lt;/code&gt;!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;daily-word&quot;&gt;Daily Word&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I needed a consistent way to seed the word, it needed to be random, within the constraints of the wordlist and seeded in a way that ties back to the date - the daily word number should correlate and be seeded with the date.&lt;/p&gt;
&lt;p&gt;The wordlist itself has some sequential structure based on RuneScape’s skills so going in order would mean a user would experience a theme of words grouped together if we went through the list in order.&lt;/p&gt;
&lt;p&gt;Unlike a &lt;code dir=&quot;auto&quot;&gt;Math.random()&lt;/code&gt; function in which every generated result would be unpredictable. I needed a helper that could take a seed and return consistent results. I came to realise these are called “Pseudo Random Number Generators” (PRNG).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getSeededRandom&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;seed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; seed &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x6d2b79f5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;t &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Math.&lt;/span&gt;&lt;span&gt;imul&lt;/span&gt;&lt;span&gt;(t &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; (t &lt;/span&gt;&lt;span&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;), t &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;t &lt;/span&gt;&lt;span&gt;^=&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; Math.&lt;/span&gt;&lt;span&gt;imul&lt;/span&gt;&lt;span&gt;(t &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; (t &lt;/span&gt;&lt;span&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;), t &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;61&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; ((t &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; (t &lt;/span&gt;&lt;span&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;)) &lt;/span&gt;&lt;span&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4294967296&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The helper above is called a &lt;a href=&quot;https://github.com/cprosche/mulberry32&quot;&gt;Mulberry32&lt;/a&gt;, the linked Stack Overflow article in the GitHub repository has many more examples of PRNGs to consider. I decided to go with Mulberry32 due to its speed since the PRNG was required once per build. With that I used the date of build as a seed to get consistent results!&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Date&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Date&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;formatter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Intl.&lt;/span&gt;&lt;span&gt;DateTimeFormat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;en-AU&apos;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;timeZone: &lt;/span&gt;&lt;span&gt;&apos;Australia/Sydney&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;year: &lt;/span&gt;&lt;span&gt;&apos;numeric&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;month: &lt;/span&gt;&lt;span&gt;&apos;numeric&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;day: &lt;/span&gt;&lt;span&gt;&apos;numeric&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; formatter.&lt;/span&gt;&lt;span&gt;formatToParts&lt;/span&gt;&lt;span&gt;(now)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dateMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Object.&lt;/span&gt;&lt;span&gt;fromEntries&lt;/span&gt;&lt;span&gt;(parts.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; [p.type, p.value]))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;year&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseInt&lt;/span&gt;&lt;span&gt;(dateMap.year)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;month&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseInt&lt;/span&gt;&lt;span&gt;(dateMap.month) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;day&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseInt&lt;/span&gt;&lt;span&gt;(dateMap.day)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aestToday&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Date&lt;/span&gt;&lt;span&gt;(year, month, day)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startOfYear&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Date&lt;/span&gt;&lt;span&gt;(year, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dayOfYear&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Math.&lt;/span&gt;&lt;span&gt;floor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(aestToday.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; startOfYear.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;()) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;86400000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;seed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; year &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; dayOfYear&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;randomIndex&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Math.&lt;/span&gt;&lt;span&gt;floor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;getSeededRandom&lt;/span&gt;&lt;span&gt;(seed) &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WORD_LIST&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; wordCount&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dailyWord&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WORD_LIST&lt;/span&gt;&lt;span&gt;[randomIndex]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All words are stripped of special characters like &lt;code dir=&quot;auto&quot;&gt;-&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;&apos;&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;+&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;(&lt;/code&gt; and converted to upper case to ensure any inconsistent names in the wordlist are able to be guessed fairly.&lt;/li&gt;
&lt;li&gt;The return statement is cut off on purpose; you can find full code on GitHub below is for illustrative purposes only.&lt;/li&gt;
&lt;li&gt;Australian time zone is hardcoded to AEST (Australia/Sydney) to ensure consistent daily word rotation aligned with my local schedule.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;anti-cheat&quot;&gt;Anti-cheat&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In game development, the more you serve via the client, the more you relinquish control over anti-cheat opening an application up to memory manipulation and cheating. I guess it’s not that different in web - looking at functions such as secure authentication and encryption, these rely on appropriate methods in middleware and back end.&lt;/p&gt;
&lt;p&gt;So you decided to ship the answer for your game with the game client, what next?&lt;/p&gt;
&lt;p&gt;Well we need to make it harder for Hackerman to find the answer! Not impossible, just harder.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Hackerman Meme from Kungfury&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1370&quot; height=&quot;582&quot; src=&quot;https://www.asbedb.dev/_astro/hackerman-meme.BMackPyx_1RVBUN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’ll be honest, beyond simple encoding, if someone is willing to make the effort to cheat and decode the word, &lt;em&gt;that’s fine&lt;/em&gt;. Funnily enough for a long time Wordle also did the same thing and worked on an honour policy. These days I’m not too sure, essentially the simple things to do here is to ensure the returned objects key isn’t too obvious in suggesting the answer lies there and to wrap the word itself in a &lt;code dir=&quot;auto&quot;&gt;btoa()&lt;/code&gt; method which encodes the answer as a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/btoa&quot;&gt;Base64 ASCII string from a Binary string. &lt;/a&gt;. This provides basic obfuscation but isn’t true encryption—anyone inspecting the code can decode it trivially.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;dictionary&quot;&gt;Dictionary&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The leetcode grind actually came in useful for this feature. I needed to create a dictionary of words which were derived from the initial wordlist, this included words which were specific to RuneScape, you wouldn’t find &lt;code dir=&quot;auto&quot;&gt;Guthix&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;Saradomin&lt;/code&gt; in the English lexicon.&lt;/p&gt;
&lt;p&gt;I committed to client side which meant no fancy third party services or APIs deciding to instantiate a dynamic dictionary during build time which shipped with the client. The initial build is O(n) as we would iterate through every word in our wordlist, the lookups are O(1) on average as we are effectively building a HashMap that takes into account the length of a word and the word itself!&lt;/p&gt;
&lt;p&gt;Here’s the dictionary code in action! I was also able to integrate a nice little UI feature that showed how many guessable words are available by tracking the word count when building the dictionary.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dictionary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WORD_LIST&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;reduce&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;acc&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;individualWords&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; item.itemName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;toUpperCase&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;replace&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;\s&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;individualWords.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;word&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cleanWord&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; word&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; cleanWord.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (len &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;acc[len]) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acc[len] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;acc[len].&lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;(cleanWord)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acc[len].&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(cleanWord)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;wordCount&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; acc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{} &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Record&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;svelte-runes&quot;&gt;Svelte Runes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;After the server pushed to the client the following items:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encoded word of the day&lt;/li&gt;
&lt;li&gt;Emoji hint&lt;/li&gt;
&lt;li&gt;Word hint&lt;/li&gt;
&lt;li&gt;Word number&lt;/li&gt;
&lt;li&gt;Dictionary&lt;/li&gt;
&lt;li&gt;Word count (to render on the UI number of words available to guess)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The functional logic of the game needed to be mapped. Inadvertently Svelte has this concept of &lt;code dir=&quot;auto&quot;&gt;Runes&lt;/code&gt; (what a coincidence!).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;What are runes?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Runes are symbols that you use in &lt;code dir=&quot;auto&quot;&gt;.svelte&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;.svelte.js&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;.svelte.ts&lt;/code&gt; files to control the Svelte compiler. If you think of Svelte as a language, runes are part of the syntax — they are &lt;em&gt;keywords&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Runes have a &lt;code dir=&quot;auto&quot;&gt;$&lt;/code&gt; prefix and look like functions:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; message &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$state&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;hello&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://svelte.dev/docs/svelte/what-are-runes&quot;&gt;&lt;em&gt;Source&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Svelte provides a few of these runes for consideration - if you are familiar with reactive web UI libraries some of the terminology will be familiar.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;$state&lt;/code&gt; - a rune which holds a variable data store which can be used to trigger re-renders, the UI reacts to this component as an example a state that holds a count could start at &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;$derived&lt;/code&gt;- a rune which will conditionally update based on a &lt;code dir=&quot;auto&quot;&gt;$state&lt;/code&gt; rune within your component, as an example a component may always be &lt;code dir=&quot;auto&quot;&gt;$state + 2&lt;/code&gt; so we can derive it accordingly.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;$effect&lt;/code&gt; - A function which runs when a &lt;code dir=&quot;auto&quot;&gt;$state&lt;/code&gt; updates.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;$props&lt;/code&gt; - Inputs to a component including it’s children&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There’s a lot of additional nuance but at a high level these are the main runes to consider.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;global-state&quot;&gt;Global State&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Disclaimer: The next section outlines a file placed in stores folder - this should not be confused with Svelte global stores prior to Svelte 5 - I only realised the naming convention may cause confusion after the fact and will refactor to remove doubts in future.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In a svelte project the &lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; folder within your &lt;code dir=&quot;auto&quot;&gt;src&lt;/code&gt;, is a unique path.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; contains your library code (utilities and components), which can be imported via the &lt;a href=&quot;https://svelte.dev/docs/kit/$lib&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;$lib&lt;/code&gt;&lt;/a&gt; alias, or packaged up for distribution using &lt;a href=&quot;https://svelte.dev/docs/kit/packaging&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;svelte-package&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Within this folder there are a few additional paths that are unique like &lt;code dir=&quot;auto&quot;&gt;server&lt;/code&gt;, outside of this you are free to manage and build out your structure in an easy to read and manageable format.&lt;/p&gt;
&lt;p&gt;For the game state this looked a little something like this.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/lib/stores/gameState.svelte.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExternalData&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;itemName&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;emojiHint&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;wordHint&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;wordNumber&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dictionary&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Record&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;wordCount&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GameStateType&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;guesses&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;currentGuess&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;playing&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;won&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;lost&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;hintUsed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;gameStarted&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;invalidWord&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; rawData &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$state&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;ExternalData&lt;/span&gt;&lt;span&gt;&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;itemName: &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;emojiHint: &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;wordHint: &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;wordNumber: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dictionary: {},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;wordCount: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;solution&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.itemName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gameData&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;solution&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.itemName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;emojiHint&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.emojiHint&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wordHint&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.wordHint&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wordNumber&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.wordNumber&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dictionary&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.dictionary&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wordCount&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; rawData.wordCount&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gameState&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$state&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;GameStateType&lt;/span&gt;&lt;span&gt;&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;guesses: [],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;currentGuess: &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;status: &lt;/span&gt;&lt;span&gt;&apos;playing&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;hintUsed: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameStarted: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;invalidWord: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;initStore&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExternalData&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isNewWord&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data.wordNumber &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; rawData.wordNumber&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (isNewWord) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.guesses &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;playing&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.gameStarted &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.hintUsed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rawData &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above in summary works on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up types for &lt;code dir=&quot;auto&quot;&gt;ExternalData&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;GameStateType&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Instantiating a &lt;code dir=&quot;auto&quot;&gt;rawData&lt;/code&gt; object to manipulate.&lt;/li&gt;
&lt;li&gt;Exporting functions to &lt;code dir=&quot;auto&quot;&gt;get&lt;/code&gt; our solution and &lt;code dir=&quot;auto&quot;&gt;gameData&lt;/code&gt; values&lt;/li&gt;
&lt;li&gt;Exporting our &lt;code dir=&quot;auto&quot;&gt;gameState&lt;/code&gt; object&lt;/li&gt;
&lt;li&gt;Exporting an initialisation function &lt;code dir=&quot;auto&quot;&gt;initStore&lt;/code&gt; that checks if a new word has been loaded prior to resetting the game state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the state loaded in our &lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; this allowed me to call the same consistent state no matter how deeply nested my folders were - this is crucial as I needed to track.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Guesses&lt;/li&gt;
&lt;li&gt;Prompt usage&lt;/li&gt;
&lt;li&gt;Letters in word/out of word already guessed&lt;/li&gt;
&lt;li&gt;The word of the day, emojis and the dictionary&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can view the component code in more detail on the GitHub however here is a small example of how this came to be used in the project.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/lib/components/HintButton.svelte&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;script lang&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ts&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { gameData, gameState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;$lib/stores/gameState.svelte&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { BLANK_GUESS } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;$lib/constants&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; { focusInput } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$props&lt;/span&gt;&lt;span&gt;&amp;#x3C;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;focusInput&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useHint&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gameState.status &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;playing&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; gameState.hintUsed &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;gameData.wordHint) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.guesses.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;BLANK_GUESS&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.hintUsed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;focusInput&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; gameData.wordHint}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;..styling&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;gameState.hintUsed}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;onclick&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(e) =&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;e.&lt;/span&gt;&lt;span&gt;stopPropagation&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;useHint&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;..styling&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;PROMPT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HINT&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GUESS&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{:&lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;..styling&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;p class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;..styling&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;Hint Revealed&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;p class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;..styling&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;{gameData.wordHint}&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;/if&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;/if&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the script tag we import the &lt;code dir=&quot;auto&quot;&gt;gameData&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;gameState&lt;/code&gt; - note the path points to &lt;code dir=&quot;auto&quot;&gt;$lib&lt;/code&gt;, this means no drilling and mental math is required and the state is persistent across our shared components and page.&lt;/p&gt;
&lt;p&gt;This also means pushing up changes across multiple components becomes much easier.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;github-pages--daily-runner&quot;&gt;GitHub Pages + Daily Runner&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The last piece to the puzzle was automating the publishing of the page with updates, whether it be a daily word or a new feature being merged. As the project is being managed through GitHub it made sense to stay within the ecosystem. The project is open source meaning other developers can contribute or fork the repository to build their own versions.&lt;/p&gt;
&lt;p&gt;The way I solved this challenge was by hosting the main branch on &lt;a href=&quot;https://pages.github.com&quot;&gt;GitHub Pages&lt;/a&gt; with a workflow file that automates a rebuild every 24 hours and on successful merge of pull requests to the main branch.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;managing-the-game-loop&quot;&gt;Managing the Game Loop&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As the game state is now an accessible rune across all components, managing that state is the main task at hand with various functions. I am going to provide a quick fire insight into this with links to the full code for the curious.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;local-storage&quot;&gt;Local Storage&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Early on I elected to utilise local storage as a means to track progress on the word of the day, a simple yet effective browser API that lets us manage an otherwise overly complicated feature if we wanted a persistent user state via a database.&lt;/p&gt;
&lt;p&gt;The local storage holds the bare minimum required for a user to come back and check in/make extra guesses until the game is up.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;onMount&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;saved&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; localStorage.&lt;/span&gt;&lt;span&gt;getItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;STORAGE_KEY&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (saved) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(saved)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (data.wordNumber &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; gameData.wordNumber) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.guesses &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data.guesses &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.hintUsed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data.hintUsed &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.gameStarted &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data.gameStarted &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;STORAGE_KEY&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$effect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gameState.gameStarted &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; gameState.guesses.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stateToSave&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;wordNumber: gameData.wordNumber,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;guesses: $state.&lt;/span&gt;&lt;span&gt;snapshot&lt;/span&gt;&lt;span&gt;(gameState.guesses),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;hintUsed: gameState.hintUsed,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameStarted: gameState.gameStarted,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;setItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;STORAGE_KEY&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stringify&lt;/span&gt;&lt;span&gt;(stateToSave))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The cliff notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On initial mount/render of site the client checks against local storage to see if a new word is being guessed &lt;code dir=&quot;auto&quot;&gt;data.wordNumber === gameData.wordNumber&lt;/code&gt; - if it’s new &lt;code dir=&quot;auto&quot;&gt;removeItem&lt;/code&gt; is invoked and the &lt;code dir=&quot;auto&quot;&gt;$effect&lt;/code&gt; will instantiate a blank object for the new word.&lt;/li&gt;
&lt;li&gt;An effect runs when making a guess, using a hint or starting a game. The primary purpose of this effect is to update &lt;code dir=&quot;auto&quot;&gt;guesses&lt;/code&gt; in local storage.&lt;/li&gt;
&lt;li&gt;Svelte has an advanced feature called &lt;a href=&quot;https://svelte.dev/docs/kit/snapshots&quot;&gt;snapshots&lt;/a&gt; this allows us to de-proxy the state stored in local storage which can help remove issues around serialisation.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;starting-the-game&quot;&gt;Starting the game&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The gameboard is initialised and the user is greeted with a “Start Quest” button, this was a strategic choice as “input jacking” with a hidden input is generally frowned upon with mobile browsers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A screenshot of scapedle on mobile&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;461&quot; height=&quot;825&quot; src=&quot;https://www.asbedb.dev/_astro/scapedle-start-quest.6v232rPw_1QpgDn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Both Scapedle and Wordle provide the user an option to use normal onscreen keyboards (or physical on pc) to input guesses. I wanted the same feeling on mobile. I resorted to using a start button that tells the browser to focus on this hidden input and in turn brings up the onscreen keyboard!&lt;/p&gt;
&lt;p&gt;This in turn also helps with initialising our local storage (used to track progress on the daily word) by putting the game in a &lt;code dir=&quot;auto&quot;&gt;playing&lt;/code&gt; state.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;making-a-guess&quot;&gt;Making a Guess&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Once the user makes a guess using the onscreen keyboard or the presented letter blocks that guess is checked against the word of the day. Each &lt;code dir=&quot;auto&quot;&gt;guess&lt;/code&gt; is updated in our &lt;code dir=&quot;auto&quot;&gt;gameState.guesses&lt;/code&gt; array and those entries are used on the keyboard component to provide user feedback on if the letter has been exhausted in the word (green), present but not in correct place (orange) or not in word at all (darker shade on keyboard).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A screenshot of scapedle with an incorrect guess&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;476&quot; height=&quot;1009&quot; src=&quot;https://www.asbedb.dev/_astro/scapedle-incorrect-guess.DanB3kBm_ZqPtao.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are a few techniques I used here that turned out to be really useful.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gameState.currentGuess.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; totalExpectedLength) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; isEntireGuessValid &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; currentIndex&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;part&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; targetParts) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cleanPart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; part.&lt;/span&gt;&lt;span&gt;replace&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;A-Z]&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;partLength&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; cleanPart.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;guessChunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; gameState.currentGuess.&lt;/span&gt;&lt;span&gt;slice&lt;/span&gt;&lt;span&gt;(currentIndex, currentIndex &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; partLength);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;validWordsForLen&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; gameData.dictionary[partLength] &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;validWordsForLen.&lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;(guessChunk)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;isEntireGuessValid &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;triggerInvalidEffect&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;currentIndex &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; partLength;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (isEntireGuessValid) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.guesses.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(gameState.currentGuess);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.currentGuess &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.invalidWord &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gameState.currentGuess.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; totalExpectedLength &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; key.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;[a-zA-Z]&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;(key)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.currentGuess &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; key.&lt;/span&gt;&lt;span&gt;toUpperCase&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The word of the day is broken into parts (split by spaces) this in turn is used when making a guess to check a single string against the dictionary because we can split the guess into parts - that’s how the valid words are identified (we even slide a window here!).&lt;/li&gt;
&lt;li&gt;All special characters have been stripped to make this logic easier to follow.&lt;/li&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;currentGuess&lt;/code&gt; is tracked and that’s how we determine if the user even has an option to “attempt to guess”. If the &lt;code dir=&quot;auto&quot;&gt;currentGuess&lt;/code&gt; doesn’t match the full word length then we don’t even attempt to look at the dictionary.&lt;/li&gt;
&lt;li&gt;A special global constant is used if the user elects to use a “hint” that will remove one guess completely and hold it in memory as such (this comes handy when sharing results).&lt;/li&gt;
&lt;li&gt;Finally once all guesses are exhausted or the correct word is guessed the game ends with a screen showing the word of the day and a share option.&lt;/li&gt;
&lt;li&gt;a &lt;code dir=&quot;auto&quot;&gt;triggerInvalidEffect()&lt;/code&gt; function is dedicated to give the user a little flashup of red text letting them know the word they have guessed is not currently in the dictionary of words available to guess.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;winning-or-losing&quot;&gt;Winning or Losing&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Winning or losing a game of Scapedle looks a little like this
&lt;img alt=&quot;A screenshot of a scapedle game being won&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1527&quot; height=&quot;1262&quot; src=&quot;https://www.asbedb.dev/_astro/scapedle-game-won.B0lMyCG0_1qJ7Of.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Naturally the global state tracking our games progress is utilised to match our guesses to the word of the day and effectively return a win/lose/still playing result.&lt;/p&gt;
&lt;p&gt;This is actually a fairly simple if statement being run as an &lt;code dir=&quot;auto&quot;&gt;$effect&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$effect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gameState.guesses.&lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;(targetAlpha)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;won&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gameState.guesses.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MAX_GUESSES&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;lost&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gameState.status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;playing&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;by tracking our &lt;code dir=&quot;auto&quot;&gt;status&lt;/code&gt; - we can lock the gameboard, show modals or allow additional guesses making it very easy to manage the UI. The modal in the pictured screenshot renders conditionally when a user is no longer in a &lt;code dir=&quot;auto&quot;&gt;playing&lt;/code&gt; state, taking into account the win/loss position of the board. From there a share results option is presented - these are fun little emoji messages used to help spread the game and challenge friends!&lt;/p&gt;
&lt;p&gt;Scapedles looks a little something like this.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Scapedle - An OSRS Guessing Game&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Todays Word #111 - 3/5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;🟨🟨⬛⬛🟨🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟨⬛&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Play at: https://scapedle.com/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With the code looking like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;generateEmojiGrid&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; gameState.guesses&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;guess&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (guess &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BLANK_GUESS&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Array&lt;/span&gt;&lt;span&gt;(targetAlpha.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;⬛&apos;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; guess&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (char &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; targetAlpha[i]) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;🟩&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (targetAlpha.&lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;(char)) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;🟨&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;⬛&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Essentially a simple map of characters in each valid guess to represent its corresponding return in the original guess with a line break at the end of the word length.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;wrap-it-up&quot;&gt;Wrap it up&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Building Scapedle taught me that “easy” projects often hide the most interesting challenges. What seemed like a simple Wordle clone turned into a whole lot more.&lt;/p&gt;
&lt;p&gt;The best part? It’s all open source. Fork the &lt;a href=&quot;https://github.com/asbedb/Scapedle&quot;&gt;repository&lt;/a&gt;, build your own variant, or just come play at &lt;a href=&quot;https://scapedle.com&quot;&gt;Scapedle.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Whether you’re here for RuneScape nostalgia or insights, I hope you found something useful in this breakdown. Now go guess that word—you’ve got this.&lt;/p&gt;</content:encoded><category>WebDev</category></item><item><title>sRGB to HSV - Science or Magic?</title><link>https://www.asbedb.dev/musings/rgb-to-hsv/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/rgb-to-hsv/</guid><description>An overview of computers and colour and how most of our devices show them off

</description><pubDate>Sat, 17 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Update 21/04/26:&lt;/strong&gt; You can find the accompanying talk to this topic by &lt;a href=&quot;https://www.youtube.com/watch?v=EB62o1lCip0&quot;&gt;clicking this link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Recently, I was automating colour generation for a theme engine, which sparked a question&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;“Why do I instinctively lean towards a HSV Colour picker when trying to pick a colour on my computer?”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Investigating a little further into the “why” of how computers work, brings me immense joy. By the end of this piece, I hope to provide insight into what helped me understand colour space, colour transformations and what they can represent in digital form.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-brief&quot;&gt;The Brief&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;From a programming standpoint, the problem I was looking to solve was fairly simple.&lt;/p&gt;
&lt;p&gt;This is the high level summary:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Take seed colours (Primary, Secondary, Tertiary, Neutral and Semantic).&lt;/li&gt;
&lt;li&gt;Ensure the colour set has an &lt;code dir=&quot;auto&quot;&gt;isDark&lt;/code&gt; flag to help deal with contrast and shades for a “Dark Mode” colour scheme.&lt;/li&gt;
&lt;li&gt;Generate shades of each colour and label 100,300,500,700,900 with 100 being the lightest and 900 being the darkest (if you use &lt;code dir=&quot;auto&quot;&gt;tailwindcss&lt;/code&gt; this might already be familiar to you).&lt;/li&gt;
&lt;li&gt;Compile our colours into a list of variables to be imported at the parent level of a CSS file (example `-primary-100: #222222;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And my intuition immediately lead to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Obtain our seed colour hex codes.&lt;/li&gt;
&lt;li&gt;Convert to a HSV value.&lt;/li&gt;
&lt;li&gt;Have a set of standard transforms based on the colour scheme flag (&lt;code dir=&quot;auto&quot;&gt;isDark&lt;/code&gt; so we can apply the right contrast ratios).&lt;/li&gt;
&lt;li&gt;Apply transforms and reconvert to hex with results ready to append.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The reason for my intuition came from having played with HSV values (in a visual tool like a colour picker) in the past. I already knew they were the right choice for this exercise, I had just never looked into why.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;An example of a shaded colour - purple&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;273&quot; height=&quot;549&quot; src=&quot;https://www.asbedb.dev/_astro/shades-purple.CbvGiaiF_1XzBB8.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source: &lt;a href=&quot;https://m2.material.io/design/color/the-color-system.html#tools-for-picking-colors&quot;&gt;Material Design: Tools for Picking Colour&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But before I do that we need to cover some of the introductory content to this space. If you want to jump straight into the meat and bones feel free to skip ahead to &lt;a href=&quot;#the-rgb-colour-model&quot;&gt;The RGB Colour Model&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;colour-is-sensed-and-perceived&quot;&gt;Colour is Sensed and Perceived&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Colour is the translation of light sensed by the human eye and perceived by the brain.&lt;/p&gt;
&lt;p&gt;Colour literature has roots dating as far back as 322 BCE (&lt;a href=&quot;https://en.wikipedia.org/wiki/On_Colors&quot;&gt;Aristotle’s - On Colours&lt;/a&gt;). Many of the concepts and standards we will come to discuss are tied to Isaac Newton’s &lt;a href=&quot;https://hti.osu.edu/sites/hti.osu.edu/files/Sir-Isaac-Newton_Letter-Theory-Light-Colors.pdf&quot;&gt;extensive work on colour theory&lt;/a&gt; stating that white light is composed of a spectrum of colours, and colour is not intrinsic to objects, but rather arises from the way an object reflects or absorbs different wavelength.&lt;/p&gt;
&lt;p&gt;Newton also discovered that sunlight is composed of 7 primary colours which are visible when passed through a prism: Red, Orange, Yellow, Green, Blue, Indigo and Violet. (fun fact: Newton added Indigo to ensure the 7 colours were aligned to musical notes Do, Re, Mi, Fa, Sol, La, Ti)&lt;/p&gt;
&lt;p&gt;An average healthy human eye can see around &lt;strong&gt;100 million different colours.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is due to the three cone cell types (photoreceptors) found in the retina which can process ~100 different colour shades, amounting to ~one million combinations.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fun Fact:&lt;/em&gt; The same biological factors can be observed in the animal kingdom, with the number of cone cells being varied. As an example some species of fish are considered to have &lt;a href=&quot;https://en.wikipedia.org/wiki/Double_cone_(biology)&quot;&gt;double cones&lt;/a&gt; where as others might have &lt;a href=&quot;https://en.wikipedia.org/wiki/Tetrachromacy&quot;&gt;four cones&lt;/a&gt;. The result of less or more cell types changes the way colours are perceived.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Photo Receptor Cells in the Eye&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;320&quot; src=&quot;https://www.asbedb.dev/_astro/photo-receptors-eye.Dk4aBIJE_Zyxfxu.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source:&lt;/em&gt; &lt;a href=&quot;https://www.aao.org/image.axd?id=7de23d7d-7d22-4c72-81ed-292dc01cfbcf&amp;#x26;t=636422014777200000&quot;&gt;American Academy of Ophthalmology&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The human eye has light-detecting neurons in the retina (rods and cones) that convert light into electrical signals for vision. The rods handle dim light and black/white vision and the cones are responsible for colour and sharp daytime vision. The human eye can perceive more variations in warmer colours rather than cooler ones due to a higher mix of cones that process longer light wavelengths (reds). These cone cells are classed as L, M and S (Long, Medium and Short)&lt;/p&gt;
&lt;p&gt;The estimated split of cone cells in a human eye are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;60% Red Sensing &lt;em&gt;L&lt;/em&gt; (these cones technically peak in the yellow-green part of the spectrum)&lt;/li&gt;
&lt;li&gt;30% Green Sensing &lt;em&gt;M&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;10% Blue Sensing &lt;em&gt;S&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Variations in this make up means a different perception of colour with a deficiency being considered a root cause of &lt;a href=&quot;https://en.wikipedia.org/wiki/Color_blindness&quot;&gt;colour blindness&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In summary the process looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Light hits photopigments in the photoreceptors outer segment&lt;/li&gt;
&lt;li&gt;The absorption starts a biochemical chain reaction (transduction)&lt;/li&gt;
&lt;li&gt;This changes the cell’s membrane potential and creates an electrical signal&lt;/li&gt;
&lt;li&gt;The signal is passed along through cells to the optic nerve and then brain&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With this some of the biology out of the way lets dive a little more into computers and colour. Because our perception is so tied to these biological quirks—like our heightened sensitivity to green and red—computer programmers needed a way to translate the ‘sensing’ into reproducible data. This is where standards come in.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;standards-standards-standards&quot;&gt;Standards, Standards, Standards&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In doing my research an article I discovered had three poignant quotes that are worth repeating (as I am a fledging in this space and can see the depths to which this topic can lead).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CIE colorimetry isn’t even half the story of colour science, it’s a tiny piece of the huge puzzle of human perception and engineering that is colour science. Don’t confuse understanding it with understanding colour perception.&lt;/p&gt;
&lt;p&gt;Colorimetry is essentially linear algebra, human perception is much more complex. CIE colorimetry isn’t the whole story of colorimetry. It’s the modern standard but the theoretical work was done by James Maxwell in the 1850s.&lt;/p&gt;
&lt;p&gt;Differentiating theoretical colorimetry from the CIE’s implementation of it will be a milestone in your understanding. I recommend : &lt;a href=&quot;https://mitpress.mit.edu/books/color-science&quot;&gt;Jan Koenderink’s Color For the Sciences&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Source&lt;/em&gt;: &lt;a href=&quot;https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65a&quot;&gt;A Beginner’s Guide to (CIE) Colorimetry&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The CIE (Commission internationale de l’éclairage) an over 100 year old organisation is the peak body providing a forum, developing international uniform standards and cooperating with interwoven fields related to the following categories (within the context of light and colour):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Light&lt;/li&gt;
&lt;li&gt;Lighting&lt;/li&gt;
&lt;li&gt;Photobiology&lt;/li&gt;
&lt;li&gt;Vision and Colour&lt;/li&gt;
&lt;li&gt;Image Technology&lt;/li&gt;
&lt;li&gt;Measurement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Specifically around Image Technology they focus on bridging the gap between how we can make printed and display images match what we see. This includes methods, measurements and quantifiable ways of processing analogue or digital reproductions of colour.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;cie-1931-colour-system&quot;&gt;CIE 1931 Colour system&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The CIE 1931 Chromaticity Diagram (below) &lt;strong&gt;&lt;em&gt;“represents”&lt;/em&gt;&lt;/strong&gt; the full gamut of human colour perception. Funnily enough depending on how the chart is presented you are also going to be limited by the colour space that it was rendered in (more on this shortly). It is a mathematical model and is a &lt;strong&gt;&lt;em&gt;“static idealisation”&lt;/em&gt;&lt;/strong&gt; i.e. what is theorised to be the colour vision of a normal human.
&lt;img alt=&quot;CIE 1931 Chromaticity Diagram&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;830&quot; src=&quot;https://www.asbedb.dev/_astro/cie-1931-d.BOjDNwhq_1opTG.webp&quot; srcset=&quot;&quot;&gt;
The diagram has a few elements to consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The outer curved boundary is the &lt;em&gt;spectral (or monochromatic) locus&lt;/em&gt; - it represents the physical measurement of light oscillation represented in wavelengths.&lt;/li&gt;
&lt;li&gt;The bottom of the chart omits this outer boundary (The purple line) These colours don’t exist as a single wavelength in nature; they are only “sensations” created by our brain when it receives both short (blue) and long (red) wavelengths simultaneously.&lt;/li&gt;
&lt;li&gt;The diagram adopts colour names from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Munsell_color_system&quot;&gt;Munsell colour system&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The solid curved line with dots through the middle (&lt;a href=&quot;https://en.wikipedia.org/wiki/Planckian_locus&quot;&gt;Planckian locus&lt;/a&gt;) is the path an &lt;a href=&quot;https://en.wikipedia.org/wiki/Black-body_radiation&quot;&gt;incandescent black body&lt;/a&gt; would take in this colour space as its temperature changes. (Think the colour of heat).&lt;/li&gt;
&lt;li&gt;Near the centre of the curve (denoted as either D65 or Point E) is usually known as the “white point” or a “defined white”.&lt;/li&gt;
&lt;li&gt;And just above the x-axis those temperatures on the locus are represented in Kelvin.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;colour-spaces-whats-that-about&quot;&gt;Colour Spaces, what’s that about?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A colour space is a digital device translation tool or dictionary used to define how colours are coded and organized.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Mapped Colour Diagram with Colour Spaces&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1086&quot; height=&quot;1034&quot; src=&quot;https://www.asbedb.dev/_astro/color-spaces-mapped-chroma.BQSDsHkJ_Z1MYW06.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Below I’ve summarised a few colour spaces to help give an understanding on how different output devices may display colour.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Primary Medium&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Key Characteristic&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;NTSC 1954&lt;/td&gt;&lt;td&gt;Analogue Television&lt;/td&gt;&lt;td&gt;The first colour standard for broadcast; notable for using YIQ colour space to remain backwards-compatible with black-and-white television. &lt;a href=&quot;https://www.telecomponents.com/html/ntsc.htm&quot;&gt;Some great information here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;sRGB&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Web &amp;#x26; Standard Monitors&lt;/td&gt;&lt;td&gt;The universal standard; smallest gamut but highest compatibility.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Adobe RGB&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Print &amp;#x26; Photography&lt;/td&gt;&lt;td&gt;Extended greens/cyans to match CMYK printing capabilities.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;DCI-P3&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Cinema &amp;#x26; Modern Smartphones&lt;/td&gt;&lt;td&gt;High-saturation standard required for HDR content.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Rec.2020&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;UHD / 8K Television&lt;/td&gt;&lt;td&gt;A massive gamut representing the future of display technology.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;the-rgb-colour-model&quot;&gt;The RGB Colour Model&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The RGB Colour model is considered an &lt;a href=&quot;https://en.wikipedia.org/wiki/Additive_color&quot;&gt;&lt;em&gt;additive colour model&lt;/em&gt;&lt;/a&gt; in which the combination of red, green and blue primary colours of light are added together to reproduce a broad array of colours. The RGB model is for sensing, representation and display of images in electronic systems. The model aligns to our perception of colours (Trichromacy).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;RGB Colour Model&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;457&quot; height=&quot;448&quot; src=&quot;https://www.asbedb.dev/_astro/rgb-colour-model.BMNGU96n_Z1AtF9x.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source: &lt;a href=&quot;https://www.figma.com/resource-library/what-is-rgb/&quot;&gt;Figma’s article “What is RGB”&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To form a colour we superimpose three light beams (red, green and blue) either by, emission from black, or reflection from white. Each beam is labelled a component of that colour. The reason the RGB space is considered additive is because if light beams of differing colour (frequency) are superposed in space, their light spectra adds up, resulting in total spectrum.&lt;/p&gt;
&lt;p&gt;To map a RGB triplet the component values are treated as positive &lt;a href=&quot;https://en.wikipedia.org/wiki/Cartesian_coordinate_system&quot;&gt;Cartesian coordinates &lt;/a&gt; with a double value clamped between 0 and 1. If you could visualize a cube holding the bounds of the colour space a point with an X (Red), Y (Blue) and Z (green) “coordinate” will represent a colour (more on this shortly).&lt;/p&gt;
&lt;p&gt;With this geometric representation additional computations can be applied such as colour similarity by mapping the distance between two given RGB colours.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;srgb-colour-space-and-transfer-function&quot;&gt;sRGB Colour Space (and Transfer Function)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;On November 5, 1996 Michael Stokes (Hewlett-Packard), Matthew Anderson (Microsoft), Srinivasan Chandrasekar (Microsoft) and Ricardo Motta (Hewlett-Packard) submitted a joint proposal to the W3C titled &lt;a href=&quot;https://www.w3.org/Graphics/Color/sRGB.html&quot;&gt;A Standard Default Color Space for the Internet - sRGB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Jointly written by HP and Microsoft the paper plays an instrumental role in shaping how we sense colour on computers today.&lt;/p&gt;
&lt;p&gt;The tech industry was facing a challenge. Hardware, applications and output devices were all displaying colour information with different standards applied. High end users who needed precision had access to hardware and software which supported a wider gamut whilst lower end entry level devices would be limited in support for such colour spaces. If the problem wasn’t addressed there would be a considerable effort required to maintain the colour display ecosystem.&lt;/p&gt;
&lt;p&gt;To address this, the paper put forward a standardised colour space (Standard RGB or sRGB) with the intention to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improve colour fidelity in the desktop environment&lt;/li&gt;
&lt;li&gt;Create a uniform standard for software development&lt;/li&gt;
&lt;li&gt;Confidently communicate colours with minimal overhead&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Essentially sRGB is a communication ruleset, a “lingua franca” (common language), made possible by constant parameters adopted to create a common colour language.&lt;/p&gt;
&lt;p&gt;To achieve this there are a couple of important factors to consider:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;colorimetric-rgb&quot;&gt;Colorimetric RGB&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;sRGB uses precise standardised definition of anchor colours, specifically the Rec.709 values for Red, Green Blue and White (D65). The reason REC.709 was chosen was because it matched the phosphors used in the consumer CRT monitor and Television set of the 1990’s ensuring backwards compatibility.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;gamma-transfer-function&quot;&gt;Gamma (Transfer Function)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The proposal provides a a bridged target of gamma suitable for most devices and breaks up the requirement into various subsets.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Viewing Gamma -&lt;/strong&gt; Computed Gamma we want to obtain
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;Viewing Gamma&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;Camera Gamma&lt;/mtext&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mtext&gt;Display Gamma&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{Viewing Gamma} = \text{Camera Gamma} * \text{Display Gamma}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Viewing Gamma&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Camera Gamma&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;∗&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Display Gamma&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Camera Gamma -&lt;/strong&gt; Derived characteristic from the image sensors standard transfer function.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CRT Gamma -&lt;/strong&gt; The gamma of the physical CRT (display).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LUT Gamma -&lt;/strong&gt; The gamma of the frame buffer lookup table&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display Gamma -&lt;/strong&gt; Computed downstream “display system” gamma
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;Display Gamma&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;CRT Gamma&lt;/mtext&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mtext&gt;LUT Gamma&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{Display Gamma} = \text{CRT Gamma} * \text{LUT Gamma}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Display Gamma&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;CRT Gamma&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;∗&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;LUT Gamma&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The four specific numbers the proposal settles on&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;1.125&lt;/strong&gt; - &lt;strong&gt;Target&lt;/strong&gt; Viewing Gamma (The desired boost for dim environments)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;1.956&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{1}{1.956}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1.956&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt; - Rec.709 Power Function (The mathematical behaviour of the 709 transfer function)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2.5&lt;/strong&gt; - Physical CRT Gamma (Baseline characteristic for CRT displays in the 90’s)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2.2&lt;/strong&gt; - The magic number or “New Standard” proposed as the ideal target for the &lt;strong&gt;sRGB Display Gamma&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To simplify further:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1.125 is our &lt;strong&gt;goal&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;1.956&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{1}{1.956}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1.956&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is a &lt;strong&gt;constraint&lt;/strong&gt; of Rec.709&lt;/li&gt;
&lt;li&gt;2.2 is used to &lt;strong&gt;bridge&lt;/strong&gt; our gap&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution results in the simple formula:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1.1247&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2.2&lt;/mn&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;1.956&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1.1247 = 2.2 * \frac{1}{1.956}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1.1247&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;2.2&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;∗&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1.956&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (This rounded would resolve to 1.125 our target viewing gamma)&lt;/p&gt;
&lt;p&gt;The reasoning behind 1.125 is clearly laid out in the proposal and well beyond the scope of what we are discussing here, in simpler terms they understood the colour space would be used in a multitude of environments which still required images to look correct and not washed out.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;definition&quot;&gt;Definition&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The final piece I will touch on at a high level is definition. The key components that were defined as &lt;strong&gt;&lt;em&gt;standard&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Standard Observer:&lt;/strong&gt; While based on the &lt;strong&gt;CIE 1931 Standard Observer&lt;/strong&gt;, the sRGB proposal specifically optimised for the “average” human’s response to the phosphors of a CRT monitor. It effectively turned a biological variable into a mathematical constant.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reference Viewing Environment:&lt;/strong&gt; This defined the “room” the observer is in, assuming a dimly lit office and a specific &lt;strong&gt;D50&lt;/strong&gt; ambient white point. This is why the &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1.125&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1.125&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1.125&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; viewing gamma was necessary (to compensate for the “darker” office surroundings).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The sRGB Gamut:&lt;/strong&gt; This is the “triangle” of colours within the CIE 1931 space. Any colour falling outside this triangle is considered “out of gamut” for sRGB and must be re-mapped.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Render Intent:&lt;/strong&gt; The inclusion of &lt;code dir=&quot;auto&quot;&gt;render-intent&lt;/code&gt; was a forward-thinking attempt to handle those “out of gamut” colours. It instructed the browser on how to squeeze a wide-gamut image (like a professional photograph) into the smaller sRGB space without losing detail in the highlights or shadows.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;some-cube-code&quot;&gt;Some Cube Code&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;RGB Cube&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;375&quot; src=&quot;https://www.asbedb.dev/_astro/rgb-cube.A7qIzfgQ_2fnLOz.webp&quot; srcset=&quot;&quot;&gt;
To visualise the sRGB transformation think of a cube (see above) and now in code (below):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;points&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; r &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; r &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; g &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; g &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; g &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; b &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; b &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;points.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(r, g, b)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Mapping in increments of &lt;code dir=&quot;auto&quot;&gt;0.1&lt;/code&gt; an &lt;code dir=&quot;auto&quot;&gt;11x11x11&lt;/code&gt; cube which would equate to 1331 unique combinations. Whilst this works for a cube with a single factor of consideration, It is not taking into account the nature of our above pictured cube having corners starting at Red, Green, Blue, White, Magenta and Black.&lt;/p&gt;
&lt;p&gt;True sRGB works in 8-bit space providing over 16.7 million unique combinations and takes into account the tracking of index in relation to each other.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;16&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;777&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;216&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;256×256×256=256^{3}=16,777,216&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;256&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;256&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;256&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;777&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;216&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;(don’t run the below code it generates over 50 million entries)&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;points&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;steps&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; r_i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; r_i &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; steps; r_i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; r_i &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; steps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; g_i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; g_i &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; steps; g_i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; g_i &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; steps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; b_i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; b_i &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; steps; b_i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; b_i &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; steps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;points.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(r, g, b)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above “cube code” with the additional parameter in mind, return coordinates to the value of &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;256^{3}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The axis of the cube is represented as such:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;X-axis = Red (R)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Y-axis = Green (G)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Z-axis = Blue (B)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Charting the colour cube is as simple as plugging in our coordinates and setting sail - see some example coordinates below:&lt;/p&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Coordinate (x,y,z)&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Resulting Color&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(0, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Black&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The Origin (No light)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(1, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Red&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Max Red, no Green or Blue&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(0, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Green&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Max Green, no Red or Blue&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(0, 0, 1)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Blue&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Max Blue, no Red or Green&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(1, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Yellow&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Red + Green (Additive)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(0, 1, 1)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Cyan&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Green + Blue (Additive)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(1, 0, 1)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Magenta&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Red + Blue (Additive)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(1, 1, 1)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;White (D65)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;All primaries at max&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;An important distinction I needed to wrap my head around:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;The mapping of the colour space (setting the coordinates) is linear, the issue is the adjustment of colour.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Remember all that stuff about gamma? Now that the coordinates are mapped I found that the relationship between coordinates and gamma to be &lt;em&gt;non-linear&lt;/em&gt;. This was the main reason why the sRGB transformation was not suitable for my computed colour scheme exercise (I’ll show a visual example shortly).&lt;/p&gt;
&lt;p&gt;When you adjust only the Red, Green or Blue sliders on an sRGB colour picker the results do not necessarily meet expectation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Side note: There is so much more to explore around gamma specifically, maybe another time.&lt;/em&gt;&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;vector-manipulation&quot;&gt;Vector Manipulation&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;If it wasn’t already implied the combination of vectors in an additive fashion allow for us to come up with a colour. As an example adding &lt;strong&gt;Pure Red&lt;/strong&gt; and &lt;strong&gt;Pure Green&lt;/strong&gt; should give us &lt;strong&gt;Yellow&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[1,0,0] + [0,1,0] = [1,1,0]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As it was aptly put by Troy from &lt;a href=&quot;https://hg2dc.com/2019/03/23/question-1/&quot;&gt;hg2dc&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What the F$%k Happens When We Change an RGB Slider Value?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You are increasing or decreasing the emission intensity of one of the three RGB lights&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The transformation lends itself to great precision providing a very large number of combinations, however, the intuitive expectations become difficult to meet.&lt;/p&gt;
&lt;p&gt;As an example let’s take &lt;strong&gt;Red&lt;/strong&gt; &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[1,0,0]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; If we wanted to make this a “Deeper Red” programmatically we would need to have either reviewed and memorised the coordinates of the red we are seeking or manipulated our RGB values and reviewed incrementally until we were happy this could land us at &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;0.9098&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0.0353&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0.0353&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[0.9098,0.0353,0.0353]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0.9098&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0.0353&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0.0353&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (a slightly darker red).&lt;/p&gt;
&lt;p&gt;Even with clamped helper values in the RGB space we would still need to manipulate our green and blue values to find the output we desire.&lt;/p&gt;
&lt;p&gt;Because of the biological quirks ([discussed earlier](#Colour is a Sensation)) — like our heightened sensitivity to Green —moving a coordinate by 0.1 on the Green axis “feels” much more dramatic than a 0.1 move on the Blue axis.&lt;/p&gt;
&lt;p&gt;This “overhead” in managing our perception and sense is why It is harder to apply a programmatic approach to computed Themes in the sRGB space. That’s why I needed to look at alternatives like HSV and HSL.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;hsv-and-hsl&quot;&gt;HSV and HSL&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;HSV and HSL comes from the desire to have a natural system in which it’s easier to adjust a colour scheme, providing more intuitive functions familiar to the standard observer (humans). The transformations are inspired from art where a base colour (hue) is picked adding white (tint), black (shade), or grey (tone/saturation).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Painters Colour Mixing Terminology&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2560&quot; height=&quot;1920&quot; src=&quot;https://www.asbedb.dev/_astro/painters-colour-mixing-terminology.DQT7HgXt_Zn1oXL.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/HSL_and_HSV&quot;&gt;Wikipedia Article on HSV and HSL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;sRGB is hardware-focussed valuing precision, where as HSL/HSV accommodates human intuition. The transformations for HSL/HSV are implemented by mapping cartesian RGB values into a &lt;a href=&quot;https://en.wikipedia.org/wiki/Cylindrical_coordinate_system&quot;&gt;cylindrical co-ordinate system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To apply the transformation (assuming RGB values are normalized to the range &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[0,1]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) a pre-calculation determines the peak and floor of each RGB triplet with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M = max(R,G,B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m = min(R,G,B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C = M - m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;−&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (This is the &lt;strong&gt;Chroma&lt;/strong&gt; , or the distance from the neutral grey axis)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We use the above values in both Value and Saturation so it’s important to remember them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;HSL and HSV Side By Side&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;490&quot; height=&quot;548&quot; src=&quot;https://www.asbedb.dev/_astro/rgb-hsv-visual.DPmvPcKq_Z22BAiu.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/HSL_and_HSV&quot;&gt;Wikipedia Article on HSV and HSL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Visualising the cylinder with a colour space mapped to it (like below) - HSL and HSV provide a transformation option where specific choices for Lightness (or Brightness in the case of HSV), Hue and Saturation become special cases, unified by adjustable parameters - also known as a parametric framework.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;HSL and HSV Side By Side&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;1280&quot; src=&quot;https://www.asbedb.dev/_astro/hsl-hsv-sbs.CLTsaHKV_aazys.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/HSL_and_HSV&quot;&gt;Wikipedia Article on HSV and HSL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I will try to summarise Hue, Saturation and Value (or lightness/intensity) in its transformative context. I did note through a lot of my readings that definition for these terms is going to have variance based on context - so keep that in mind when exploring other areas.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;hue&quot;&gt;Hue&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;TLDR: Hue is an angle on our unwrapped colour cylinder normalised to &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;360&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;°&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;360\degree&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;360°&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to represent a perceived colour.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;hue-angles&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2560&quot; height=&quot;557&quot; src=&quot;https://www.asbedb.dev/_astro/hue-angles.Dzyh2AMJ_1WAaay.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/Hue&quot;&gt;Wikipedia Article on Hue&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I came to find this particular definition from &lt;a href=&quot;https://books.google.com.au/books/about/Color_Appearance_Models.html?id=8_TxzK2B-5MC&quot;&gt;Color Appearance Models by Mark D. Fairchild&lt;/a&gt; as a great starting point for my understanding of hue.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hue - Attribute of a visual sensation according to which an area appears to be similar to one of the perceived colors; red, yellow, green and blue or to a combination of two of them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In a HSV/HSL model both hue and chroma are parameters which when applied navigate our coordinates with different effect.&lt;/p&gt;
&lt;p&gt;To have a reference for hue first the RGB cube tilted with the black vertex on the bottom is projected to a hexagonal shape.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;RBG Projected Hue Plane&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;587&quot; height=&quot;553&quot; src=&quot;https://www.asbedb.dev/_astro/rgb-projected.BarYRPwq_bqyai.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Each projected vertex which constitutes points between edges in our hexagon become the anchor vectors with the definition of hue being roughly the angle of the vector to a point in the projection, with red at 0°&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Projected to Vector&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2560&quot; height=&quot;1108&quot; src=&quot;https://www.asbedb.dev/_astro/projected-to-vector.CsgEicue_1wA3DO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As such Hue is the angular component and is typically measured in degrees. As an example from the above image a yellow hue would sit at roughly &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;60&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;°&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;60\degree&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;60°&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; - if H is less then 0 then it would add &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;360&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;°&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;360\degree&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;360°&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to normalise it.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;saturation&quot;&gt;Saturation&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;TLDR: In HSV saturation is simply the chroma &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; divide by the maximum value &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Saturation&lt;/em&gt; is the “colourfulness of an area judged in proportion to its brightness” (17-1136)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Source &lt;a href=&quot;https://munsell.com/color-blog/difference-chroma-saturation/&quot;&gt;The Difference Between Chroma and Saturation&lt;/a&gt;*&lt;/p&gt;
&lt;p&gt;The math behind the generalised saturation functions is certainly a little above my paygrade however I will try to keep it simple.&lt;/p&gt;
&lt;p&gt;Saturation is traditionally calculated at the length of a vector &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L(c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (calculation varied based on weightings - see lightness below) divided by the length of the extension of this vector to the surface of the RGB cube. Dependant on the brightness function creating a parametric system which allows us to keep a &lt;em&gt;conic&lt;/em&gt; or &lt;em&gt;bi-conic&lt;/em&gt; form of transformation space, intimately utilises brightness functions and takes into account specific co-ordinates on the brightness slope. Those poitns are then used in a calculation to divide our length accordingly.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;brightness-or-lightness-value-ft-intensity&quot;&gt;Brightness or Lightness Value (ft. Intensity)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;TLDR: In HSV = Value = Max of RGB Triplet - the below gives more detail and insight and can be skipped if it’s not of interest.&lt;/p&gt;
&lt;p&gt;HSL, HSV and HSI all use a form of luminous intensity ( &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L(c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; ) as a subjective measure of brightness - this is derived from the &lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S1049965283710199&quot;&gt;Generalized Lightness Hue and Saturation (GLHS) colour model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The equation below provides insight into how the brightness is calculated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Assuming c as a colour &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[R, G, B]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; value.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{min}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;min&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{mid}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;mi&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{max}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; as user set weights (generally 0 or 1)&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;min(c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; represents the minimum value amongst the &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[R, G, B]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; values&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid(c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;mi&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; represents the median of the &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[R, G, B]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; values&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;max(c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; represents the maximum value amongst the &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[R, G, B]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Finally a few constraints - &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;&gt;&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{max} &gt; 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;and &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1.&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{min} + w_{mid} + w_{max} = 1.&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;min&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;mi&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;⋅&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;⋅&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;⋅&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L (c) = w_{min} · min (c) + w_{mid} · mid (c) + w_{max} · max (c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;min&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;⋅&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;mi&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;⋅&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;mi&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;⋅&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Specific values of the weights give the brightness functions used by the common cylindrical colour spaces:&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model&lt;/th&gt;&lt;th&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{min}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;min&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; , &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{mid}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;mi&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;,&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;w_{max}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Resulting Formula&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;HSV&lt;/td&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0 , 0, 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Value determined by strongest colour component&lt;/td&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L = max(c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HSL&lt;/td&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mfrac&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{1}{2} , 0 , \frac{1}{2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Lightness is the average of the most and least saturated components&lt;/td&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L = \frac{min(c) + max(c)}{2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HSI&lt;/td&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mfrac&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mfrac&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mfrac&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{1}{3}, \frac{1}{3}, \frac{1}{3}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Intensity is the true average of all three RGB components.&lt;/td&gt;&lt;td&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L = \frac{R+G+B}{3}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;G&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;why-hsv&quot;&gt;Why HSV?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;So now that the RGB space is clearly laid out, we need to consider colour matching in a very basic sense, if my theme engine was to take some seed colours for Primary, Secondary, Tertiary and Neutral how do I expand this system with multiple derivative shades in a formulaic fashion.&lt;/p&gt;
&lt;p&gt;Lets take hex code &lt;code dir=&quot;auto&quot;&gt;#4287f5&lt;/code&gt; as our seed colour - RGB &lt;code dir=&quot;auto&quot;&gt;66, 135, 245&lt;/code&gt;
&lt;img alt=&quot;Seed Blue&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;233&quot; height=&quot;266&quot; src=&quot;https://www.asbedb.dev/_astro/seed-blue.BMRL1eOG_38pXx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;And here is a subjectively lighter shade of blue &lt;code dir=&quot;auto&quot;&gt;#7cadfc&lt;/code&gt; - RGB &lt;code dir=&quot;auto&quot;&gt;124, 173, 252&lt;/code&gt;
&lt;img alt=&quot;lighter Blue&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;234&quot; height=&quot;281&quot; src=&quot;https://www.asbedb.dev/_astro/lighter-blue.CPYC3zAf_2h3dtU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As the nature of travelling between colours (adjusting gamma) in sRGB is non linear there is no defined step change across all three vectors that will yield a consistent results. If we were to take the above logic then a stepped change of &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;58&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;11&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;7&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[+58, -11, +7]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;58&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;−&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; across our vectors should have a similar result on a green colour. Lets try it!&lt;/p&gt;
&lt;p&gt;Here is our green seed hex &lt;code dir=&quot;auto&quot;&gt;#30d42a&lt;/code&gt; - RGB &lt;code dir=&quot;auto&quot;&gt;48, 212, 42&lt;/code&gt;
&lt;img alt=&quot;Seed Green&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;232&quot; height=&quot;259&quot; src=&quot;https://www.asbedb.dev/_astro/seed-green.CjtmcM1f_2d3vRX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here if we apply the same modifiers to our RGB coordinates we map to RGB &lt;code dir=&quot;auto&quot;&gt;106, 201, 49&lt;/code&gt; which results in hex &lt;code dir=&quot;auto&quot;&gt;#6ac931&lt;/code&gt; In comparison to our blue shade variant the green looks washed out and “not quite right”.
&lt;img alt=&quot;Modified Green&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;236&quot; height=&quot;272&quot; src=&quot;https://www.asbedb.dev/_astro/modified-green.CcBslz16_Z82B8T.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;You may also notice that the green variation feels different compared to blue. This is because the standard observer (human being) has an uneven sensitivity across the spectrum: we are most sensitive to changes in &lt;strong&gt;Green&lt;/strong&gt;, followed by &lt;strong&gt;Red&lt;/strong&gt;, and least sensitive to &lt;strong&gt;Blue&lt;/strong&gt;. This is why a fixed mathematical shift in RGB results in wildly different perceptual shifts depending on the starting colour.&lt;/p&gt;
&lt;p&gt;To demonstrate this point I will pick two seed colours and apply the same step change of &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;58&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;11&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;7&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[+58, -11, +7]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;58&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;−&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; four times and put them side by side for comparison. (The top is the seed colour picked at random).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Comparison of Palettes&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;520&quot; height=&quot;573&quot; src=&quot;https://www.asbedb.dev/_astro/palette-transform.BZ6Wsl3t_ZnueX4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The results tend to feel washed out, and the uniform intuitive option will not resonate across a swatch.&lt;/p&gt;
&lt;p&gt;Now let’s apply the same exercise in the HSV space. First and foremost we are not going to play with Hue or Saturation only Value (Brightness Factor!).&lt;/p&gt;
&lt;p&gt;Now one thing I didn’t mention is this project is being done in Java (sorry in advance) so the code here is going to be a bit verbose but should be easy to follow:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ColorShade&lt;/span&gt;&lt;span&gt;(String name, String hex, Color color) {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; List&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;ColorShade&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;generateShades&lt;/span&gt;&lt;span&gt;(String baseColorName, String hexColor) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Color baseColor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Color.&lt;/span&gt;&lt;span&gt;web&lt;/span&gt;&lt;span&gt;(hexColor);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;List&amp;#x3C;&lt;/span&gt;&lt;span&gt;ColorShade&lt;/span&gt;&lt;span&gt;&gt; palette &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; ArrayList&amp;#x3C;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt;[] brightnessFactors &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt;1.5&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1.2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1.0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0.8&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0.5&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] labels &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt;&quot;100&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;300&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;500&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;700&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;900&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; brightnessFactors.length; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Color shadeColor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; baseColor.&lt;/span&gt;&lt;span&gt;deriveColor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1.0&lt;/span&gt;&lt;span&gt;, brightnessFactors[i], &lt;/span&gt;&lt;span&gt;1.0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;String shadeName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; baseColorName &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;-&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; labels[i];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ColorShade shadeToAppend &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ColorShade&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;shadeName,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;toHexString&lt;/span&gt;&lt;span&gt;(shadeColor),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;shadeColor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;palette.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(shadeToAppend);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; palette;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;By applying a standardised multiplier to our base colours brightness we get some interesting results! lets take our colours we used in our sRGB approach and apply the same multipliers:&lt;/p&gt;
&lt;p&gt;Lets take our original purple hex &lt;code dir=&quot;auto&quot;&gt;#FF1BB4&lt;/code&gt; in our function the 1.0 or “500” shade is considered the centre and the results show a noticeable difference.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Purple Base Transformed&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;579&quot; src=&quot;https://www.asbedb.dev/_astro/hsb-figma-applied.CMycZHgi_Z2wJdON.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;and now the same with the &lt;code dir=&quot;auto&quot;&gt;#FF714E&lt;/code&gt; coral orange.
&lt;img alt=&quot;Orange Base Transformed&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;813&quot; height=&quot;579&quot; src=&quot;https://www.asbedb.dev/_astro/hsb-figma-orange.B8XopDOA_PyTh2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The immediate uniformity in shade application and the effect of having a parameter that gives us consistent results becomes apparent!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This was a really long way of saying if you want to automate theming a parametric system like HSV/HSL or HSI and now the new standards in CSS like &lt;a href=&quot;https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl&quot;&gt;OKCLH&lt;/a&gt; (which supports a wider gamut of colours in the p3 space) are going to allow for you to have consistent automated results.&lt;/p&gt;
&lt;p&gt;Until next time!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;reading-sources&quot;&gt;Reading Sources&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://books.google.com.au/books/about/Color_Appearance_Models.html?id=8_TxzK2B-5MC&quot;&gt;Color Appearance Models - Mark D. Fairchild&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S1049965283710199&quot;&gt;GLHS: A Generalized Lightness, Hue, and Saturation Color Model Levkowitz H. Herman G.T.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.researchgate.net/publication/228977873_The_taming_of_the_hue_saturation_and_brightness_colour_space&quot;&gt;The taming of the hue, saturation and brightness colour space - Alan Hanbury&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/&quot;&gt;Color Management - Chris Brejon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65a&quot;&gt;Beginners Guide to Colorimetry - Chandler Abraham&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hg2dc.com/&quot;&gt;Hitchhikers Guide to Digital Colour&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pantone.com/articles/color-fundamentals/how-do-we-see-color&quot;&gt;How do we see color? - Pantone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://files.cie.co.at/CIE_Brochure_July_2022.pdf&quot;&gt;CIE Informational Brochure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/Graphics/Color/sRGB.html&quot;&gt;A Standard Default Color Space for the Internet - sRGB - Microsoft and HP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/CIE_1931_color_space&quot;&gt;CIE 1931 Color Space - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/HSL_and_HSV&quot;&gt;HSV and HSL - Wikipedia&lt;/a&gt;*&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aao.org/eye-health/anatomy/photoreceptors&quot;&gt;Photoreceptors - American Academy of Ophthalmology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://munsell.com/color-blog/difference-chroma-saturation/&quot;&gt;Difference Between Chroma &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.figma.com/color-palette-generator/&quot;&gt;Figma Colour Palette Generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>CompSci</category></item><item><title>sudo apt-get it on an old Pixel 3xl</title><link>https://www.asbedb.dev/musings/smort-phone/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/smort-phone/</guid><description>This is a high level guide on some fun I had with an old Google Pixel 3xl with the following goals in mind.

</description><pubDate>Mon, 08 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;tldr&quot;&gt;TLDR&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This is a high level guide on some fun I had with an old Google Pixel 3xl with the following goals in mind.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;De-google and run a Linux distro&lt;/li&gt;
&lt;li&gt;Glorious SSH&lt;/li&gt;
&lt;li&gt;Install and run a developer environment&lt;/li&gt;
&lt;li&gt;Potentially host and access services from another device through incoming connections&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want to skip the why, and learn more about the how, feel free to go straight to &lt;a href=&quot;#lineageos&quot;&gt;LineageOS&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;lets-go&quot;&gt;Lets go!&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We recently hit spring (supposedly) which means its that time of the year to clean out the tech closets. After a lifetime of advocating to reduce “tech debt”, I always find it funny opening my closet to find decades of technology just sitting there dormant. Like warriors of past the closet doubles as hall of fallen heroes, each with it’s own tale of conquest and heroism from a simpler time.&lt;/p&gt;
&lt;p&gt;So as one does, I come back to clean this space every few months and each time a new seemingly simple, but usually complicated, idea pops into my mind. Things like &lt;strong&gt;&lt;em&gt;“I wonder if I can run RAID across 5 old laptop hard drives?”&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;“I should build a cyberdeck out of all these extra parts”&lt;/em&gt;&lt;/strong&gt;. To be fair, one of these ideas resulted in installing Arch on an old ThinkPad - a decision I am extremely happy with. (I use Arch btw).&lt;/p&gt;
&lt;p&gt;So this time when the cogs started to turn there were two things in the back of my mind that really helped speed things along.&lt;/p&gt;
&lt;p&gt;The first was the concept of ownership as opposed to being a hostage. Whilst this isn’t a piece dedicated to that, and many before me have done it justice the crux of it came down to.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Right to repair&lt;/li&gt;
&lt;li&gt;Freedom to modify for personal use&lt;/li&gt;
&lt;li&gt;Unrestricted access to features&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The second came from an odd place.&lt;/p&gt;
&lt;p&gt;Long time content creator recently turned 10x engineer PewDiePie has gone on an interesting journey building fun projects and solving tech problems. He has, probably like me, opened the tech closet and gazed upon the titans of past thinking of giving them purpose once more. One project that stood out was &lt;a href=&quot;https://youtu.be/u_Lxkt50xOg?si=y5hEvKN6EC8RKpFT&quot;&gt;self hosting using a Steam deck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So with an optimistic glimmer in my eye and my gaze affixed on a retired Google Pixel 3xl from 2018, I set forth to conquer what I thought would be a few simple milestones.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;De-google and run a Linux distro on my Pixel 3xl&lt;/li&gt;
&lt;li&gt;Glorious SSH&lt;/li&gt;
&lt;li&gt;Install and run a developer environment&lt;/li&gt;
&lt;li&gt;Potentially host and access services from another device through incoming connections&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;lineageos&quot;&gt;LineageOS&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The first step was to “unshackled the Google from Google” a task that was surprisingly accessible. I know its easy to pick at issues with big tech companies - but for what its worth, at least there’s a way to do this with relative ease.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;lineage-loading&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;797&quot; src=&quot;https://www.asbedb.dev/_astro/lineage-loading.BtvcjJy-_1PrfBb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I thoroughly enjoyed this process because it was reminiscent of installing an operating system back in the “good old days”. A time where taking careful note of hardware compatibility and kernels could be the difference between a short simple process or hours of troubleshooting.&lt;/p&gt;
&lt;p&gt;So after some research I found there weren’t many choices for my relic and the best suited one would be &lt;a href=&quot;https://lineageos.org/&quot;&gt;LineageOS&lt;/a&gt; an android distribution that has an impressive amount of &lt;a href=&quot;https://wiki.lineageos.org/devices/&quot;&gt;devices&lt;/a&gt; it supports.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;lineage-loaded&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;797&quot; src=&quot;https://www.asbedb.dev/_astro/lineage-loaded.DyvZPpaI_1vpFT0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This isn’t going to be a step by step guide on how to install &lt;code dir=&quot;auto&quot;&gt;LineageOS&lt;/code&gt; as the documentation does a good job in explaining the process there are however key things when tinkering with an android phone that were critical to installing &lt;code dir=&quot;auto&quot;&gt;LineageOS&lt;/code&gt; and subsequently rooting the phone. These being Android Developer Options, Android Debug Bridge (&lt;code dir=&quot;auto&quot;&gt;adb&lt;/code&gt;) and &lt;code dir=&quot;auto&quot;&gt;Fastboot&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;android-developer-options&quot;&gt;Android Developer Options&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To access and run debugging via a USB Cable the phone required Android developer options enabled. To enable this&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to the phones &lt;code dir=&quot;auto&quot;&gt;Settings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Press&lt;code dir=&quot;auto&quot;&gt;About Phone&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tap the &lt;code dir=&quot;auto&quot;&gt;Build Number&lt;/code&gt; seven times&lt;/li&gt;
&lt;li&gt;Enter your pin or password if prompted.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can then find the &lt;code dir=&quot;auto&quot;&gt;Developer Options&lt;/code&gt; menu in your main settings, often under &lt;code dir=&quot;auto&quot;&gt;System&lt;/code&gt;. This menu will be crucial to enabling &lt;code dir=&quot;auto&quot;&gt;USB Debugging&lt;/code&gt; which will be used through out the process.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;android-debug-bridge-adb-and-fastboot&quot;&gt;Android Debug Bridge (ADB) and Fastboot&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;As part of installing LineageOS the process will require you to reboot into a bootloader by using a command line interface. ADB is a command line tool which allows you to communicate with the device and perform a number of privileged actions after enabling developer access.&lt;/p&gt;
&lt;p&gt;If you have used Android Studio or an Android SDK chances are you already have &lt;code dir=&quot;auto&quot;&gt;adb&lt;/code&gt; installed to check this you can run the command in your preferred command line interface. The communication between PC and Phone is usually done over a USB cable, but Wi-Fi connections are also supported.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;adb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Using &lt;code dir=&quot;auto&quot;&gt;fastboot&lt;/code&gt; (if your device supports it) should simply involve rebooting to fastboot mode. While in fastboot mode, you can type &lt;code dir=&quot;auto&quot;&gt;fastboot devices&lt;/code&gt; to verify that your device is being detected&lt;/p&gt;
&lt;p&gt;To run &lt;code dir=&quot;auto&quot;&gt;adb&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;fastboot&lt;/code&gt; you will need to consider your OS and &lt;a href=&quot;https://wiki.lineageos.org/adb_fastboot_guide#installing-adb-and-fastboot&quot;&gt;follow the instructions here&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;su-magisk&quot;&gt;Su (magisk)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Even after installing &lt;code dir=&quot;auto&quot;&gt;LineageOS&lt;/code&gt; there still will be an issue when trying to run processes or commands requiring elevated privileges. Simply put without rooting the device the &lt;code dir=&quot;auto&quot;&gt;su&lt;/code&gt; command is non existent. To do this you &lt;a href=&quot;https://topjohnwu.github.io/Magisk/install.html&quot;&gt;can follow along here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The shortened guide below.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/topjohnwu/Magisk/releases/latest&quot;&gt;Download and install the Magisk&lt;/a&gt; mobile app&lt;/li&gt;
&lt;li&gt;Within the app get a copy of &lt;strong&gt;one&lt;/strong&gt; of the following images &lt;code dir=&quot;auto&quot;&gt;boot.img&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;init_boot.img&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;recovery.img&lt;/code&gt;. (If you don’t see either of these see the detailed instruction linked in the first paragraph for more details).&lt;/li&gt;
&lt;li&gt;Copy the &lt;code dir=&quot;auto&quot;&gt;boot/init_boot/&amp;#x3C;recovery_image.img&gt;&lt;/code&gt; to your phone&lt;/li&gt;
&lt;li&gt;Press &lt;code dir=&quot;auto&quot;&gt;install&lt;/code&gt; in the &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;Magisk&lt;/code&gt;&lt;/strong&gt; section (not the app section).&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Select and Patch a File&lt;/strong&gt; followed by your recovery image.&lt;/li&gt;
&lt;li&gt;Once installation is done copy your new &lt;code dir=&quot;auto&quot;&gt;img&lt;/code&gt; file via &lt;code dir=&quot;auto&quot;&gt;adb&lt;/code&gt;. (Your device might have a different folder structure instead of &lt;code dir=&quot;auto&quot;&gt;sdcard&lt;/code&gt;) &lt;strong&gt;Warning&lt;/strong&gt;: &lt;em&gt;Never download and use a random &lt;code dir=&quot;auto&quot;&gt;img&lt;/code&gt; file online - always patch your own file to avoid any security or configuration issues.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;adb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/sdcard/Download/magisk_patched_[random_strings].img&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;your_pc_directory&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# You can use the . symbol to download into the same directory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;Reboot phone into recovery mode using &lt;code dir=&quot;auto&quot;&gt;adb -d reboot bootloader&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code dir=&quot;auto&quot;&gt;fastboot&lt;/code&gt; and point your device to your new image (take note of boot type based on your &lt;code dir=&quot;auto&quot;&gt;img&lt;/code&gt; file type) and then turn on your phone.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fastboot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/magisk_patched_[random_strings].img&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# OR&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fastboot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;init_boot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/magisk_patched_[random_strings].img&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# OR&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fastboot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;recovery&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/magisk_patched_[random_strings].img`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol start=&quot;9&quot;&gt;
&lt;li&gt;Launch the &lt;code dir=&quot;auto&quot;&gt;Magisk&lt;/code&gt; app and select &lt;code dir=&quot;auto&quot;&gt;Direct Install&lt;/code&gt; followed by another reboot&lt;/li&gt;
&lt;li&gt;The phone should now be rooted successfully.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;magisk-superusers&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;797&quot; src=&quot;https://www.asbedb.dev/_astro/magisk-superusers.ChE0N3xj_cwiDv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;f-droid-and-termux&quot;&gt;F-Droid and Termux&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now that we have a free and opensource operating system we also need a catalogue of free and opensource applications available for the android platform, and that’s exactly what &lt;a href=&quot;https://f-droid.org/en/&quot;&gt;F-Droid&lt;/a&gt; does. Installation of F-Droid is fairly simple you navigate to the main page on the phone hit the big download button and install via the APK.&lt;/p&gt;
&lt;p&gt;Going back to our goal of SSH and emulating Linux the first step was to ensure we had a terminal we could play with. I decided to go with &lt;a href=&quot;https://f-droid.org/en/packages/com.termux/&quot;&gt;Termux&lt;/a&gt; as it provides an extensive Linux package collection. Heck you could even compile code with &lt;code dir=&quot;auto&quot;&gt;gcc&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;clang&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;f-droid&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;797&quot; src=&quot;https://www.asbedb.dev/_astro/f-droid.DPbz9Q8Z_2Iwaa.webp&quot; srcset=&quot;&quot;&gt;
Now the old Pixel 3XL not only is running a brand new de-Googled OS but it also has a nice terminal emulator waiting for root access. All that’s left is to ensure we allow for &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; to have said access as a super user.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;run the &lt;code dir=&quot;auto&quot;&gt;su&lt;/code&gt; command (inside &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; on the phone)&lt;/li&gt;
&lt;li&gt;Grant access via &lt;code dir=&quot;auto&quot;&gt;Magisk&lt;/code&gt; app (approve prompts on your phone)&lt;/li&gt;
&lt;li&gt;execute the &lt;code dir=&quot;auto&quot;&gt;adb shell&lt;/code&gt; on your PC - whilst the phone is plugged into your pc (this is akin to having a direct wired connection to your terminal)&lt;/li&gt;
&lt;li&gt;type in &lt;code dir=&quot;auto&quot;&gt;su&lt;/code&gt; within the &lt;code dir=&quot;auto&quot;&gt;adb shell&lt;/code&gt; terminal on your pc and then &lt;strong&gt;approve/verify&lt;/strong&gt; the access &lt;strong&gt;on the phone.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;termux&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;797&quot; src=&quot;https://www.asbedb.dev/_astro/termux.DxNK1ko1_Z1zGl75.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;glorious-ssh&quot;&gt;Glorious SSH&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Alas, the last step is to provide remote SSH access (at this stage via local network). Now that we have an elevated terminal and can technically access it straight from our PC via a USB cable it becomes no different to a regular Linux process! You can elect to do this via &lt;code dir=&quot;auto&quot;&gt;adb shell&lt;/code&gt; or directly on the phone via Termux&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; / or &lt;code dir=&quot;auto&quot;&gt;adb shell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run the command &lt;code dir=&quot;auto&quot;&gt;pkg upgrade &amp;#x26;&amp;#x26; pkg update&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run the command &lt;code dir=&quot;auto&quot;&gt;pkg install openssh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set a SSH password using the &lt;code dir=&quot;auto&quot;&gt;passwd&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;Run the &lt;code dir=&quot;auto&quot;&gt;sshd&lt;/code&gt; command to start the SSH daemon&lt;/li&gt;
&lt;li&gt;Check your phones local IP address using the &lt;code dir=&quot;auto&quot;&gt;ifconfig&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;Check your terminal username using the &lt;code dir=&quot;auto&quot;&gt;whoami&lt;/code&gt; command (this needs to be done on &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; directly on the phone)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(Optional but recommended) With this setup if the device goes to sleep it will automatically sever the SSH connection - you can stop this behaviour by running the command &lt;code dir=&quot;auto&quot;&gt;termux-wake-lock&lt;/code&gt; in &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; on the phone.&lt;/p&gt;
&lt;p&gt;This stops your device from going into “deep sleep” ensuring access even if the screen is “asleep”.&lt;/p&gt;
&lt;p&gt;So by now you should have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Phones Local IP&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; Username&lt;/li&gt;
&lt;li&gt;SSH Password&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The final check is ensuring you can SSH into the phone to do this open up your favourite CLI which can of course provide you with glorious SSH and type in the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ssh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8022&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;username&gt;@&amp;#x3C;phone_IP_Address&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If everything has been done correctly you should be greeted with something similar to the below image:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ssh-terminal-screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;601&quot; height=&quot;540&quot; src=&quot;https://www.asbedb.dev/_astro/ssh-terminal-screenshot.DwH1GX-F_3Hjsu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;proot-distro&quot;&gt;proot-distro&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt; provides a package called &lt;a href=&quot;https://github.com/termux/proot-distro&quot;&gt;proot-distro&lt;/a&gt; which takes care of managing Linux distributions inside &lt;code dir=&quot;auto&quot;&gt;Termux&lt;/code&gt;. You can install this utility by executing.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pkg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;proot-distro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;By using &lt;code dir=&quot;auto&quot;&gt;proot&lt;/code&gt; we open the device up to so much more fun! In my example I went with ubuntu - this was as simple as executing the following commands:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;proot-distro&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ubuntu&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;proot-distro&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;login&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ubuntu&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Proot supports the following distros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Alpine Linux (edge)&lt;/li&gt;
&lt;li&gt;Arch Linux / Arch Linux 32 / Arch Linux ARM&lt;/li&gt;
&lt;li&gt;Debian (stable)&lt;/li&gt;
&lt;li&gt;Fedora 35&lt;/li&gt;
&lt;li&gt;Manjaro AArch64&lt;/li&gt;
&lt;li&gt;OpenSUSE (Tumbleweed)&lt;/li&gt;
&lt;li&gt;Ubuntu (22.04)&lt;/li&gt;
&lt;li&gt;Void Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;hey-look-my-phone-now-runs-a-dev-environment&quot;&gt;hey look, my phone now runs a dev environment&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;So this was my last goal really, could I run a node server and access it on my local network. Sadly I was able to only get it half done.&lt;/p&gt;
&lt;p&gt;There were a few reasons for this but let me start by providing a quick overview on the Node and NPM experience .I took a bit of a different route to get it running because we needed to ensure all the binaries were available a luxury that you overlook when using a desktop OS.&lt;/p&gt;
&lt;p&gt;Below you will find the commands in order, I also opted to use Node Version Manager (NVM) to make it easier to manage multiple node packages in the future.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; &amp;#x26;&amp;#x26; &lt;/span&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upgrade&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nodejs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build-essential&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.bashrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--lts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--lts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Magic&lt;/em&gt;
&lt;img alt=&quot;node-screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;432&quot; height=&quot;105&quot; src=&quot;https://www.asbedb.dev/_astro/node-screenshot.KNTc9j38_1GHbYJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;With what I have just demonstrated you can imagine the amount of possibilities that open up, I have seen people turn old phones into a bunch of things including a mobile pen testing tool running Kali Linux.&lt;/p&gt;
&lt;p&gt;Here’s an Astro site running locally as an example:
&lt;img alt=&quot;astro-cli&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;532&quot; height=&quot;397&quot; src=&quot;https://www.asbedb.dev/_astro/astro-cli.Dn-t_d8I_TuaoF.webp&quot; srcset=&quot;&quot;&gt;
&lt;img alt=&quot;astro-local&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;797&quot; src=&quot;https://www.asbedb.dev/_astro/astro-local.CyiFySd0_1fdB2z.webp&quot; srcset=&quot;&quot;&gt;
Sadly there was one thing I didn’t account for.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;nobody-escapes-the-google&quot;&gt;Nobody escapes the Google&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;jesus-quintana&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;308&quot; height=&quot;400&quot; src=&quot;https://www.asbedb.dev/_astro/jesus-quintana.CMaQZKPs_Z21ekQO.webp&quot; srcset=&quot;&quot;&gt;
Just when I thought I was out Google pulled me right back in. Compared to it’s fruit variety the freedom is unmatched however there was still some restriction I had not accounted for. The NIC is extremely locked down in most mobile phones (for good reason!) that certainly is no different in the case of the pixel.&lt;/p&gt;
&lt;p&gt;After trying almost every option to fix the error &lt;code dir=&quot;auto&quot;&gt;A system error occurred: uv_interface_addresses returned Unknown system error 13 (Unknown system error 13)&lt;/code&gt;. I staggered off to lick my wounds - Whilst I think there still might be a way for me to beat the final challenge - perhaps it’s a tale for another day.&lt;/p&gt;
&lt;p&gt;In retrospect the issue stems from permissions as the &lt;code dir=&quot;auto&quot;&gt;libuv&lt;/code&gt; library tries to call the function &lt;code dir=&quot;auto&quot;&gt;os.networkInterfaces()&lt;/code&gt;. This function triggers an Access denied on modern Android (11+) as querying network interface details are restricted.&lt;/p&gt;
&lt;p&gt;This was a fun exercise and it has given me something to do with an otherwise dormant relic of the past. I would always recommend finding ways to give old tech a new purpose - you may even surprise yourself with the results.&lt;/p&gt;</content:encoded><category>Security</category></item><item><title>Do you even grep? Disko 1 picoCTF</title><link>https://www.asbedb.dev/musings/disko-1/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/disko-1/</guid><description>A guide to solving the Disko 1 picoCTF challenge using grep on Linux and PowerShell on Windows

</description><pubDate>Thu, 11 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;“In the Microsoft eco-system, the people are &lt;strong&gt;not&lt;/strong&gt; represented by two separate, yet equally important, groups: those who &lt;code dir=&quot;auto&quot;&gt;grep&lt;/code&gt;, investigating file content using simple commands; and those with beautiful window managers, effortlessly floating between screens rarely touching the mouse.”&lt;/p&gt;
&lt;p&gt;This all started with a CTF (Capture The Flag) challenge over at &lt;a href=&quot;https://play.picoctf.org/practice/challenge/505&quot;&gt;picoctf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For those who are interested in trying the challenge on their own.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sorry but the title of this piece might be a major clue.&lt;/li&gt;
&lt;li&gt;Stop reading this RIGHT NOW - Go try it first (and if you can be bothered) try figuring it out on windows.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the uninitiated a CTF is a technical challenge trying to find a hidden string by completing either some digital forensic examination, real vulnerability exploits (on fake and intentionally vulnerable products), and sometimes even fake social engineering. They are really fun and a good way to get the neurons firing. The skills you gain from them are practical and can make you a better technology professional.&lt;/p&gt;
&lt;p&gt;I don’t want to be one of those people but…&lt;/p&gt;
&lt;p&gt;I’ve been daily driving Linux on my laptop and every time I want to do a Linux thing on my windows machine - A little bit of me cries.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;disko-1&quot;&gt;Disko 1&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This CTF is meant to be a digital forensic exercise analysing a dump of a disk (&lt;code dir=&quot;auto&quot;&gt;dd&lt;/code&gt; File) trying to find a hidden string. So really we need to do two things.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get all the strings from the &lt;code dir=&quot;auto&quot;&gt;dd&lt;/code&gt; File&lt;/li&gt;
&lt;li&gt;Search that string to find a pattern that will match our CTF Flag.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thankfully we know what the CTF Flag looks like with this handy greyed out input box showing us what we are probably looking for.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ctf-flag&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;722&quot; height=&quot;115&quot; src=&quot;https://www.asbedb.dev/_astro/ctf_flag.DcrLnSBd_vXCQ1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;and if you are on Linux - well you can do this with one line.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;strings disko-1.dd | grep &quot;picoCTF{&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;the &lt;code dir=&quot;auto&quot;&gt;strings&lt;/code&gt; command displays all listable strings inside our &lt;code dir=&quot;auto&quot;&gt;disko-1.dd&lt;/code&gt; the pipe &lt;code dir=&quot;auto&quot;&gt;|&lt;/code&gt; redirects our output to a second command feeding the output directly into &lt;code dir=&quot;auto&quot;&gt;grep &quot;&amp;#x3C;search term&gt;&quot;&lt;/code&gt; which effectively searches our output for the search term.&lt;/p&gt;
&lt;p&gt;If you did this CTF with Linux - congrats. You did it in 5 minutes.&lt;/p&gt;
&lt;p&gt;But what about Windows?&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;is-it-winning-if-its-not-win-dows&quot;&gt;Is it winning if it’s not WIN-dows?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This really bugged me. I started this CTF in Windows. Why can’t I do it with one line in Windows. Surely its not that bad is it?&lt;/p&gt;
&lt;p&gt;The first challenge I had was dealing with a &lt;code dir=&quot;auto&quot;&gt;.dd&lt;/code&gt; file - the file size wasn’t overly large (50mb), maybe I could just open this in notepad and &lt;code dir=&quot;auto&quot;&gt;ctrl+f&lt;/code&gt; the string?&lt;/p&gt;
&lt;p&gt;Sounds silly but isn’t that what the &lt;code dir=&quot;auto&quot;&gt;grep&lt;/code&gt; command is doing in a neat little CLI anyway? That was not a good move, notepad my good friend for many years had been checkmated into a “not responding”. This of course was due to the &lt;code dir=&quot;auto&quot;&gt;strings&lt;/code&gt; command in Linux extracting all printable strings restricting our search and return to the correct type we were looking for.&lt;/p&gt;
&lt;p&gt;There’s something hallmark about that signature grey/white UI with emboldened black text and data being presented in tabular format. It screams .NET core, those who win-amped remember aero styling, those who used Visual Basic remember grey square buttons.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;osf_screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1012&quot; height=&quot;482&quot; src=&quot;https://www.asbedb.dev/_astro/osf_screenshot.DeKYbKid_ZY06jk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I say all this because the first popular choice that came up to open and display content from a &lt;code dir=&quot;auto&quot;&gt;.dd&lt;/code&gt; file was a tool from PassMark called &lt;a href=&quot;https://www.osforensics.com/tools/mount-disk-images.html&quot;&gt;OSFMount&lt;/a&gt; a software company I used in high school to prove my computer could run the &lt;a href=&quot;https://forums.whirlpool.net.au/archive/39111&quot;&gt;Age of Empires disc that came with my cereal&lt;/a&gt;. Credit where credit is due - once I had &lt;code dir=&quot;auto&quot;&gt;OSFMount&lt;/code&gt; installed and opening the &lt;code dir=&quot;auto&quot;&gt;.dd&lt;/code&gt; file I could now peak into the structure and contents of the folder. I was no closer to the one liner; however now that I had a “Folder” maybe our good friend PowerShell could come in to save the day.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;powershell-had-its-own-comic-book&quot;&gt;PowerShell had it’s own comic-book.&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I spoke about daily driving Linux earlier (I use Arch btw). I think every Linux user at one point or another has used a command similar to &lt;code dir=&quot;auto&quot;&gt;sudo apt-get&lt;/code&gt;, after slowly realising how easy it is to install update and manage packages from the command line interface (CLI) not only do these commands become second nature but the CLI itself becomes a “friendly(er)” to the user.&lt;/p&gt;
&lt;p&gt;To be fair I think most Windows users have seen Command Prompt - or so I hope. PowerShell on the other hand &lt;a href=&quot;https://learn.microsoft.com/en-us/powershell/scripting/community/digital-art?view=powershell-7.5&quot;&gt;actually needed its own brand mascot.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ps_mascot.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;847&quot; height=&quot;1137&quot; src=&quot;https://www.asbedb.dev/_astro/ps_mascot.BT3WspRV_ZoAXUU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Anyway I digress - I’ve been trying to slot in showing people the PowerShell mascot without being too obnoxious about it.&lt;/p&gt;
&lt;p&gt;So can we “&lt;code dir=&quot;auto&quot;&gt;grep&lt;/code&gt;” now? To review I have a mounted drive full of files a file path to be able to search contents of said files, granted the files are also nondescript and might have the same issues perhaps breaking down the operations to per file will yield results as my direct attempts on the &lt;code dir=&quot;auto&quot;&gt;.dd&lt;/code&gt; file had mostly failed&lt;/p&gt;
&lt;p&gt;(The direct attempts below)&lt;/p&gt;
&lt;p&gt;This one timed out&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$fileContent &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Get-Content&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;Path &lt;/span&gt;&lt;span&gt;&quot;C:\disko-1.dd&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Select-String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;InputObject $fileContent &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;Pattern &lt;/span&gt;&lt;span&gt;&quot;picoCTF&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;and this one returned something however the output was not correct&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Get-ChildItem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;Path &lt;/span&gt;&lt;span&gt;&quot;*&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Select-String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;Pattern &lt;/span&gt;&lt;span&gt;&quot;pico&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;no-child-output&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1377&quot; height=&quot;541&quot; src=&quot;https://www.asbedb.dev/_astro/no-child-output.BAtCAYQu_QIcy5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I felt the last command was close - It was at this moment I realised something - perhaps i was doing this all wrong and there was a simple way. It wasn’t going to be as pretty as a &lt;code dir=&quot;auto&quot;&gt;strings&lt;/code&gt; command but maybe - if I just passed my &lt;code dir=&quot;auto&quot;&gt;.dd&lt;/code&gt; file as a variable and piped a &lt;code dir=&quot;auto&quot;&gt;Select-String&lt;/code&gt; it would work. and so:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$fileContent &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Get-Content&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;Path &lt;/span&gt;&lt;span&gt;&quot;c:\disko-1.dd&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$fileContent &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Select-String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;picoCTF&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I couldn’t believe my eyes - after quite a long journey the answer was lying there - now formatting wasn’t nice and i got some garble with it. But we did it. we finally “won” on windows.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;picoCTF{1t5_ju5t_4_5tr1n9_be6031da}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ctf-disko-one-done&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;667&quot; height=&quot;267&quot; src=&quot;https://www.asbedb.dev/_astro/ctf-disko-1-done.DiCnDt2L_ZPFj8f.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interestingly - if you tried this command as a single lined pipe declaring the &lt;code dir=&quot;auto&quot;&gt;Get-Content&lt;/code&gt; on the left you would have a blank result.&lt;/p&gt;
&lt;p&gt;Something that if I knew early on might have stopped me exploring OSFMount - but where’s the fun in that.&lt;/p&gt;</content:encoded><category>Security</category></item><item><title>angOS- Part One</title><link>https://www.asbedb.dev/musings/angospartone/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/angospartone/</guid><description>Building a WindowsXP toy project with TypeScript

</description><pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;** Update 11/09 - Someone told me the name might be confused with another project out in the wild so updating to reflect my working title **angOS** (I just mushed angular and OS together - nothing fancy)&lt;/p&gt;
&lt;p&gt;My earliest memory of a Windows PC dates back to when I was five. The information age had started to pick up steam and Microsoft was sporting it’s latest operating system, Windows 95 - a powerhouse for business, connectivity and leisure marketed as a must-have tool for the modern family.&lt;/p&gt;
&lt;p&gt;My parents who were operating a small business and raising a young family certainly thought so and bought home the Compaq Presario 4160, a technological marvel for its time. This machine not only served me throughout most of my adolescent life, but also sparked a joy for technology that would be lifelong.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;compaq_4160&quot; title=&quot;compaq 4160 pc&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;1000&quot; src=&quot;https://www.asbedb.dev/_astro/compaq_4160.CBVwtbko_Z1LLJiQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I reference this because even at that young age, wanting to understand the ins and outs of my machine, how all the software operated was something that excited me. That’s why I recently decided to go deeper and attempt to simulate an operating system using a modern web language - these projects are often described as a webOS and are generally used to learn and grow as a developers.&lt;/p&gt;
&lt;p&gt;This project has been very rewarding for me, it has taught me a great deal on how larger teams make various decisions. For those who are at an intermediate level and looking to branch from one type of development to another (in my case it was web to Systems/OS) - this is a great way to think outside the box.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;conception&quot;&gt;Conception&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At the end of June 2025 I came across whispers that the Windows 11 Start Menu was built with &lt;a href=&quot;https://winaero.com/windows-11-start-menu-revealed-as-resource-heavy-react-native-app-sparks-performance-concerns/&quot;&gt;React Native&lt;/a&gt;. After further research, it seemed to be some casual “clickbait” that surfaced every few months and nothing of note (the Start Menu itself is &lt;a href=&quot;https://www.youtube.com/watch?v=kMJNEFHj8b8&amp;#x26;t=287s&quot;&gt;built with C++ and XAML&lt;/a&gt; with the recommendations feature using React Native). It was a nice little rabbit hole at the time however it did spark a small proof of concept.&lt;/p&gt;
&lt;p&gt;The nostalgia of older Microsoft operating systems notably 95, 98 and XP brings me joy, reminiscing about aero icons and MSN Messenger dings after school I set myself a goal of visually recreating a Windows XP desktop environment in React - not the hardest front end styling exercise but one I came to enjoy.&lt;/p&gt;
&lt;p&gt;It was around this time that my curiosity and learning topics started to mingle - I had recently started reading &lt;a href=&quot;https://www.amazon.com.au/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164&quot;&gt;Clean Architecture&lt;/a&gt; by Robert C. Martin (Uncle Bob), alongside working through some courseware from &lt;a href=&quot;https://www.coursera.org/learn/algorithms-part1&quot;&gt;Princeton around Data Structures and Algorithms.&lt;/a&gt; which was taught in Java. Putting the two together I had fully bought into the OO paradigm and was itching to practice my knowledge and theory - as I started crafting my UI design, I asked myself some fundamental questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“How does Windows get to the front end?”&lt;/li&gt;
&lt;li&gt;“Is Windows different to other operating systems in how it achieves this?”&lt;/li&gt;
&lt;li&gt;“How do we manage themes, preferences, start menu applications and other users?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The more I asked these questions the more I realised this project was going to go beyond the scope of just a front end recreation.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-goals&quot;&gt;New Goals&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I had made a decision to turn this small project into a “learning companion” giving me a higher level understanding of core components that go into an Operating System, to keep it simple it would be written in a language I am currently familiar and comfortable in (TypeScript). I wanted the project to push me to think outside of the box with my current language whilst introducing me to concepts found in different development practices (Kernel Development, Drivers, Firmware, OS etc. ).&lt;/p&gt;
&lt;p&gt;I first needed to set myself some rules - after careful consideration these were the main ones.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pick a reference architecture.&lt;/li&gt;
&lt;li&gt;Choose a Paradigm.&lt;/li&gt;
&lt;li&gt;Stick to &lt;a href=&quot;https://en.wikipedia.org/wiki/SOLID&quot;&gt;SOLID principles&lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;Modularity and expansion prioritised in design and structure.&lt;/li&gt;
&lt;li&gt;Constrain realism to limitations of language and tools we are building in.&lt;/li&gt;
&lt;li&gt;Be open to changing these rules if it meets the goals of simulating our reference architecture.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;opinionated-early&quot;&gt;Opinionated Early&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;These rules resulted in some early decisions. I first elected to align with the &lt;a href=&quot;https://en.wikipedia.org/wiki/Object-oriented_programming&quot;&gt;Object Oriented Paradigm&lt;/a&gt; for this project, this would mean some changes to frameworks and structure (more on that shortly). I also decided to choose the &lt;a href=&quot;https://en.wikipedia.org/wiki/Architecture_of_Windows_NT&quot;&gt;NT Architecture&lt;/a&gt; as my reference architecture considering I was already working on a Windows front end.&lt;/p&gt;
&lt;p&gt;Some other “standards” I set for myself.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kebab-case naming convention with dot separators to identify our files with ease etc: &lt;code dir=&quot;auto&quot;&gt;example-file.class.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Separation of concerns including modularised &lt;code dir=&quot;auto&quot;&gt;type.ts&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;const.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Test driven development to milestone major functionality implementations with unit testing methodology.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I believe the above to be more foundational, I realised the more important decisions were paradigm and reference architecture which helped shape and grow these standards organically.&lt;/p&gt;
&lt;p&gt;In addition I chose some technologies to assist with the developer experience - the main ones being &lt;code dir=&quot;auto&quot;&gt;jest&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;prettier&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;tailwind&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;angular&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ts-jest&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;jsdom&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;jest&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;js-dom&lt;/code&gt;: Is the main testing suite being used as it allows for both functional unit tests and DOM related output validation.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;prettier&lt;/code&gt;: I used to ensure consistent formatting across our files.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;tailwind&lt;/code&gt;: Is a utility class based CSS library allowing for us to have simple inline styling across our html components&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;angular&lt;/code&gt;: Is an OO front end framework which we will discuss in more detail in the next section.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;functional-vs-oo&quot;&gt;Functional vs OO&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I had done a considerable amount of work making a functional front end using &lt;code dir=&quot;auto&quot;&gt;vite&lt;/code&gt;. I had built a replica of the Windows XP taskbar which visually matched the old Start Menu. I had even built multiple themes being served through a &lt;code dir=&quot;auto&quot;&gt;contextProvider&lt;/code&gt;, originally the vision was to allow for users to make their own themes to replicate other popular operating systems - the only issue, &lt;code dir=&quot;auto&quot;&gt;vite&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;React&lt;/code&gt; (whilst no issue mixing in OO principles &lt;code dir=&quot;auto&quot;&gt;after all everything is an object in javascript&lt;/code&gt;) are primarily better suited to the functional paradigm.&lt;/p&gt;
&lt;p&gt;I had my first decision to make - one that I now believe to be the right one.&lt;/p&gt;
&lt;p&gt;I elected to port my project in full to &lt;a href=&quot;https://angular.dev/&quot;&gt;Angular&lt;/a&gt;. This was a great experience overall and my approach helped speed things up, if you are ever looking to port a project from one framework to another - my suggestion is to speak in the language of the Framework you are familiar with to an LLM (my current choice is Gemini for “pair programming ” purposes) - I’m not suggesting the responses are gospel however, questions like.&lt;/p&gt;
&lt;p&gt;“What is the React &lt;code dir=&quot;auto&quot;&gt;useState&lt;/code&gt; equivalent in the Angular framework?”&lt;/p&gt;
&lt;p&gt;Helped speed up finding the right reference materials for me to learn the basics of the framework, other more nuanced techniques were reserved to reading documentation and self research.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;an-example-of-change&quot;&gt;An example of change&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Here I want to show how different the two frameworks are, let’s take the Windows XP Start Menu (see reference picture from my frontend).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;webos_startmenu&quot; title=&quot;web os startmenu&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;697&quot; height=&quot;920&quot; src=&quot;https://www.asbedb.dev/_astro/webos_startmenu.Cw1CfDyX_26WHX4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The original functional component code (&lt;code dir=&quot;auto&quot;&gt;vite&lt;/code&gt;) looked like this:&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;StartMenu.tsx&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/applications/system/desktop-environment/components/StartMenu.tsx&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Divider &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../divider/Divider&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; PowerPanel &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./PowerPanel&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StartMenuLeftPanel &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./StartMenuLeftPanel&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StartMenuRightPanel &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./StartMenuRightPanel&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { forwardRef } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useTheme } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../../themes/ThemeContext&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StartMenuProps&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;isOpen&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StartMenu&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;forwardRef&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;HTMLDivElement&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;StartMenuProps&lt;/span&gt;&lt;span&gt;&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;({ &lt;/span&gt;&lt;span&gt;isOpen&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;ref&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// &apos;ref&apos; is the second argument provided by forwardRef&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;theme&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useTheme&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuTheme&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; theme.startmenustyles&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuWrapperClasses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.wrapper.border,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.wrapper.color,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.wrapper.display,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;(Boolean)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuHeaderClasses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.startMenuHeader.border,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.startMenuHeader.color,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.startMenuHeader.display,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;(Boolean)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;innerMenuClasses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.innermenu.border,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startMenuTheme.innermenu.display,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;(Boolean)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;`${&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;isOpen&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;absolute&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;hidden&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;startMenuWrapperClasses&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{ref}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{startMenuHeaderClasses}&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;img&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{theme.startmenustyles.profilepicture.iconSrc}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;theme.startmenustyles.profilepicture.iconStyle&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;alt&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{theme.startmenustyles.profilepicture.iconAlt}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                             &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{theme.startmenustyles.username.text}&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Administrator          {&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{innerMenuClasses}&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Divider&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dividerColor&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;orange&quot;&lt;/span&gt;&lt;span&gt; /&gt;         {&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{theme.startmenustyles.pannelwrapper.display}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;StartMenuLeftPanel&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;StartMenuRightPanel&lt;/span&gt;&lt;span&gt; /&gt;         {&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;PowerPanel&lt;/span&gt;&lt;span&gt; /&gt;       {&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; StartMenu&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And the ported object oriented component (&lt;code dir=&quot;auto&quot;&gt;Angular&lt;/code&gt;) looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;StartMenu.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/applications/system/desktop-environment/components/StartMenu.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Component, inject, computed, Input } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;@angular/core&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { CommonModule } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;@angular/common&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { NgOptimizedImage } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;@angular/common&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { ThemeContextService } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../../themes/theme-context&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Divider &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../divider/divider&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StartMenuLeftPanel &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./start-menu-left-panel&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StartMenuRightPanel &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./start-menu-right-panel&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StartMenuPowerPanel &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./power-panel&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { StyleHelpers } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../../style-helpers&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;selector: &lt;/span&gt;&lt;span&gt;&apos;start-menu&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;standalone: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;imports: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CommonModule,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;NgOptimizedImage,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Divider,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;StartMenuLeftPanel,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;StartMenuRightPanel,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;StartMenuPowerPanel,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;template: &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;div [ngClass]=&quot;startMenuWrapperClasses&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;div [ngClass]=&quot;startMenuHeaderClasses&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;img&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[ngSrc]=&quot;profilePicture.iconSrc&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[ngClass]=&quot;profilePicture.iconStyle&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[alt]=&quot;profilePicture.iconAlt&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;span [ngClass]=&quot;startMenuUsernameClasses&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Administrator&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;div [ngClass]=&quot;startMenuInnerMenuClasses&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;divider color=&quot;orange&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;div [ngClass]=&quot;startMenuPanelClasses&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;start-menu-left-panel /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;start-menu-right-panel /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;start-menu-power-panel /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StartMenu&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Input&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;isOpen&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;theme&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inject&lt;/span&gt;&lt;span&gt;(ThemeContextService)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.theme.&lt;/span&gt;&lt;span&gt;theme&lt;/span&gt;&lt;span&gt;().startmenustyles)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;profilePicture&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; StyleHelpers.&lt;/span&gt;&lt;span&gt;returnIconValues&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt;().profilepicture)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuPanelClasses&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; StyleHelpers.&lt;/span&gt;&lt;span&gt;joinStyleValues&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt;().pannelwrapper)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuInnerMenuClasses&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; StyleHelpers.&lt;/span&gt;&lt;span&gt;joinStyleValues&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt;().innermenu)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuHeaderClasses&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; StyleHelpers.&lt;/span&gt;&lt;span&gt;joinStyleValues&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt;().startMenuHeader)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuUsernameClasses&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; StyleHelpers.&lt;/span&gt;&lt;span&gt;joinStyleValues&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt;().username)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startMenuWrapperClasses&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;classes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [StyleHelpers.&lt;/span&gt;&lt;span&gt;joinStyleValues&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;styles&lt;/span&gt;&lt;span&gt;().wrapper)]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.isOpen) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;classes.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;hidden&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;classes.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;absolute&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; classes.&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;(Boolean).&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Two completely different approaches ultimately leading to the same rendered component - I had moved from &lt;code dir=&quot;auto&quot;&gt;useContext&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;inject&lt;/code&gt; (and &lt;code dir=&quot;auto&quot;&gt;compute&lt;/code&gt;); &lt;code dir=&quot;auto&quot;&gt;props&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;@decorators&lt;/code&gt;; &lt;code dir=&quot;auto&quot;&gt;state&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;signals&lt;/code&gt; and of course was now returning classes instead of functions.&lt;/p&gt;
&lt;p&gt;Whilst the conscious choice to port to Angular was made early this wasn’t necessarily due to one framework being better then the other. It aligned more to those opinions and rules I had set - in particular adhering to an OOP approach upfront.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;starting-at-the-hardware&quot;&gt;Starting at the Hardware&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A computer is made up of components, those components put together make it compute. So how do we simulate those components without losing focus on the overall project and its learning outcomes. My first task was to validate a configuration with some simulated core hardware components.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;cpu&quot;&gt;CPU&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;During my initial research I made a decision to forgo simulating a CPU at this stage - I made this decision as I saw the task as one that would consume a significant amount of early stage development that could cause the project to lose focus and fail to meet its initial learning goals.&lt;/p&gt;
&lt;p&gt;Should I have included the CPU I would need to consider, threading, concurrency, logic gate functionality, orchestrating kernel executions and much more. My approach was simple, allow for the structure to “plugin” a CPU at a later date and for now continue with the main goals.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;storage-ram-and-gpu&quot;&gt;Storage, RAM and GPU&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Memory from a functionality perspective is fairly simple with the two main functions being read and write. (technically it is storing and releasing but for now let’s relegate to read and write).&lt;/p&gt;
&lt;p&gt;Accessing memory has no linearity, allowing for non-sequential reads and writes to ensure fast access. As this is a simulation we were not going to get into the granularity of control logic, address decoders (at least in detail) or multiplexers. The function of our various memory modules was to meet and address a few points.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A way to simulate and limit concurrent running processes&lt;/li&gt;
&lt;li&gt;Abstracted pointers to Hexadecimal values (&lt;code dir=&quot;auto&quot;&gt;Uint8Array&lt;/code&gt; was used for this).&lt;/li&gt;
&lt;li&gt;Simple read and write that could eventually be accessed through our win32API (More on this in part two of this article in the near future).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first technical decision made was to limit the simulated storage parameters to be kilobytes (kb/&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mn&gt;1024&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;*1024&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;∗&lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) noting I would scale this up in the front end environment for rendering/visual purposes. The reason was due to the constraints for object creation lengths in JavaScript. Having a &lt;code dir=&quot;auto&quot;&gt;Uint8Array&lt;/code&gt; with a length that equated to the amount of bytes in a GB would not be acceptable or even required for this project.&lt;/p&gt;
&lt;p&gt;As mentioned I made a choice of a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;Uint8Array&lt;/code&gt;&lt;/a&gt; to represent our “address decoder” (using the term very loosely) because it supports the working with arbitrary binary data. Should I decide to dip my toes into WASM and decoding binary data then we have a good typed array to support this in the future!&lt;/p&gt;
&lt;p&gt;I also decided to not implement GDI level simulation which meant limiting the GPU to memory functionality, this means that both the GPU and RAM classes would be identical for now separated in name.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;ram.class.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/ram/ram.class.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// GPU and RAM have the same functions at this stage.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// technical decision to use kb instead of mb to simulate actual memory reads within javascript&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;totalMemoryKB&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;memoryContent&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;usedMemoryKB&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;availableMemoryKB&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;totalBytes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;memoryKB&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; memoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.availableMemoryKB &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalBytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.memoryContent &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalBytes)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allocateMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;expectedMemoryUsageKB&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (expectedMemoryUsageKB &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;warn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;RAM: Cannot allocate 0 or negative memory&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (expectedMemoryUsageKB &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.availableMemoryKB) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;warn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;`RAM: Not enough RAM Memory available. Requested ${&lt;/span&gt;&lt;span&gt;expectedMemoryUsageKB&lt;/span&gt;&lt;span&gt;}KB, but only ${&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;availableMemoryKB&lt;/span&gt;&lt;span&gt;}KB remaining.`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allocatedAddressBytes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.usedMemoryKB &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.availableMemoryKB &lt;/span&gt;&lt;span&gt;-=&lt;/span&gt;&lt;span&gt; expectedMemoryUsageKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.usedMemoryKB &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; expectedMemoryUsageKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;`RAM: Allocated ${&lt;/span&gt;&lt;span&gt;expectedMemoryUsageKB&lt;/span&gt;&lt;span&gt;}KB of memory. Used: ${&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;usedMemoryKB&lt;/span&gt;&lt;span&gt;}KB, Remaining: ${&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;availableMemoryKB&lt;/span&gt;&lt;span&gt;}KB`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; allocatedAddressBytes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;addressBytes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;lengthBytes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;totalBytes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (addressBytes &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; addressBytes &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; lengthBytes &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; totalBytes) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;`RAM: Memory read out of bounds. Address: ${&lt;/span&gt;&lt;span&gt;addressBytes&lt;/span&gt;&lt;span&gt;}, Length: ${&lt;/span&gt;&lt;span&gt;lengthBytes&lt;/span&gt;&lt;span&gt;} bytes. Total Size: ${&lt;/span&gt;&lt;span&gt;totalBytes&lt;/span&gt;&lt;span&gt;} bytes.`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.memoryContent.&lt;/span&gt;&lt;span&gt;subarray&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;addressBytes,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;addressBytes &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; lengthBytes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;writeMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;addressBytes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;totalBytes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (addressBytes &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; addressBytes &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; data.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; totalBytes) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;`RAM: Memory read out of bounds. Address: ${&lt;/span&gt;&lt;span&gt;addressBytes&lt;/span&gt;&lt;span&gt;}, Data Length: ${&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;} bytes. Total Size: ${&lt;/span&gt;&lt;span&gt;totalBytes&lt;/span&gt;&lt;span&gt;} bytes.`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.memoryContent.&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(data, addressBytes)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getAvailableMemory&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.availableMemoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getUsedMemory&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.usedMemoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;storage-devices&quot;&gt;Storage Devices&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Whilst the storage device would also take the same functions a small addition was added to the constructor to ensure I could adapt the class to have different type properties. I did this by using a &lt;code dir=&quot;auto&quot;&gt;StorageType&lt;/code&gt; export. I was also initially considering how to check “port compatibility” and this structure would help me address that across components.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;storage/types.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulatedHardware/storage/types.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageTypes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;DISC_DVD: &lt;/span&gt;&lt;span&gt;&apos;DISC_DVD&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IDE_HDD_ONE: &lt;/span&gt;&lt;span&gt;&apos;IDE_HDD_ONE&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IDE_HDD_TWO: &lt;/span&gt;&lt;span&gt;&apos;IDE_HDD_TWO&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IDE_HDD_THREE: &lt;/span&gt;&lt;span&gt;&apos;IDE_HDD_THREE&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;USB_FLASHDRIVE: &lt;/span&gt;&lt;span&gt;&apos;USB_FLASHDRIVE&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageType&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; StorageTypes)[&lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; StorageTypes]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;storage-device.class.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/storage/storage-device.class.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;(storageType: StorageType, memoryKB: number) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (memoryKB &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;STORAGE: Cannot create a storage device with no memory.&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.availableMemoryKB &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalBytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.memoryContent &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.hardwareProfile &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; storageType;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; memoryKB;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalBytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.availableMemoryKB &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemoryKB;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.memoryContent &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalBytes);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.hardwareProfile &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; storageType;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;motherboard&quot;&gt;Motherboard&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The motherboard serves as a I/O board that verifies if its slots are occupied with valid devices and returns a class with &lt;em&gt;“what’s plugged in”&lt;/em&gt;. I decided to use custom interfaces to construct types that would ensure the compatibility requirements of slots were met.&lt;/p&gt;
&lt;p&gt;This approach allows me to come back to this module and expand on the idea in the future. For now the &lt;code dir=&quot;auto&quot;&gt;pcieOne&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;pcieTwo&lt;/code&gt; ports as per &lt;code dir=&quot;auto&quot;&gt;pcConstructorProperties&lt;/code&gt; take a &lt;code dir=&quot;auto&quot;&gt;pcieSlotConfig&lt;/code&gt; type which would offer us with either a null value (nothing plugged in) or an interface that’s &lt;code dir=&quot;auto&quot;&gt;gpu&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;storage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The motherboard can ultimately have anything plugged in (assuming compatibility requirements are met), at a minimum it needs GPU, Storage and RAM to be a valid construction of a motherboard otherwise returning a &lt;code dir=&quot;auto&quot;&gt;configurationError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;motherboard/types.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/motherboard/types.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { GPU } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../gpu/gpu.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { RAM } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../ram/ram.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { StorageDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../storage/storage-device.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GpuPcieProperties&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;profile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageProperties&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;profile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PCIeDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieSlotConfig&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GpuPcieProperties&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageProperties&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcConstructorProperties&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotOne&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotTwo&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotThree&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotFour&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ideOne&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageProperties&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ideTwo&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageProperties&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;sataOne&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageProperties&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pcieOne&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieSlotConfig&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pcieTwo&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieSlotConfig&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;motherboard.class.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/motherboard/motherboard.class.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { RAM } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../ram/ram.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { StorageDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../storage/storage-device.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; { pcConstructorProperties } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./types&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; { PCIeDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./types&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dimSlotOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dimSlotTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dimSlotThree&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dimSlotFour&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ideOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ideTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sataOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PCIeDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PCIeDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;dimSlotOne&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;dimSlotTwo&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;dimSlotThree&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;dimSlotFour&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ideOne&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ideTwo&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;sataOne&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pcieOne&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pcieTwo&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcConstructorProperties&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;dimSlotOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;dimSlotTwo &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;dimSlotThree &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;dimSlotFour) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;configurationError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Missing RAM`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (pcieOne?.type &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; pcieTwo?.type &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;configurationError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Missing GPU`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;ideOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;ideTwo &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;sataOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne?.type &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieTwo?.type &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;configurationError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Missing Storage`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (dimSlotOne) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; dimSlotOne&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (dimSlotTwo) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotTwo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; dimSlotTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (dimSlotThree) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotThree &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; dimSlotThree&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (dimSlotFour) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotFour &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; dimSlotFour&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (ideOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; ideOne.type &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ideOne.profile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (ideTwo &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; ideTwo.type &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideTwo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ideTwo.profile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (sataOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; sataOne.type &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.sataOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sataOne.profile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (pcieOne) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; pcieOne.profile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (pcieTwo) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; pcieTwo.profile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;configurationError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;errorMessage&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`PC: ${&lt;/span&gt;&lt;span&gt;errorMessage&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;currentConfig&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotTwo: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotThree: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotThree,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotFour: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotFour,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideTwo: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sataOne: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.sataOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieTwo: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;firmware&quot;&gt;Firmware&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I introduced the concept of firmware when I was separating concerns related to verifying an option ROM and the master boot record. In a normal scenario an operating system would initially be installed off external boot media with a valid boot signatures however in this scenario the simulation would assume that the operating system was “pre-installed” and these installation steps had been completed. I made a choice to relegate the master boot record to a “firmware” function, this would allow for me to create different signatures, should I for example want to dynamically load a Linux inspired MBR onto a Storage device in the future.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;storage-firmware-master-boot-record&quot;&gt;Storage Firmware (Master Boot Record)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To create the master boot record the approach I took wasn’t dissimilar to how it would work in a real operating system. The first step was to set some variables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;diskSectorSize&lt;/code&gt; - This would be the smallest size allocated for each sector, similar to a real device we chose 512 as the smallest divisible number.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;pointerVariables&lt;/code&gt; - These variables are the memory addresses reserved to identify characteristics of the the boot record we have:
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;446&lt;/code&gt;: Pointer which returns if partition is Active or Inactive.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;450:&lt;/code&gt; Partition type (NTFS, FAT etc.)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;510&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;511&lt;/code&gt;: These pointers are reserved to let the BIOS know if the partition has a boot signature.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;328&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;329&lt;/code&gt;: For the simulation I reserved pointer 328 and 329 to be our OS Signature, in a real operating system unreserved bytes in the MBR would store the bootloader software. As I was going straight into kernel mode depending on signature found I simplified the logic to match - it also means we can make different operating systems without needing to build a bootloader for each one.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;partitionVariables&lt;/code&gt;: To accompany the above memory addresses the partition variables are set into two categories.
&lt;ul&gt;
&lt;li&gt;Storage Specific - File Type, Active/Inactive&lt;/li&gt;
&lt;li&gt;OS Specific - Boot Signature Values, OS Signature Values (For our simulation we only have the Windows ones for now.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;const.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/firmware/storage/const.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// MBR Constants&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;diskSectorSize&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// MBR - Pointers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerBootablePartition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;446&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerPartitionType&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;450&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerBootSignatureOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;510&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerBootSignatureTwo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;511&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerOSSignatureOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;328&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerOSSignatureTwo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;329&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// MBR - Flags/Data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;partitionActive&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;partitionInactive&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x00&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;partitionTypeNTFS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x07&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;partitionTypeFat32&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x0c&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// MBR - OS Sigantures&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;osBootSignatureOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x55&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;osBootSignatureTwo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0xaa&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;osSignatureBindowsXDOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0xff&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;osSignatureBindowsXDTwo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0xee&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With the values set now it was time to translate this to a class structure - I opted to take four variables for the constructor as captured by the types file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;partitionType&lt;/code&gt;: a simple union type that would translate different filesystem types.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;sectorSize&lt;/code&gt;: a number representing the number of bytes per sector.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;osSingatureOne&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;osSignatureTwo&lt;/code&gt;: our unique system implemented to invoke the correct operating system from BIOS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;types.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/firmware/storage/types.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MasterBootRecordPartitionType&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ntfs&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;fat32&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MasterBootRecordTypeConstructorProperties&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;partitionType&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MasterBootRecordPartitionType&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;sectorSize&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;osSignatureOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;osSignatureTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Finally I combined the variables and put together the &lt;code dir=&quot;auto&quot;&gt;MasterBootRecord&lt;/code&gt; class when constructed would return a &lt;code dir=&quot;auto&quot;&gt;Uint8Array&lt;/code&gt; which could be directly written into the previous &lt;code dir=&quot;auto&quot;&gt;StorageDevice&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;The class when constructed would first ensure the constructor arguments adhered to the original architecture specifications (512 byte length, active partition, valid OS signature and valid filesystem type). Once checks are complete it sets the &lt;code dir=&quot;auto&quot;&gt;this.masterBootRecord&lt;/code&gt; property to the typed array with the crucial pointers having the correct corresponding data.&lt;/p&gt;
&lt;p&gt;I also included a &lt;code dir=&quot;auto&quot;&gt;validateMasterBootRecord&lt;/code&gt; function which would return &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; if all specifications were met else returning &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;master-boot-record.class.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/firmware/storage/master-boot-record.class.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; { MasterBootRecordTypeConstructorProperties } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./types&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerBootSignatureOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerBootSignatureTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerBootablePartition,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerOSSignatureOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerOSSignatureTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerPartitionType,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionActive,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionInactive,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionTypeFat32,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionTypeNTFS,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osBootSignatureOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osBootSignatureTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./const&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MasterBootRecord&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;masterBootRecord&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;partitionType&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;sectorSize&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;osSignatureOne&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;osSignatureTwo&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MasterBootRecordTypeConstructorProperties&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;(sectorSize).&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0x00&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (sectorSize &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootablePartition] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionInactive&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Master Boot Record: Sector Size not supported.&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootablePartition] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionActive&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;partitionType) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootablePartition] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionInactive&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Master Boot Record: Missing Partition Type&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (partitionType &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ntfs&apos;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerPartitionType] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionTypeNTFS&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (partitionType &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;fat32&apos;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerPartitionType] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionTypeFat32&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osSignatureOne &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; osBootSignatureOne &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osSignatureTwo &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; osBootSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootablePartition] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionInactive&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;&apos;Master Boot Record: Invalid boot signature values provided&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootSignatureOne] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; osBootSignatureOne&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootSignatureTwo] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; osBootSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;osSignatureOne &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;osSignatureTwo) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootablePartition] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; partitionInactive&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Master Boot Record: No OS Signature provided.&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerOSSignatureOne] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; osSignatureOne&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerOSSignatureTwo] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; osSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;validateMasterBootRecord&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootablePartition] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionActive &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerPartitionType] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionTypeNTFS &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerPartitionType] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionTypeFat32) &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootSignatureOne] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osBootSignatureOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerBootSignatureTwo] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osBootSignatureTwo &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerOSSignatureOne] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x00&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.masterBootRecord[pointerOSSignatureTwo] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x00&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Finally we can create a custom &lt;code dir=&quot;auto&quot;&gt;const&lt;/code&gt; for a “Windows” master boot record (if you haven’t noticed yet my simulated OS working title is &lt;code dir=&quot;auto&quot;&gt;Bindows XD&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;windows-master-boot-record.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/firmware/storage/windows-master-boot-record.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { MasterBootRecord } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./master-boot-record.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { osSignatureBindowsXDOne, osSignatureBindowsXDTwo } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./const&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;windowsMasterBootRecord&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MasterBootRecord&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;partitionType: &lt;/span&gt;&lt;span&gt;&apos;ntfs&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sectorSize: &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osSignatureOne: osSignatureBindowsXDOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osSignatureTwo: osSignatureBindowsXDTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;gpu-firmware-option-rom&quot;&gt;GPU Firmware (Option ROM)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Now that I have explained the logic behind how pointers and data is set when dealing with storage - I can expand on the GPU’s role. For now I have decided to use &lt;code dir=&quot;auto&quot;&gt;Angular&lt;/code&gt; as a “Graphical Device Interface Service” rather then building something custom to simulate the OS GDI Layer. There is however a crucial role a GPU can play in the boot process - mainly housing the option ROM functionality.&lt;/p&gt;
&lt;p&gt;An option ROM allows you to use basic peripherals prior to your device loading an operating system (as an example display and Input support when configuring your BIOS). Like a Master Boot Record, an Option Rom also has a unique signature noted by the first two bytes accessed on the devices onboard storage. For our simulation the GPU houses the option ROM and the option ROM’s function is merely to be validated during POST (nothing more at this stage). This means I can come back later and expand on this idea should I decide to expand on the BIOS functionality or work on a GDI service/expand the GPU’s role and functions.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;const.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/firmware/gpu/const.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;optionRomBootSignatureOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x55&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;optionRomBootSignatureTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0xaa&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerOptionRomBootSignatureOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pointerOptionRomBootSignatureTwo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;option-rom.class.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/firmware/gpu/option-rom.class.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerOptionRomBootSignatureOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pointerOptionRomBootSignatureTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optionRomBootSignatureOne,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optionRomBootSignatureTwo,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./const&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;OptionRom&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;optionRomData&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Uint8Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0x00&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData[pointerOptionRomBootSignatureOne] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optionRomBootSignatureOne&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData[pointerOptionRomBootSignatureTwo] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optionRomBootSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;validateOptionRom&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData[pointerOptionRomBootSignatureOne] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optionRomBootSignatureOne &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.optionRomData[pointerOptionRomBootSignatureTwo] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;optionRomBootSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;assembled-pc&quot;&gt;Assembled PC&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now we have our building blocks to build a PC ready to be inspected by a BIOS function. Below is what all the parts together look like. First I created a type interface which allocated compatibility for each slot available in a fully constructed PC&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;types.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/pc-builds/types.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { RAM } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../ram/ram.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { StorageDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../storage/storage-device.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { PCIeDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../motherboard/types&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FullSystem&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotThree&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dimSlotFour&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ideOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ideTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;sataOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pcieOne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PCIeDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pcieTwo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PCIeDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Following this a helper function was created to return a default system spec - for now this is functional. I will move this to a class at a later stage with the ability to choose multiple builds for testing.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/pc-builds/pc-builds.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { GPU } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../gpu/gpu.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { RAM } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../ram/ram.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { StorageDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../storage/storage-device.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { MotherBoard } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../motherboard/motherboard.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { windowsMasterBootRecord } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../../firmware/storage/windows-master-boot-record&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { OptionRom } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../../firmware/gpu/option-rom.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; { FullSystem } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./types&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defaultSystemSpecs&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FullSystem&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ram1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpu&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ideone&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;IDE_HDD_ONE&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;windowsMBR&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; windowsMasterBootRecord&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpuOptionRom&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;OptionRom&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (windowsMBR.&lt;/span&gt;&lt;span&gt;validateMasterBootRecord&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// represent kb as bytes for memory allocation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideone.&lt;/span&gt;&lt;span&gt;allocateMemory&lt;/span&gt;&lt;span&gt;(windowsMBR.masterBootRecord.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideone.&lt;/span&gt;&lt;span&gt;writeMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, windowsMBR.masterBootRecord)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gpuOptionRom.&lt;/span&gt;&lt;span&gt;validateOptionRom&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// represent kb as bytes for memory allocation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gpu.&lt;/span&gt;&lt;span&gt;allocateMemory&lt;/span&gt;&lt;span&gt;(gpuOptionRom.optionRomData.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gpu.&lt;/span&gt;&lt;span&gt;writeMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, gpuOptionRom.optionRomData)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: ram1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: { type: &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt;, profile: gpu },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: { type: &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;, profile: ideone },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; pc.&lt;/span&gt;&lt;span&gt;currentConfig&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As you can see the RAM, GPU, Storage, Option ROM and Windows MBR classes are instantiated. A validation of the option ROM and MBR then allocate and write memory to storage and GPU. Resulting in the return of a constructed PC via the &lt;code dir=&quot;auto&quot;&gt;MotherBoard&lt;/code&gt; class.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;unit-testing-examples&quot;&gt;Unit Testing Examples&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I mentioned earlier following a test driven development model for each of these components iterating on functionality by building to pass tests. This methodology has not only been useful in accounting for edge cases early but it has also been an invaluable tool when I refactored code or separated concerns helping me rapidly find variables/changes that may have causes chain reactions across my project where there were joint dependencies. Below I have included some simulated hardware tests as an example. I have made it a a point to go back and ensure these tests are updated to reduce any burdens caused by refactoring at a later stage.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;gpu.test.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/__tests__/gpu.test.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { GPU } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../gpu/gpu.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/// &amp;#x3C;&lt;/span&gt;&lt;span&gt;reference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;types&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jest&quot;&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;GPU&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; simulatedGPU&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;beforeEach&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;simulatedGPU &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;it&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Should return the hardware specifications as per it&apos;s constructor correctly`&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(simulatedGPU.totalMemoryKB).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(simulatedGPU.availableMemoryKB).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(simulatedGPU.memoryContent.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;it&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Should allocate and return the first &quot;byte address&quot; being used&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(simulatedGPU.&lt;/span&gt;&lt;span&gt;allocateMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(simulatedGPU.&lt;/span&gt;&lt;span&gt;allocateMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;)).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10240&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(simulatedGPU.&lt;/span&gt;&lt;span&gt;allocateMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;)).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;30720&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;motherboard.test.ts&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/simulated-hardware/__tests__/MotherBoard.test.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/// &amp;#x3C;&lt;/span&gt;&lt;span&gt;reference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;types&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jest&quot;&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { MotherBoard } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../motherboard/motherboard.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { GPU } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../gpu/gpu.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { RAM } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../ram/ram.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { StorageDevice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;../storage/storage-device.class&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;PC&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; simulatedPC&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;beforeEach&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ideone&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;IDE_HDD_ONE&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ram1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpu&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ideone&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;IDE_HDD&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: ram1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: { type: &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt;, profile: gpu },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: { type: &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;, profile: ideone },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(pc.&lt;/span&gt;&lt;span&gt;currentConfig&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;toStrictEqual&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: ram1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotTwo: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotThree: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotFour: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: ideone,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideTwo: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sataOne: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: gpu,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieTwo: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;it&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;should throw an error if no RAM is provided&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieGPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bootDriveIDE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;IDE_HDD&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: { type: &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt;, profile: pcieGPU },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: { type: &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;, profile: bootDriveIDE },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;toThrow&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;PC: Missing RAM&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;it&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;should throw an error if no GPU is provided in PCIe slots&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;slotOneRam&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bootDriveIDE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;IDE_HDD&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: slotOneRam,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: { type: &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;, profile: bootDriveIDE },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;toThrow&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;PC: Missing GPU&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;it&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;should throw an error if no storage device is provided&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;slotOneRam&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pcieGPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: slotOneRam,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: { type: &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt;, profile: pcieGPU },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;toThrow&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;PC: Missing Storage&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;it&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;should allow multiple RAM and storage devices&apos;&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ram1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ram2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sataDrive&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;SATA_SSD&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;128&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpu&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;128&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MotherBoard&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: ram1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotTwo: ram2,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sataOne: { type: &lt;/span&gt;&lt;span&gt;&apos;storage&apos;&lt;/span&gt;&lt;span&gt;, profile: sataDrive },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: { type: &lt;/span&gt;&lt;span&gt;&apos;gpu&apos;&lt;/span&gt;&lt;span&gt;, profile: gpu },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;expect&lt;/span&gt;&lt;span&gt;(pc.&lt;/span&gt;&lt;span&gt;currentConfig&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;toStrictEqual&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotOne: ram1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotTwo: ram2,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotThree: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dimSlotFour: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideOne: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ideTwo: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sataOne: sataDrive,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieOne: gpu,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pcieTwo: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;bios&quot;&gt;BIOS&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At this stage I felt ready to start tackling the BIOS - at a high level my plan was to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Take an assembled PC in its constructor&lt;/li&gt;
&lt;li&gt;Detect components in PC at a BIOS level.&lt;/li&gt;
&lt;li&gt;Conduct a Power on Self Test (POST) to ensure the PC would boot&lt;/li&gt;
&lt;li&gt;Check and validate a boot signature and option ROM signature&lt;/li&gt;
&lt;li&gt;Invoke an interrupt (19h) to boot into Kernel&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h3 id=&quot;class-properties-and-constructor&quot;&gt;Class Properties and Constructor&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The BIOS class would mirror the motherboard when it comes to slot properties alongside a few tracking variables.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;public &lt;/span&gt;&lt;span&gt;eventLog&lt;/span&gt;&lt;span&gt;: Array&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;public &lt;/span&gt;&lt;span&gt;postResults&lt;/span&gt;&lt;span&gt;: boolean &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;dimSlotOne&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;dimSlotTwo&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;dimSlotThree&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;dimSlotFour&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;ideOne&lt;/span&gt;&lt;span&gt;: StorageDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;ideTwo&lt;/span&gt;&lt;span&gt;: StorageDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;sataOne&lt;/span&gt;&lt;span&gt;: StorageDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;pcieOne&lt;/span&gt;&lt;span&gt;: PCIeDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;pcieTwo&lt;/span&gt;&lt;span&gt;: PCIeDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;bootTable&lt;/span&gt;&lt;span&gt;: Array&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;totalMemory&lt;/span&gt;&lt;span&gt;: number &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;totalStorage&lt;/span&gt;&lt;span&gt;: number &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;totalGpuMemory&lt;/span&gt;&lt;span&gt;: number &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The two &lt;code dir=&quot;auto&quot;&gt;public&lt;/code&gt; properties would be the &lt;code dir=&quot;auto&quot;&gt;eventLog&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;postResults&lt;/code&gt; with the rest being reserved for the internal state of the class.&lt;/p&gt;
&lt;p&gt;The constructor takes an assembled PC, runs a &lt;code dir=&quot;auto&quot;&gt;detectDevices&lt;/code&gt; function followed by a &lt;code dir=&quot;auto&quot;&gt;postResults&lt;/code&gt; (Power on Self Test), if the POST fails it returns an error, if it passes it invokes Interrupt 19h (further explained below).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;(assembledPC: FullSystem) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;assembledPC) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`PC: Assembled PC Not Found`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;detectDevices&lt;/span&gt;&lt;span&gt;(assembledPC);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.postResults &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;powerOnSelfTest&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.postResults) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&apos;BIOS: POST FAILED During boot-up. System cannot proceed.&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;interrupt&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;19h&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Not much commentary required for the &lt;code dir=&quot;auto&quot;&gt;detectDevice&lt;/code&gt; Function; it simply translates the slots that are occupied from our &lt;code dir=&quot;auto&quot;&gt;assembledPC&lt;/code&gt; to the private BIOS variables.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;detectDevices&lt;/span&gt;&lt;span&gt;(assembledPC: FullSystem) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.dimSlotOne) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.dimSlotOne;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.dimSlotTwo) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotTwo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.dimSlotTwo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.dimSlotThree) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotThree &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.dimSlotThree;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.dimSlotFour) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotFour &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.dimSlotFour;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.ideOne) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.ideOne;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.ideTwo) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideTwo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.ideTwo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.sataOne) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.sataOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.sataOne;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.pcieOne) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.pcieOne;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (assembledPC.pcieTwo) &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; assembledPC.pcieTwo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;bios-event-logging&quot;&gt;BIOS Event Logging&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;I included a utility function to track BIOS level events. The intent is to take an event object to lift up to the Kernel (and eventually Event Manager). For now the function takes the arguments of a &lt;code dir=&quot;auto&quot;&gt;message&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;isError&lt;/code&gt;. Pushing to our public &lt;code dir=&quot;auto&quot;&gt;Array&amp;#x3C;string&gt;&lt;/code&gt; typed &lt;code dir=&quot;auto&quot;&gt;eventLog&lt;/code&gt; a message entry.&lt;/p&gt;
&lt;p&gt;When the function is called a new &lt;code dir=&quot;auto&quot;&gt;Date&lt;/code&gt; object with the current system time is broken into a string representation of &lt;code dir=&quot;auto&quot;&gt;hours&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;minutes&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;seconds&lt;/code&gt;, padding the start with two zeros to create a time stamp. We then concatenate our timestamp with the event message to update our event log entry. The &lt;code dir=&quot;auto&quot;&gt;isError&lt;/code&gt; is used to display our message in the DOM as either a &lt;code dir=&quot;auto&quot;&gt;console.error&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;console.log&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;public &lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(message: string, isError&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; boolean): Array&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Date&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const hours &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;(date.&lt;/span&gt;&lt;span&gt;getHours&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;padStart&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;0&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const minutes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;(date.&lt;/span&gt;&lt;span&gt;getMinutes&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;padStart&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;0&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const seconds &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;(date.&lt;/span&gt;&lt;span&gt;getSeconds&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;padStart&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;0&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const timeStamp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`[${&lt;/span&gt;&lt;span&gt;hours&lt;/span&gt;&lt;span&gt;}:${&lt;/span&gt;&lt;span&gt;minutes&lt;/span&gt;&lt;span&gt;}:${&lt;/span&gt;&lt;span&gt;seconds&lt;/span&gt;&lt;span&gt;}]`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const concatEventMessage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`${&lt;/span&gt;&lt;span&gt;timeStamp&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;this.eventLog.push(concatEventMessage);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;isError&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(concatEventMessage);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} else {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(concatEventMessage);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;return this.eventLog;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;power-on-self-test-post&quot;&gt;Power on Self Test (POST)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The Power on Self Test is responsible for verifying if the hardware is “functioning”. The function is &lt;code dir=&quot;auto&quot;&gt;private&lt;/code&gt; to the class and starts with an &lt;code dir=&quot;auto&quot;&gt;updateEventLog&lt;/code&gt; function call.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;BIOS: Starting Power-On Self-Test (POST)...&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; overallPostPassed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; atLeastOneGPUFound &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; atLeastOneBootDriveFound &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For the simulation the POST begins with a &lt;code dir=&quot;auto&quot;&gt;overallPostPassed&lt;/code&gt; boolean set to &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt;, I also created a variable for &lt;code dir=&quot;auto&quot;&gt;atLeastOneGPUFound&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;atLeastOneBootDriveFound&lt;/code&gt;. Whilst technically both of these flags are not required for an actual POST function. I went with integrating these two “checks” into the POST to simulate a verifying an option ROM and bootloader. Should I decide to research bootloaders in the future I can easily create a class that sits between our BIOS and Kernel that can act as an additional interface.&lt;/p&gt;
&lt;p&gt;Setting some constants helped maintain modularity when testing various slot without having to repeat code. Using the structure of an object entry inside an array I set up &lt;code dir=&quot;auto&quot;&gt;storageSupporingSlots&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;gpuSupportingSlots&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ramSupportingSlots&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I also accounted for scenarios where a &lt;code dir=&quot;auto&quot;&gt;GPU&lt;/code&gt; or a &lt;code dir=&quot;auto&quot;&gt;StorageDevice&lt;/code&gt; could be using a PCIE slot by using typescripts &lt;code dir=&quot;auto&quot;&gt;instanceof&lt;/code&gt; type check to determine, and return, the matching class ensuring edge cases were covered.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;storageSupportingSlots&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;IDE ONE:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideOne },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;IDE TWO:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.ideTwo },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;SATA ONE:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.sataOne },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &lt;/span&gt;&lt;span&gt;&apos;PCIE ONE:&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne &lt;/span&gt;&lt;span&gt;instanceof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &lt;/span&gt;&lt;span&gt;&apos;PCIE TWO:&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo &lt;/span&gt;&lt;span&gt;instanceof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StorageDevice&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpuSupportingSlots&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &lt;/span&gt;&lt;span&gt;&apos;PCIE ONE:&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne &lt;/span&gt;&lt;span&gt;instanceof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieOne &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &lt;/span&gt;&lt;span&gt;&apos;PCIE TWO:&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo &lt;/span&gt;&lt;span&gt;instanceof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.pcieTwo &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ramSupportingSlots&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;DIM SLOT ONE:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotOne },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;DIM SLOT TWO:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotTwo },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;DIM SLOT THREE:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotThree },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ name: &lt;/span&gt;&lt;span&gt;&apos;DIM SLOT FOUR:&apos;&lt;/span&gt;&lt;span&gt;, device: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.dimSlotFour },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;ram-testing&quot;&gt;RAM Testing&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;I was now able to construct a &lt;em&gt;for&lt;/em&gt; loop that would take the array and run the right battery of tests based on “slot type” (this pattern is repeated for GPU and Storage). As the class slot properties are constructed with either null or a valid object the property would be mirrored for &lt;code dir=&quot;auto&quot;&gt;slotInfo.device&lt;/code&gt; reducing operations and only testing on slots that are “occupied”.&lt;/p&gt;
&lt;p&gt;For RAM a &lt;code dir=&quot;auto&quot;&gt;postTestMemory&lt;/code&gt; is first called returning a &lt;code dir=&quot;auto&quot;&gt;boolean&lt;/code&gt; value followed by adding to the &lt;code dir=&quot;auto&quot;&gt;totalMemory&lt;/code&gt; of the bios class alongside an update to the &lt;code dir=&quot;auto&quot;&gt;overallPostPassed&lt;/code&gt; based on a combination of the existing &lt;code dir=&quot;auto&quot;&gt;boolean&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ramTestPassed&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;slotInfo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; ramSupportingSlots) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (slotInfo.device) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ramTestPassed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;postTestMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotInfo.name,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotInfo.device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalMemory &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; slotInfo.device.availableMemoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;overallPostPassed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; overallPostPassed &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; ramTestPassed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;postTestMemory&lt;/code&gt; function is used in both &lt;em&gt;for&lt;/em&gt; loops for &lt;code dir=&quot;auto&quot;&gt;ramSupportingSlots&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;storageSupporingSlots&lt;/code&gt;. It initially logs an event message followed by a &lt;code dir=&quot;auto&quot;&gt;isFunctioning&lt;/code&gt; check. Once complete it ensures the memory modules available memory is above &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt; before returning &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; for the test being passed.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;postTestMemory&lt;/span&gt;&lt;span&gt;(slot: string, detectedMemoryModule: &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt;): boolean {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} Testing Memory.`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isFunctioning&lt;/span&gt;&lt;span&gt;(detectedMemoryModule, slot)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (detectedMemoryModule.totalMemoryKB &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;detectedMemoryModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;} Zero Memory  Detected.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;detectedMemoryModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}: ${&lt;/span&gt;&lt;span&gt;detectedMemoryModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;} Initialised.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;isFunctioning&lt;/code&gt; is purely decorative - we don’t really need this in typescript. We are just simulating that the slot is powered and returning a 1 or a 0 basically.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;isFunctioning&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;testModule: &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; StorageDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; PCIeDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotName: string,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;): boolean {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;testModule) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slotName&lt;/span&gt;&lt;span&gt;} Hardware Detection issue.`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slotName&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;testModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;} detected.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;gpu-testing&quot;&gt;GPU Testing&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Again the &lt;em&gt;for&lt;/em&gt; loop cycles through &lt;code dir=&quot;auto&quot;&gt;gpuSupporingSlots&lt;/code&gt; this time calling the &lt;code dir=&quot;auto&quot;&gt;postTestGPU&lt;/code&gt; function.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;slotInfo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; gpuSupportingSlots) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (slotInfo.device) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpuTestPassed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;postTestGPU&lt;/span&gt;&lt;span&gt;(slotInfo.name, slotInfo.device)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;overallPostPassed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; overallPostPassed &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; gpuTestPassed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalGpuMemory &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; slotInfo.device.availableMemoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (gpuTestPassed) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;atLeastOneGPUFound &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As relayed earlier to reduce complexity around deploying a full bootloader the POST relies on a GPU not only being loaded but also including a valid option rom signature within its first two bytes.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;postTestGPU&lt;/span&gt;&lt;span&gt;(slot: string, gpuModule: &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt;): boolean {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} Testing GPU.`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isFunctioning&lt;/span&gt;&lt;span&gt;(gpuModule, slot)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpuSignature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; gpuModule.&lt;/span&gt;&lt;span&gt;readMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gpuSignature[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; optionRomSignatureOne &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gpuSignature[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; optionRomSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;`POST ERROR: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} GPU Option ROM Signature Not Found.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} GPU: Option Rom Signature Found.`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} GPU: GPU Initialised.`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;storage-testing&quot;&gt;Storage Testing&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The final &lt;em&gt;for&lt;/em&gt; loop cycle continues with the same tests on storage with an additional check to add devices to a &lt;code dir=&quot;auto&quot;&gt;bootTable&lt;/code&gt; if the check returns true on a &lt;code dir=&quot;auto&quot;&gt;bootSignature&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;slotInfo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; storageSupportingSlots) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (slotInfo.device) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;storageTestPassed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;postTestStorage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotInfo.name,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotInfo.device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (slotInfo.device.availableMemoryKB) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.totalStorage &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; slotInfo.device.availableMemoryKB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;overallPostPassed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; overallPostPassed &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; storageTestPassed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (storageTestPassed) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isBootable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;checkBootSignature&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotInfo.name,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotInfo.device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (isBootable) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.bootTable.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(slotInfo.device)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;atLeastOneBootDriveFound &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;and the &lt;code dir=&quot;auto&quot;&gt;checkbootSignature&lt;/code&gt; function similar to our GPU check returns true if the MBR sectors last two bytes return a boot signature (&lt;code dir=&quot;auto&quot;&gt;0x55, 0xaa&lt;/code&gt;).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;checkBootSignature&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slot: string,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;detectedStorageModule: StorageDevice,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;): boolean {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;detectedStorageModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;hardwareProfile&lt;/span&gt;&lt;span&gt;} Drive: Searching for Boot Signature in Storage Device.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bootSignature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; detectedStorageModule.&lt;/span&gt;&lt;span&gt;readMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bootSignature[&lt;/span&gt;&lt;span&gt;510&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; bootSignatureOne &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bootSignature[&lt;/span&gt;&lt;span&gt;511&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; bootSignatureTwo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;detectedStorageModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;hardwareProfile&lt;/span&gt;&lt;span&gt;} Drive: Boot Signature not found.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;`POST: ${&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt;} ${&lt;/span&gt;&lt;span&gt;detectedStorageModule&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}: Boot Signature Found.`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;finalising-post&quot;&gt;Finalising POST&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The last step in POST is a &lt;code dir=&quot;auto&quot;&gt;boolean&lt;/code&gt; return with a final update to our event log assuming all the tests have passed. This marks the conclusion of the POST function with our &lt;code dir=&quot;auto&quot;&gt;Interrupt19h&lt;/code&gt; being called next in the constructor should POST be successful.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;overallPostPassed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;overallPostPassed &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; atLeastOneBootDriveFound &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; atLeastOneGPUFound&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;BIOS: POST Completed successfully...&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; overallPostPassed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;interrupts&quot;&gt;Interrupts&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Currently the only Interrupt I have implemented in &lt;code dir=&quot;auto&quot;&gt;19h&lt;/code&gt;. Interrupt calls are invoked by operating systems and application programs as an interface to firmware. For our example we are using the &lt;code dir=&quot;auto&quot;&gt;19h&lt;/code&gt; call to load our “bootloader”. As mentioned earlier as we are going straight from BIOS to Kernel our &lt;code dir=&quot;auto&quot;&gt;19h&lt;/code&gt; call in this example will instantiate a new Kernel object. Using a &lt;code dir=&quot;auto&quot;&gt;switch case&lt;/code&gt; I have set the foundation for future interrupts with relevant event logging and comments as a reminder of the functionality of each call.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;interrupt&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;interuptVector: string,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;device&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; StorageDevice &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RAM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;): &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;12h&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Interrupt 12h invoked - Returning Memory Size...&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;13h01h&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Interrupt 13h01h invoked - Check Drive Status...&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;13h02h&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Interrupt 13h02h invoked - Read Sectors...&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;13h03h&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Interrupt 13h03h invoked - Write Sectors...&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;// Implemented Interrupt to find bootloader.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;19h&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&apos;Interrupt 19h: Invoked - Searching for Boot Table...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.bootTable.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&apos;Interrupt 19h: Boot Table Found - Searching for OS...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;interrupt19h&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Finally the &lt;code dir=&quot;auto&quot;&gt;interrupt19h&lt;/code&gt; function will check the OS Signature and return a new kernel object accordingly (The return has not been implemented yet). This structure allows for me to create support for other operating systems in the future.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;private &lt;/span&gt;&lt;span&gt;interrupt19h&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bootDrive&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.bootTable) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;`Interrupt 19h: Checking OS Signature on ${&lt;/span&gt;&lt;span&gt;bootDrive&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;osSignatureAddress&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; bootDrive.&lt;/span&gt;&lt;span&gt;readMemory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;328&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osSignatureAddress[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; osSignatureOneBindows &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;osSignatureAddress[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; osSignatureTwoBindows&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateEventLog&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;`Interrupt 19h: OS Signature on ${&lt;/span&gt;&lt;span&gt;bootDrive&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;} matches BindowsXD`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;conclusion-and-next-phase&quot;&gt;Conclusion and Next Phase&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I hope you enjoyed part one of my journey so far. This project has helped me really think outside the box, it has driven me to change and adapt things to match a paradigm and constraints. At this stage I am working on a NT Architecture kernel splitting objects and functionality between User and Executive mode with various services which will make up the core of the operating system being orchestrated accordingly. In part two (once I finish most of the kernel level structure and code) I will provide a lot more insight into the NT Architecture and the challenges I faced implementing my simulated approach.&lt;/p&gt;</content:encoded><category>CompSci</category></item><item><title>React Router, Vite and JWT Authentication</title><link>https://www.asbedb.dev/musings/react-vite-jwt/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/react-vite-jwt/</guid><description>Using JWT Authentication tokens on your React App

</description><pubDate>Tue, 18 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is meant to act as a summary and reference for implementing React Router with hashed authentication in your Vite project. The project is made as a Single User Login using an &lt;code dir=&quot;auto&quot;&gt;.env&lt;/code&gt; file as basis to store credentials. It can be modified for multiple use cases.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-react-router&quot;&gt;What is React Router?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Well according to React Router themselves.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;React Router is a multi-strategy router for React bridging the gap
from React 18 to React 19. You can use it maximally as a React
framework or as minimally as you want.
&lt;a href=&quot;https://reactrouter.com/home&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The site goes on to explain there are three modes available. For the purposes of this exercise we are primarily focused on declarative components.&lt;/p&gt;
&lt;p&gt;I recommend reading the &lt;a href=&quot;https://reactrouter.com/start/modes&quot;&gt;full documentation on React Router&lt;/a&gt; should additional requirements pop up.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;important-lessons&quot;&gt;Important Lessons&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As part of this exercise, the most important lesson to remember is the delineation between &lt;code dir=&quot;auto&quot;&gt;client&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;server&lt;/code&gt;. As we are using stored credentials, any interaction with those credentials needs to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ensure that the communication of those credentials is encrypted.&lt;/li&gt;
&lt;li&gt;Those credentials are not validated or exposed at a &lt;code dir=&quot;auto&quot;&gt;client&lt;/code&gt; level.&lt;/li&gt;
&lt;li&gt;Restrict access to the &lt;code dir=&quot;auto&quot;&gt;sever&lt;/code&gt; when it comes to matters related to credentials is critical.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This article assumes you are familiar with Node, React, and have deployed a Vite project as the basis for your web application. The code provided is written in TypeScript.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;file-setup&quot;&gt;File Setup&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Below are the main files we will be working with in your pre installed Vite folder structure.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/root-project&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├── /server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   ├── server.js&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   ├── .env&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├── /src&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   ├── App.tsx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   ├── /utils&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   │   └── ProtectedRoutes.tsx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   ├── /components&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   │   ├── Dashboard.tsx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   │   ├── Login.tsx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;│   │   └── Home.tsx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The following dependencies are used in this project across both client and server (break down to follow):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;vite&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^6.2.2&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;typescript&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;~5.7.2&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;react-dom&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;react-router-dom&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^7.3.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;cors&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^2.8.5&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;dotenv&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^16.4.7&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;express&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^4.21.2&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;jose&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^6.0.10&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;client&quot;&gt;Client&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;These modules should be targeting your Vite project folder, ensure relevant&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;package.json&lt;/code&gt; &lt;strong&gt;folders are updated with the correct dependencies.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The below NPM command’s can be utilised to install relevant dependencies client side:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vite&lt;/strong&gt;
To create a new Vite project with React and TypeScript template:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vite@latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;YOUR_PROJECT_NAME&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--template&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;react-ts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;react-dom&lt;/strong&gt;
To install &lt;code dir=&quot;auto&quot;&gt;react-dom&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;react-dom&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;react-router-dom&lt;/strong&gt;
To install &lt;code dir=&quot;auto&quot;&gt;react-router-dom&lt;/code&gt; (for routing):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;react-router-dom&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;server&quot;&gt;Server&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;These modules should be targeting your&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;server&lt;/code&gt; &lt;strong&gt;folder, to have a separate set of modules within your Vite project structure it is recommended to run the&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;npm init -y&lt;/code&gt; &lt;strong&gt;command in your server’s root directory prior to executing additional install commands.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The below NPM command’s can be utilised to install relevant dependencies server side:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;dotenv&lt;/strong&gt;
To install &lt;code dir=&quot;auto&quot;&gt;dotenv&lt;/code&gt; (hold our server side secrets):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dotenv&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;cors&lt;/strong&gt;
To install &lt;code dir=&quot;auto&quot;&gt;cors&lt;/code&gt; (allows for cross origin traffic filterting on our server):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cors&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;express&lt;/strong&gt;
To install &lt;code dir=&quot;auto&quot;&gt;express&lt;/code&gt; (to host our server):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;express&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;jose&lt;/strong&gt;
To install &lt;code dir=&quot;auto&quot;&gt;jose&lt;/code&gt; (JWT utility):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;jose&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Client Dependencies&lt;/strong&gt;: Make sure you’re installing the relevant modules (vite, react-dom, and react-router-dom) in the /src folder of your Vite project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server Dependencies&lt;/strong&gt;: Use npm init -y to initialize a package.json in your /server folder. Then, install the necessary server-side modules (dotenv, cors, express, and jose) there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment Configuration&lt;/strong&gt;: Ensure that your .env file is placed in the /server folder for storing sensitive information like SECRET_KEY and other configuration details.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;server-configuration&quot;&gt;Server Configuration&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;serverenv&quot;&gt;/server/.env&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The user management side of things will be extremely simple, whilst a more complex system can be applied to manage multiple users authenticating. This article will focus on a single-user login using an .env file. The methodology applied is still very relevant as we are managing an Authenticated user with local storage authentication and routing accordingly. The same logic can be applied to a validated SQL Row as an example.&lt;/p&gt;
&lt;p&gt;If you are unfamiliar with .env files and the significant role they may play in your application, I would recommend &lt;a href=&quot;https://medium.com/@sujathamudadla1213/what-is-the-use-of-env-8d6b3eb94843&quot;&gt;reading this article&lt;/a&gt; alongside doing some additional research.&lt;/p&gt;
&lt;p&gt;Below is an example .env file to examine:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ADMIN_USERNAME=admin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ADMIN_PASSWORD=admin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SECRET_KEY=changeme&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We have three variables being stored: a username, password and secret which our application will interface with to verify a successful login.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;serverserverjs&quot;&gt;server/server.js&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Let’s dive into our &lt;code dir=&quot;auto&quot;&gt;server.js&lt;/code&gt; code:&lt;/p&gt;
&lt;p&gt;The comment’s should provide a high level insight.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// We are importing the node installed components as a first step.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;express&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;express&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;SignJWT&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;jwtVerify&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;jose&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cors&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;cors&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* Setting our parameters for the server including variables assigned&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;to run our application.*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;express&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* Whilst this step is optional, it is highly recommended to set cross-origin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rules to control which origins can access your API and prevent unauthorised&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;access from untrusted networks.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Please note the origin and configure it accordingly for production builds.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;It’s recommended to use an environment variable to store your project’s root&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;domain, ensuring consistency across different environments and potential&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;variables. */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;corsOptions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;origin: &lt;/span&gt;&lt;span&gt;&apos;http://localhost/&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;methods: [&lt;/span&gt;&lt;span&gt;&apos;GET&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;POST&apos;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;allowedHeaders: [&lt;/span&gt;&lt;span&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;Authorization&apos;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Advising the application to use CORS and express&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app.&lt;/span&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;cors&lt;/span&gt;&lt;span&gt;(corsOptions))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app.&lt;/span&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt;(express.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Setting our variables from our .env file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SECRET_KEY&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; process.env.&lt;/span&gt;&lt;span&gt;SECRET_KEY&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ADMIN_USERNAME&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; process.env.&lt;/span&gt;&lt;span&gt;ADMIN_USERNAME&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; process.env.&lt;/span&gt;&lt;span&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// This is our login API request (more details below)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app.&lt;/span&gt;&lt;span&gt;post&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/api/login&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; req.body&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (username &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ADMIN_USERNAME&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; password &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { username }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SignJWT&lt;/span&gt;&lt;span&gt;(payload)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setProtectedHeader&lt;/span&gt;&lt;span&gt;({ alg: &lt;/span&gt;&lt;span&gt;&apos;HS256&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setIssuedAt&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setExpirationTime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;1h&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sign&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextEncoder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SECRET_KEY&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ token })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (err) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(err)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;500&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;Internal server error.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;Invalid username or password.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/*This is our JWT token verification middleware function (it checks the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;validity of the token for accessing protected routes).*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;verifyToken&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; req.headers[&lt;/span&gt;&lt;span&gt;&apos;authorization&apos;&lt;/span&gt;&lt;span&gt;]?.&lt;/span&gt;&lt;span&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;token) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;403&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;No token provided.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;jwtVerify&lt;/span&gt;&lt;span&gt;(token, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextEncoder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SECRET_KEY&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (err) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Token verification failed:&apos;&lt;/span&gt;&lt;span&gt;, err)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;Invalid or expired token.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// These are our protected routes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/api/protected&apos;&lt;/span&gt;&lt;span&gt;, verifyToken, (&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;This is a protected route&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* Finally, we initialise our app by listening on port 3000 (Port can&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;change or be removed for cloud instances like Heroku)*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app.&lt;/span&gt;&lt;span&gt;listen&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;3000&lt;/span&gt;&lt;span&gt;, () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Server running on port 3000&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;apilogin&quot;&gt;/api/login&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app.&lt;/span&gt;&lt;span&gt;post&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/api/login&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; req.body&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (username &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ADMIN_USERNAME&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; password &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { username }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SignJWT&lt;/span&gt;&lt;span&gt;(payload)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setProtectedHeader&lt;/span&gt;&lt;span&gt;({ alg: &lt;/span&gt;&lt;span&gt;&apos;HS256&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setIssuedAt&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setExpirationTime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;1h&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sign&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextEncoder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SECRET_KEY&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ token })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (err) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(err)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;500&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;Internal server error.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;Invalid username or password.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Below is a break down of the above code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Defining the Login Route&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;A POST request is set up at the /api/login endpoint to handle login requests.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Request Body Validation&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The incoming request body is de structured to extract username and password.&lt;/li&gt;
&lt;li&gt;These are compared with the ADMIN_USERNAME and ADMIN_PASSWORD environment variables, effectively checking credentials for a single user login.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;JWT Token Creation&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;If the credentials match, a JWT (JSON Web Token) is created using the username as the payload.&lt;/li&gt;
&lt;li&gt;The token is signed using the HS256 algorithm, with the SECRET_KEY encoded to ensure secure hashing.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Token Metadata&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The token is configured with:
&lt;ul&gt;
&lt;li&gt;setIssuedAt(): Marks the time the token was issued.&lt;/li&gt;
&lt;li&gt;setExpirationTime(‘1h’): Sets the token to expire after one hour.&lt;/li&gt;
&lt;li&gt;setProtectedHeader({ alg: ‘HS256’ }): Specifies the signing algorithm used.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;&lt;strong&gt;Returning the Token&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;The generated JWT token is returned to the client in the response as a token object.&lt;/li&gt;
&lt;li&gt;This token is then used for authenticating subsequent requests via middleware to access protected routes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h4 id=&quot;verifytoken&quot;&gt;verifyToken&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;verifyToken&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; req.headers[&lt;/span&gt;&lt;span&gt;&apos;authorization&apos;&lt;/span&gt;&lt;span&gt;]?.&lt;/span&gt;&lt;span&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;token) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;403&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;No token provided.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;jwtVerify&lt;/span&gt;&lt;span&gt;(token, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextEncoder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SECRET_KEY&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (err) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Token verification failed:&apos;&lt;/span&gt;&lt;span&gt;, err)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;({ message: &lt;/span&gt;&lt;span&gt;&apos;Invalid or expired token.&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Below is a break down of the above code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Extracting the Token from the Authorization Header&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The middle ware first checks the Authorization header and splits it by spaces. Typically, the header will have the format &lt;code dir=&quot;auto&quot;&gt;Bearer &amp;#x3C;token&gt;&lt;/code&gt;, so we extract the token portion after the space.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Checking if the Token Exists&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;We ensure that the token exists. If it’s missing or &lt;code dir=&quot;auto&quot;&gt;null&lt;/code&gt;, the middle ware responds with a &lt;code dir=&quot;auto&quot;&gt;403 Forbidden&lt;/code&gt; status and an error message saying “No token provided.”&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Verifying the Token’s Validity&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The token is then verified using jwtVerify function, which checks the token against the &lt;code dir=&quot;auto&quot;&gt;SECRET_KEY&lt;/code&gt;. If the token is valid and the signature matches, the middleware allows the request to proceed by calling &lt;code dir=&quot;auto&quot;&gt;next()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;If there’s any issue with the token (e.g., invalid, expired, or tampered with), an error is thrown and caught returning a status of &lt;code dir=&quot;auto&quot;&gt;401 Unauthorized&lt;/code&gt; denying access to the requested resource.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;summary-1&quot;&gt;Summary&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;At this point, we have a server with endpoints capable of handling authentication via JWT tokens. The client can request a token by providing valid credentials, and the server will issue a signed JWT. Subsequent requests to protected routes will require the token for access, ensuring that only authenticated users can reach sensitive endpoints.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;client-1&quot;&gt;Client&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;apptsx&quot;&gt;App.tsx&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;App.tsx&lt;/code&gt; file serves as a “gateway” to the different routes available in your application. Traditionally, this file contains the core logic for how a user can navigate to various features of your app. For the purposes of this article, we will implement exactly that. As suggested by the file structure, our three main landing pages will be the Home Page, Login Page, and Dashboard Page.&lt;/p&gt;
&lt;p&gt;Let’s have a look at the file and break it down.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;App.tsx&lt;/span&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./App.css&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { BrowserRouter &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; Router, Routes, Route } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Home &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/Home&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Login &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/Login&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Dashboard &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/Dashboard&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; ProtectedRoutes &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./utils/ProtectedRoutes&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;App&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Router&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Routes&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;Home&lt;/span&gt;&lt;span&gt; /&gt;} /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;ProtectedRoutes&lt;/span&gt;&lt;span&gt; /&gt;}&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/admin/dashboard&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;Dashboard&lt;/span&gt;&lt;span&gt; /&gt;} /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/admin&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;span&gt; /&gt;} /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Routes&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Router&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; App&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;import-statements&quot;&gt;Import Statements&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./App.css&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { BrowserRouter &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; Router, Routes, Route } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Home &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/Home&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Login &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/Login&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Dashboard &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/Dashboard&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; ProtectedRoutes &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./utils/ProtectedRoutes&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Here we are doing three main imports:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Global CSS&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;App.css&lt;/code&gt; file for styling, which is standard in Vite’s React TypeScript setup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React Router Components&lt;/strong&gt;: We import &lt;code dir=&quot;auto&quot;&gt;Router&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Routes&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;Route&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;react-router-dom&lt;/code&gt; to enable routing functionality in the application.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom Components&lt;/strong&gt;: We import the &lt;code dir=&quot;auto&quot;&gt;Home&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Login&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;Dashboard&lt;/code&gt; components from the components folder to render the respective pages.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;ProtectedRoutes&lt;/code&gt;: This is a custom utility component that handles protecting certain routes, ensuring only authenticated users can access them.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h4 id=&quot;understanding-browserrouter&quot;&gt;Understanding BrowserRouter&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;h5 id=&quot;router&quot;&gt;Router&lt;/h5&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Router&gt;&lt;/code&gt;is the parent element for our &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Routes&gt;&lt;/code&gt;, aligning location context (Determining the URL Path). It is a declarative element that can either be a &lt;code dir=&quot;auto&quot;&gt;StaticRouter&lt;/code&gt; (used for server-side rendering) or a &lt;code dir=&quot;auto&quot;&gt;BrowserRouter&lt;/code&gt; (used for client-side rendering). In this case, we have declared our router to be a BrowserRouter, as Vite is optimised for client-side rendering.&lt;/p&gt;
&lt;div&gt;&lt;h5 id=&quot;routes&quot;&gt;Routes&lt;/h5&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Routes&gt;&lt;/code&gt; component serves as the parent container that holds all of our &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Route&gt;&lt;/code&gt; logic. It allows the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Router&gt;&lt;/code&gt; to match the current URL and render the appropriate components based on the matching route.&lt;/p&gt;
&lt;div&gt;&lt;h5 id=&quot;route&quot;&gt;Route&lt;/h5&gt;&lt;/div&gt;
&lt;p&gt;All of our customisation will be done at this level. The &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Route&gt;&lt;/code&gt; is pointing our router to its final destination through the &lt;code dir=&quot;auto&quot;&gt;path&lt;/code&gt; property, returning the correct component based on the &lt;code dir=&quot;auto&quot;&gt;element&lt;/code&gt; property.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;jsx-return&quot;&gt;JSX Return&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;App&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Router&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Routes&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;Home&lt;/span&gt;&lt;span&gt; /&gt;} /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;ProtectedRoutes&lt;/span&gt;&lt;span&gt; /&gt;}&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/admin/dashboard&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;Dashboard&lt;/span&gt;&lt;span&gt; /&gt;} /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Route&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/admin&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;#x3C;&lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;span&gt; /&gt;} /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Routes&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Router&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; App&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Here’s a breakdown of the &lt;code dir=&quot;auto&quot;&gt;App.tsx&lt;/code&gt; JSX return:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Router Component&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Router&gt;&lt;/code&gt; wraps all of the routes to provide routing functionality based on the URL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Routes Component&lt;/strong&gt;: Inside the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Router&gt;&lt;/code&gt;, the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Routes&gt;&lt;/code&gt; component holds all the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Route&gt;&lt;/code&gt; definitions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Paths and Components&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Home Page&lt;/strong&gt;: The first route (&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Route path=&quot;/&quot; element={&amp;#x3C;Home /&gt;} /&gt;&lt;/code&gt;) corresponds to the root URL (&lt;code dir=&quot;auto&quot;&gt;/&lt;/code&gt;). When a user visits the root path, the Home component is rendered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Login Page&lt;/strong&gt;: The second route (&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Route path=&quot;/admin&quot; element={&amp;#x3C;Login /&gt;} /&gt;)&lt;/code&gt; is for the login page. It matches the &lt;code dir=&quot;auto&quot;&gt;/admin&lt;/code&gt; path and renders the Login component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dashboard Page (Protected)&lt;/strong&gt;: The third route (&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Route path=&quot;/admin/dashboard&quot; element={&amp;#x3C;Dashboard /&gt;} /&gt;)&lt;/code&gt; is nested inside a &lt;code dir=&quot;auto&quot;&gt;ProtectedRoutes&lt;/code&gt; wrapper. This ensures that only authenticated users can access the dashboard page at &lt;code dir=&quot;auto&quot;&gt;/admin/dashboard&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ProtectedRoutes Component&lt;/strong&gt;:
The &lt;code dir=&quot;auto&quot;&gt;ProtectedRoutes &lt;/code&gt;component is used to wrap the routes that require authentication. This ensures that only authenticated users can access the &lt;code dir=&quot;auto&quot;&gt;/admin/dashboard&lt;/code&gt; route. If the user is not authenticated, they will be redirected to the login page or shown an appropriate error message.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;summary-2&quot;&gt;Summary&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;App.tsx&lt;/code&gt; file is responsible for setting up routing in our application. It uses React Router’s &lt;code dir=&quot;auto&quot;&gt;BrowserRouter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Routes&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;Route&lt;/code&gt; components to render different views based on the current URL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Home&lt;/strong&gt;: Accessible via the root URL (&lt;code dir=&quot;auto&quot;&gt;/&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Login&lt;/strong&gt;: Available at &lt;code dir=&quot;auto&quot;&gt;/admin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;: A protected route at &lt;code dir=&quot;auto&quot;&gt;/admin/dashboard&lt;/code&gt; that requires authentication.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;utilsprotectedroutestsx&quot;&gt;/utils/ProtectedRoutes.tsx&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;ProtectedRoutes.tsx&lt;/code&gt; component acts as a wrapper for routes that require authentication. It checks if the user has a valid authorization token before allowing access to the child routes inside it. If the token is not valid or missing, the user is redirected to the login page.&lt;/p&gt;
&lt;p&gt;Let’s have a look at the file and break it down:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Outlet, useNavigate } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useEffect } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ProtectedRoutes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; localStorage.&lt;/span&gt;&lt;span&gt;getItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useNavigate&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;verifyToken&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (token) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;&apos;http://localhost:3000/api/protected&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;method: &lt;/span&gt;&lt;span&gt;&apos;GET&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;headers: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Authorization: &lt;/span&gt;&lt;span&gt;`Bearer ${&lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                &lt;/span&gt;&lt;span&gt;// Send the token in the Authorization header&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;response.ok) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (error) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Token verification failed:&apos;&lt;/span&gt;&lt;span&gt;, error)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;verifyToken&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}, [token, navigate])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; token &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;Outlet&lt;/span&gt;&lt;span&gt; /&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; ProtectedRoutes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;import-statements-1&quot;&gt;Import Statements&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Outlet, useNavigate } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We are not introduced to two new imports from &lt;code dir=&quot;auto&quot;&gt;react-router-dom&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;useNavigate&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;useNavigate&lt;/code&gt; function sends a navigation request when triggered, as of writing this article this is the preferred method of navigation suggested by React Router.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outlet&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;Outlet&lt;/code&gt; element returns nested &lt;code dir=&quot;auto&quot;&gt;Routes&lt;/code&gt; of the parent component.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h4 id=&quot;protectedroutes-function&quot;&gt;ProtectedRoutes() function&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ProtectedRoutes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; localStorage.&lt;/span&gt;&lt;span&gt;getItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useNavigate&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;verifyToken&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (token) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;&apos;http://localhost:3000/api/protected&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;method: &lt;/span&gt;&lt;span&gt;&apos;GET&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;headers: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Authorization: &lt;/span&gt;&lt;span&gt;`Bearer ${&lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;response.ok) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (error) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Token verification failed:&apos;&lt;/span&gt;&lt;span&gt;, error)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;verifyToken&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}, [token, navigate])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; token &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;Outlet&lt;/span&gt;&lt;span&gt; /&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Below is a break down of the above code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Setting Token and Navigation Variables&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The function will be relying on a locally stored &lt;code dir=&quot;auto&quot;&gt;token&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;localStorage&lt;/code&gt; to determine the users authorisation status.&lt;/li&gt;
&lt;li&gt;The function needs a &lt;code dir=&quot;auto&quot;&gt;navigate&lt;/code&gt; variable to trigger &lt;code dir=&quot;auto&quot;&gt;useNavigate&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Token Validation&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;useEffect&lt;/code&gt; hook is responsible for the validation based on changes to &lt;code dir=&quot;auto&quot;&gt;token&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;navigate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;We ensure that the token exists prior to validation attempts.&lt;/li&gt;
&lt;li&gt;The function then try’s the &lt;code dir=&quot;auto&quot;&gt;ap/protected&lt;/code&gt; endpoint where we have written our token verification function server side.&lt;/li&gt;
&lt;li&gt;Should the signatures match and the &lt;code dir=&quot;auto&quot;&gt;token&lt;/code&gt; is deemed valid the router allows for children via the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Outlet/&gt;&lt;/code&gt; to be rendered&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;If there’s any issue with the token (e.g., invalid, expired, or tampered with), an error is thrown any instance of the local &lt;code dir=&quot;auto&quot;&gt;token&lt;/code&gt; is deleted and the user is returned to the unprotected &lt;code dir=&quot;auto&quot;&gt;/admin&lt;/code&gt; page.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;dashboard-login-and-home&quot;&gt;Dashboard Login and Home:&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;Dashboard&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;Home&lt;/code&gt; components are quite open-ended. You can include whatever JSX you are comfortable with. The only suggestion I would make is including a &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;button&gt;&lt;/code&gt; component (or something similar) in the Dashboard to allow the user to log out.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;componentslogintsx&quot;&gt;/components/Login.tsx&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useNavigate } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setUsername&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setPassword&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;loading&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setLoading&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setError&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nav&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useNavigate&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;checkLogin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;React&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;FormEvent&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;e.&lt;/span&gt;&lt;span&gt;preventDefault&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;setLoading&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;http://localhost:3000/api/login&apos;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;method: &lt;/span&gt;&lt;span&gt;&apos;POST&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;headers: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&apos;application/json&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;body: &lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stringify&lt;/span&gt;&lt;span&gt;({ username, password }),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (response.ok) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; response.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;setItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;, token)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;nav&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin/dashboard&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; response.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;setError&lt;/span&gt;&lt;span&gt;(message &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Invalid username or password.&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (err) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;setError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;`An error occurred while trying to log in. Please try again later. ${&lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;setLoading&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;h1&lt;/span&gt;&lt;span&gt;&gt;Login&amp;#x3C;/&lt;/span&gt;&lt;span&gt;h1&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onSubmit&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{checkLogin}&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;&gt;Username:&amp;#x3C;/&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setUsername&lt;/span&gt;&lt;span&gt;(e.target.value)}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;required&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;&gt;Password:&amp;#x3C;/&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;password&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setPassword&lt;/span&gt;&lt;span&gt;(e.target.value)}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;required&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;submit&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{loading &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Signing in...&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Sign In&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{error &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text-red-500&quot;&lt;/span&gt;&lt;span&gt;&gt;{error}&amp;#x3C;/&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; Login&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above code should now be familiar and fairly easy to follow. If you have worked with React Query (Tanstack) before or any other API try/catch style requests, then it is clear we are pinging our API endpoint and validating a login form, returning a local storage item.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;componentsdashboardtsx&quot;&gt;/components/Dashboard.tsx&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre dir=&quot;ltr&quot;&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useNavigate } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react-router-dom&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Dashboard&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useNavigate&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;handleLogout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;authToken&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/admin&apos;&lt;/span&gt;&lt;span&gt;, { replace: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Dashboard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onClick&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{handleLogout}&gt;Logout&amp;#x3C;/&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; Dashboard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As previously mentioned, including a &lt;code dir=&quot;auto&quot;&gt;handleLogout&lt;/code&gt; function will allow the user to return to a logged-out state. Here, you can see we are removing the authentication token from local storage, causing the user to be returned to an unauthenticated state.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Overall, this was a great exercise with a lot to learn about how routing works. It taught me some great techniques in dealing with the security of communicating credentials and has given me some topics to research further. I’m excited to see where this journey leads me next.&lt;/p&gt;</content:encoded><category>WebDev</category></item><item><title>What I learned Deploying NGINX Proxy Manager</title><link>https://www.asbedb.dev/musings/nginx-proxy/</link><guid isPermaLink="true">https://www.asbedb.dev/musings/nginx-proxy/</guid><description>Detailed guide on my deployment of NGINX Proxy Manager

</description><pubDate>Sat, 15 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It was a beautiful morning in Melbourne. I had just gotten up preparing for my day. Today’s task was continuing a front end Vite project and reviewing some content on Data Structures and Algorithms (so, hot right now). When suddenly, a notification from one of my learning adjacent communities, unfurled a chain of events eventuating to the deployment of NGINX Proxy Manager.&lt;/p&gt;
&lt;p&gt;Along the journey there were a few moments oh which I felt were worthy to share, not only for those who are discovering the technology for the first time, but for myself also, a place to come back and reference should I need to revise.&lt;/p&gt;
&lt;p&gt;Before we start with the basics — throughout this process, Cloudflare as an organisation really stood out for me. It was my first time interacting with their products and I have to say kudos where kudos is due.&lt;/p&gt;
&lt;p&gt;I am sure there are some valid criticisms out there, however based on my personal use case, there were stark contrasts compared to the alternatives.&lt;/p&gt;
&lt;p&gt;In addition, they do a tremendous job in providing documentation and education on networking related topics (a page taken out of the book of Cisco no doubt.)&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-a-proxy-server&quot;&gt;What is a proxy Server?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The below image is a great representation of how a proxy server helps collate and add services related to traffic flowing out of a private network.&lt;/p&gt;
&lt;p&gt;As an example, this could be a school using web filtering to block access to content, an anonymiser to protect the identity of a user, or even a tool to help circumvent institutional browsing restrictions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;739&quot; height=&quot;370&quot; src=&quot;https://www.asbedb.dev/_astro/forward-proxy.CNUcypcY_4yssP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image Source: &lt;a href=&quot;https://www.cloudflare.com/en-au/learning/cdn/glossary/reverse-proxy/&quot;&gt;https://www.cloudflare.com/en-au/learning/cdn/glossary/reverse-proxy/&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“A forward proxy, often called a proxy, proxy server, or web proxy, is a server that sits in front of a group of client machines. When those computers make requests to sites and services on the Internet, the proxy server intercepts those requests and then communicates with web servers on behalf of those clients, like a middleman.” — &lt;a href=&quot;https://www.cloudflare.com/en-au/learning/cdn/glossary/reverse-proxy/&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-a-reverse-proxy&quot;&gt;What is a reverse proxy?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As you may have guessed, a reverse proxy sits in front of web servers and controls how client requests reach them, rather than controlling outbound client traffic like a forward proxy. (the two are not mutually exclusive and can work in tandem).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;438&quot; src=&quot;https://www.asbedb.dev/_astro/reverse-proxy.LYcY2dn7_Z1h19YG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image Source: &lt;a href=&quot;https://www.cloudflare.com/en-au/learning/cdn/glossary/reverse-proxy/&quot;&gt;https://www.cloudflare.com/en-au/learning/cdn/glossary/reverse-proxy/&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“A reverse proxy is a server that sits in front of web servers and forwards client (e.g. web browser) requests to those web servers “ – &lt;a href=&quot;https://www.cloudflare.com/en-au/learning/cdn/glossary/reverse-proxy/&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;h2 id=&quot;why-have-a-reverse-proxy-cant-you-just-link-directly-to-a-server&quot;&gt;Why have a reverse proxy can’t you just link directly to a server?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Reverse proxies are typically implemented to help increase security, performance, and reliability. Yes, you can link directly to a server however this practice comes with many risks including (and not limited to) making it easier for threat actors seek holes in your server’s security.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;nginx&quot;&gt;NGINX&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As the title of this article suggests we are primarily looking at NGINX Proxy Manager — NGINX (Pronounced Engine X [or _Ehn Jinx if you are cool like me and mispronounce GIF as well]_). Is one of the many unsung heroes of web, helping serve you web content since 2004.&lt;/p&gt;
&lt;p&gt;Whilst most of us browse the internet with a Windows device. A lot of the servers are running on open-source Linux based applications and operating systems.&lt;/p&gt;
&lt;p&gt;One thing I do want to note, which is important to understanding the nature of proxy managers and effectively can be applied to any application, a mantra I regularly chant for software I’m developing, implementing or running.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Use the right tool for the right job”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;NGINX Proxy Manager is primarily used for web proxy filtering and web traffic. It is not a tool to manage proxies into non web traffic servers (gaming servers as an example) — There are other ways to achieve that.&lt;/p&gt;
&lt;p&gt;NGINX is a collection of web server applications which includes reverse proxy, load balancing, caching and HTTPS. Like most things popular and open-source, it has a &lt;a href=&quot;https://github.com/nginx/nginx&quot;&gt;passionate community of contributors&lt;/a&gt; maintaining and managing the repository inspiring over 7,000 forks (potential offshoots) and over 26,000 stars (the GitHub term for likes). It also serves as the core to the NGINX Proxy Manager.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-are-the-prerequisites-loosely&quot;&gt;What are the prerequisites (loosely).&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;There are a few ways to approach the next steps — so I won’t go into detail, rather I will provide guidance and general advice on how it may work for you.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Hardware —&lt;/strong&gt; As the images in the introduction suggest, whether it’s in the public cloud or you are self-hosting. To set up a proxy server effectively you need a minimum of two servers. One acting as your reverse proxy device and one that is hosting your web services/applications. You can technically utilise the same server to run a proxy manager and web apps however this will detract from the security benefits provided.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;2. The ability to run Linux on the hardware.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; &lt;strong&gt;Some understanding of Docker technology&lt;/strong&gt; — will go a long way in simplifying this process. My deployment utilised Docker to deploy a container running NGINX Proxy Manager which had the service up and running in no time. (&lt;a href=&quot;https://docs.docker.com/get-started/docker-overview/&quot;&gt;See docker documentation&lt;/a&gt; if you are unsure on what Docker)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; &lt;strong&gt;A domain&lt;/strong&gt; — that will act as the address to your server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; &lt;strong&gt;Some (Not necessarily in depth) networking knowledge&lt;/strong&gt; — At a minimum understanding what purpose IP Addresses, Ports and Firewalls serve and how you could configure those particularly on your host machine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6.&lt;/strong&gt; &lt;strong&gt;If you are self-hosting&lt;/strong&gt; — policies you should implement on your host when it comes to tunnelling to your proxy server along side firewall rules, this is very important in managing what is exposed to the rest of your network.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;how-i-implemented-the-stack-to-work-for-me&quot;&gt;How I implemented the stack to work for me.&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Again the reason I have titled this section this way is because everyone’s configurations will differ slightly, in my scenario I was hosting my proxy manager on a VPS (Virtual Private Server) and pointing it to another VPS. More commonly the manager is used to tunnel to a server that is self-hosted to ensure host IP is obfuscated reducing risk to an administrator’s home network.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;virtual-private-server&quot;&gt;Virtual Private Server&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;364&quot; src=&quot;https://www.asbedb.dev/_astro/vps.DcaoNXlq_Z1RUTmX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the Binary Lane Website&lt;/p&gt;
&lt;p&gt;The first thing I needed was a VPS. This wasn’t my first time requiring such a service and as I am running a developer environment where things aren’t necessarily going to be permanent, I decided to use a great Australian service provider I have used in the past called &lt;a href=&quot;https://www.binarylane.com.au&quot;&gt;BinaryLane&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With some of the VPS options starting at $4 a month it’s just a no brainer to me. I’m sure there’s plenty out there this just comes down to personal choice and what features are important for you. As a side note the proxy manager on it’s own has very minimal hardware requirements and can even run on a Raspberry Pi.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;docker&quot;&gt;Docker&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Once our Ubuntu server was up and running in the cloud, we immediately had the option to remotely connect and work on it just like you would a virtual or local server. I ran your regular Linux upgrade, install get commands to ensure everything was up to date and proceeded to &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot;&gt;install docker&lt;/a&gt; as it would be the primary method to install/manage/maintain and deploy images for me.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;447&quot; src=&quot;https://www.asbedb.dev/_astro/dockerdocs.3FWcdbrp_5zVyu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A screenshot of Docker Documenation&lt;/p&gt;
&lt;p&gt;From here there are multiple routes available — for those more experienced with Docker following the &lt;a href=&quot;https://nginxproxymanager.com/setup/&quot;&gt;installation guide for NGINX Proxy Manager&lt;/a&gt; should be self-explanatory . That said there is a more guided approach available if the task is daunting.&lt;/p&gt;
&lt;p&gt;I know there are plenty of CLI (Command Line Interface) enthusiasts out there that despise the idea of a Graphical User Interface (NeoVIM advocacy intensifies) thankfully there are also developers who understand humans can also process things in layouts and interfaces and sometimes (hear me out), it makes it easier for us to complete/achieve things if they are laid out a certain way.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;portainer&quot;&gt;Portainer&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;385&quot; src=&quot;https://www.asbedb.dev/_astro/portainer.hyltoRyO_Z1XVpaR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of Portainer&lt;/p&gt;
&lt;p&gt;Portainer is a tool/Docker application (with a free option available) allowing you to manage/visualise and deploy docker containers through a Web GUI, you deploy it as a docker app and proceed to browse to your &lt;strong&gt;serverip:port&lt;/strong&gt; to complete the setup. From there you can run the rest of your docker experience through the browser with minimal CLI interaction.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;472&quot; src=&quot;https://www.asbedb.dev/_astro/portainer-2.DmXZmRDn_21cwmJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of Portainer Settings Where App templates can be found&lt;/p&gt;
&lt;p&gt;One of the handy features Portainer brings to the table is the integration of application templates (App Templates) making deploying your containers a breeze. Communities maintain and share beneficial templates, typically as JSON files on GitHub, allowing others to use them.&lt;/p&gt;
&lt;p&gt;For my deployment I used the &lt;a href=&quot;https://github.com/novaspirit/pi-hosted&quot;&gt;pi-hosted&lt;/a&gt; template which can be found &lt;a href=&quot;https://raw.githubusercontent.com/pi-hosted/pi-hosted/master/template/portainer-v2-amd64.json&quot;&gt;here&lt;/a&gt;, depending on the version of NGINX Proxy Manager you seek, there may be a need for a different application template that includes your version.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;108&quot; src=&quot;https://www.asbedb.dev/_astro/nginx-proxy-manager.DlyPW2xO_Z2c3eoG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of NGINX Proxy Manager v2 with Sqlite in App Templates&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;odd-portainer-issue&quot;&gt;Odd Portainer Issue&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Side Note:&lt;/em&gt; As with a lot of things which are free and highly customisable I hit an “odd” issue here — depending on when you are reading this either this method is outdated, or the issue has been resolved.&lt;/p&gt;
&lt;p&gt;That said using the above JSON (and in general any other JSON I tried) I found that there was a visual glitch which re renders my search results rather than letting me proceed with the deployment of the container — the band aid solution to this is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Ensure your search results are correct, and your required container is displayed.&lt;br&gt;
&lt;strong&gt;2.&lt;/strong&gt; Go back to your app settings and modify your JSON address slightly (I just changed v2 to v3). &lt;em&gt;This technically is not a real file from what I have gathered it removes the polling to render the app list.&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;3.&lt;/strong&gt; Return to your search results and you should be able to click through to deploy container.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;final-menu-for-deployment&quot;&gt;Final Menu for Deployment&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;883&quot; src=&quot;https://www.asbedb.dev/_astro/nginx-proxy-manager-2.DfquxK8m_ZWF9HG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of a Container Ready to install in Portainer&lt;/p&gt;
&lt;p&gt;From here you are free to deploy the proxy manager accordingly — ensure to select the correct network when deploying. By default, the container is deployed to ports 443, 80 and 81.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;finalising-nginx-proxy-manager-installation&quot;&gt;Finalising NGINX Proxy Manager Installation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;You will now have access to your NGINX Proxy Manager through a Web GUI on port 81 (if you are using default ports). Your initial login will be set to the default of&lt;/p&gt;
&lt;p&gt;Email: &lt;a href=&quot;mailto:admin@example.com&quot;&gt;admin@example.com&lt;/a&gt;&lt;br&gt;
password: changeme&lt;/p&gt;
&lt;p&gt;The first login will prompt you to change these settings immediately.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;domain-management-cloudflare&quot;&gt;Domain Management (Cloudflare)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;254&quot; src=&quot;https://www.asbedb.dev/_astro/cloud-market.BQNNIr4U_Z1mXh2T.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image Source: cloudflare.com&lt;/p&gt;
&lt;p&gt;Here is where our path’s may split — My scenario required me to take some additional steps to move my name servers to Cloudflare yours could be different.&lt;/p&gt;
&lt;p&gt;If for some reason you are having trouble with your domain name service provider, whether it’s revoked access to API’s (issue I had) or something else. The good news is Cloudflare at its free tier gives you everything you need to do this step.&lt;/p&gt;
&lt;p&gt;The domain itself is of course going to be pointed to your proxy manager. The Domain Name System (DNS) layer provided is critical to ensuring you can resolve to these services with a layer of security through the browser (Secure Sockets Layer — SSL). &lt;em&gt;Yes I know it’s TLS now, trying to keep it simple.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;NGINX Proxy Manager creates and authorises these SSL certificates through a service called Let’s Encrypt and if your DNS provider allows it, you can automatically update those certificates without the need to manually intervene. This would be through an application programming interface (API) managed by the provider.&lt;/p&gt;
&lt;p&gt;Why automate? — for arguments sake let’s say your domain is foo.com, browsing to this page resolves to a basic home page running on a standard web server you are hosting.&lt;/p&gt;
&lt;p&gt;You decide to run another web server for your blog but now you need an address to point to that server.&lt;/p&gt;
&lt;p&gt;If the environment is setup correctly you will have the ability to make browsing to multiple routes predictable utilising an automated system that creates subdomains (blog.foo.com as an example), generates SSL certificates and manages those for the life of the configuration — steps that would be extremely tedious to manage on a regular basis as your infrastructure/services grow and change.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;so-what-did-i-do-with-cloudflare&quot;&gt;So, what did I do with Cloudflare?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;As mentioned, I quickly realised I needed to move my nameservers to Cloudflare as I had an issue with the original provider revoking access to API’s (needed for certificate automation).&lt;/p&gt;
&lt;p&gt;I made an account, selected the free tier and used an automated service to transfer the existing DNS records across. In my scenario I needed to update the name servers to Cloudflare for the transfer to take place. (the wizard they provide is self-explanatory).&lt;/p&gt;
&lt;p&gt;From here there are two DNS Records I was primarily interested in — again this may be different for you.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;853&quot; height=&quot;329&quot; src=&quot;https://www.asbedb.dev/_astro/a-name.BFGDmxX9_Z1E2MqO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A screenshot of the cloudflare DNS Record Management System&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A Record —&lt;/strong&gt; A stands for Address and is the most fundamental type of DNS it contains the IP address of a given domain. example, if you pull the DNS records of cloudflare.com, the A record currently returns an IP address of 104.17.210.9 (Note: A records only hold IPV4 Addresses for IPV6 you need AAAA).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CNAME Record —&lt;/strong&gt; CNAME stands for canonical name in short these are used as an alias and commonly provided as a record for a sub domain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Additional note in DNS records to consider&lt;/strong&gt; — naming conventions utilise the &lt;strong&gt;*&lt;/strong&gt; character as a wildcard helping route anything that might be utilised as input in place. In the below example we use the wildcard to cover sub domains.&lt;/p&gt;
&lt;p&gt;I have put together a table further explaining how this can be implemented:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Example Domain:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;foo.com&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With the below DNS Records including the wildcard for the second CNAME.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;116&quot; src=&quot;https://www.asbedb.dev/_astro/wildcard.Dg9bXgYm_Z2kvAAV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example DNS Table&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We would reroute any s&lt;/em&gt;&lt;strong&gt;&lt;em&gt;ubdomain.foo.com&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;alongside the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;foo.com&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;domain itself to the IP&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Address of our reverse proxy server&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;thus having all traffic to that address now managed by our reverse proxy server.&lt;/em&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;quick-side-rant-api-related&quot;&gt;Quick Side Rant (API Related)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot; src=&quot;https://www.asbedb.dev/_astro/buggy.D36tUVir_Z1qCSSP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image Source: &lt;a href=&quot;https://www.behance.net/gallery/10500093/Dinosaur-Car-Named-Dinobeelte&quot;&gt;https://www.behance.net/gallery/10500093/Dinosaur-Car-Named-Dinobeelte&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One of the things I have become a lot more appreciative of is organisations that don’t maximise their profits at the cost of those who make their products more desirable. I’ll give you an example.&lt;/p&gt;
&lt;p&gt;Let’s make up a fictitious car make and model for this analogy. The &lt;em&gt;Hundord Raploster&lt;/em&gt; — (why not) — and let’s say the &lt;em&gt;Raploster&lt;/em&gt; on launch had an average at best reception.&lt;/p&gt;
&lt;p&gt;One day, a group of clever engineers realised that the &lt;em&gt;Raploster&lt;/em&gt; had a system or mechanism that if modified, could save the average consumer half a tank of fuel every week. They build this system — believe in a philosophy that allows everyone to have access to this great technology and push it out there for people to improve on modify and use.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hundord&lt;/em&gt; in it’s great wisdom sees a potential to maximise profits, the next iteration of the car now has a padlock on the mechanism that allows for you to implement this modification, They advise &lt;em&gt;Raploster&lt;/em&gt; owners that the padlock can only be unlocked with a key magically provided by &lt;em&gt;Hundord&lt;/em&gt; (With the payments usually being a subscription model in which &lt;em&gt;Hundlord&lt;/em&gt; can change the padlock and make you pay more for different tiers of padlock keys!).&lt;/p&gt;
&lt;p&gt;I think the analogy should resonate with now — simply put, don’t alienate a community of enthusiasts who make your product better for small profit gains. These communites grow demand, trust and market presence. Alienating them means losing sales as they will go straight to your competitor and give them the free hype and expertise.&lt;/p&gt;
&lt;p&gt;On that note…&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;cloudflare-api-and-certbot&quot;&gt;Cloudflare API (and Certbot)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;764&quot; height=&quot;499&quot; src=&quot;https://www.asbedb.dev/_astro/cflareapi.BicWHKnt_Mn7xl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the Cloudflare API Menu&lt;/p&gt;
&lt;p&gt;Yes, the Cloudflare API is available to use on the free tier. It’s super simple to setup and through a few clicks you can get your API key. You can also segregate your keys to ensure interfaces are only accessible to the zones you have approved should you have multiple zones being managed.&lt;/p&gt;
&lt;p&gt;This will serve as the interface between your proxy server and Cloudflare.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;nginx-proxy-manager&quot;&gt;NGINX Proxy Manager&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;A quick reminder before we continue:&lt;/em&gt;&lt;/strong&gt; As mentioned the reverse proxy method is one of many ways to add a security layer between your server and client. &lt;strong&gt;It does not replace other techniques&lt;/strong&gt; such as firewall management and traffic segregation, a robust security strategy must always be considered on the host itself — food for thought when you have nodes publicly accessible.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;875&quot; height=&quot;248&quot; src=&quot;https://www.asbedb.dev/_astro/nginx-dash.CYOpEJZ8_ZiGqu6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the NGINX Proxy manager homepage&lt;/p&gt;
&lt;p&gt;And with that lets return to NGINX Proxy Manager ready to finalise our routes. This journey is near its completion and if you have made it this far the good news is the last few steps are simple.&lt;/p&gt;
&lt;p&gt;This is in no way an in-depth guide to the dashboard or the various options available, my use case was a simple redirect. That said, there are plenty of features you can explore outside of this context highly useful for different scenarios.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;871&quot; height=&quot;266&quot; src=&quot;https://www.asbedb.dev/_astro/nginx-dash-2.DC5E3YfW_2fpru0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of NGINX Proxy Manager SSL Certificates Page&lt;/p&gt;
&lt;p&gt;The first step to take was to ensure we had SSL Certifications set up with Let’s Encrypt alongside a valid connection to our Cloudflare API — by now we have a key and all relevant details ready to go.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;304&quot; height=&quot;450&quot; src=&quot;https://www.asbedb.dev/_astro/lets-encrypt.DQJFSK_D_Z10bMOF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot for adding Encryption Certificates&lt;/p&gt;
&lt;p&gt;The menu presented asks for your domains, a valid email alongside your DNS provider (in our case Cloudflare). For the domain field it is important to include both &lt;strong&gt;base domain (foo.com)&lt;/strong&gt; along with your &lt;strong&gt;wildcard domain (*.foo.com)&lt;/strong&gt; you must &lt;strong&gt;press enter&lt;/strong&gt; after typing &lt;strong&gt;each domain.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I will say the UI experience is not overly intuitive the first time you use it, so these small mistakes are likely to happen.&lt;/p&gt;
&lt;p&gt;Once you have completed this step and everything is green on your dashboard. You can now navigate to your base domain, and it should return a &lt;strong&gt;congratulations&lt;/strong&gt; page with a valid SSL certificate.&lt;/p&gt;
&lt;p&gt;The contents of this page do acknowledge that the domain points to a proxy server. This might not be something you want to advertise, thankfully within the dashboard you can change the default site through the settings tab — if setup correctly any non-routed sub domain would redirect to this default site.&lt;/p&gt;
&lt;p&gt;Now that certifications are checked off we are ready to route some hosts!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;484&quot; height=&quot;530&quot; src=&quot;https://www.asbedb.dev/_astro/new-proxy-host.D-9JNBgn_Zry74i.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of proxy host popup&lt;/p&gt;
&lt;p&gt;Head on over to your Hosts Tab&gt;Proxy Hosts and hit the Add Proxy Host button — from here you can assign the following settings:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;· A domain or subdomain&lt;/strong&gt; — for example blog.foo.com (don’t forget to hit enter).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;· The forward hostname&lt;/strong&gt; — Address to your hosted server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;· Scheme of your host&lt;/strong&gt; — HTTP or HTTPS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;· Security Settings&lt;/strong&gt; provided through NGINX Proxy Manager around exploits and websockets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;· Access Lists&lt;/strong&gt; — Restrict who can access the host.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;486&quot; height=&quot;372&quot; src=&quot;https://www.asbedb.dev/_astro/new-proxy-host-ssl.CdTpw5D4_l0COC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Additionally SSL is important to configure (found in the pop up upper tabs) to avoid browser presented errors — Here you can assign your generated SSL certificate to your domain/subdomain&lt;/p&gt;
&lt;p&gt;🎉**And with that final step completed and the save button clicked, your host should now have a reverse proxy address that can be accessed in accordance with how you have set it up!**🎉&lt;/p&gt;</content:encoded><category>DevOps</category></item></channel></rss>