diff --git a/.gitignore b/.gitignore
index ea097fa..57010a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
node_modules
.idea
+flake.lock
+bun.lockb
# Output
.output
@@ -24,5 +26,3 @@ vite.config.js.timestamp-*
vite.config.ts.timestamp-*
-# Jet brains
-.idea
\ No newline at end of file
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..d9c36df
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,41 @@
+{
+ description = "Bun development flake. Adjust as needed";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+ flake-utils.url = "github:numtide/flake-utils";
+ };
+
+ outputs = { self, nixpkgs, flake-utils, ... }:
+ flake-utils.lib.eachDefaultSystem (system:
+ let
+ pkgs = import nixpkgs { inherit system; };
+ in
+ {
+ # Define the development shell.
+ # When you run `nix develop` (or direnv activates), you'll enter this shell.
+ devShells.default = pkgs.mkShell {
+ # List all the development tools you need available in this shell's PATH.
+ packages = with pkgs; [
+ # Add packages here...
+ bun
+ ];
+
+ # Define the shell that will be executed.
+ # Here, we explicitly use zsh.
+ # Note: pkgs.zsh needs to be included in `packages` or `nativeBuildInputs`
+ # for it to be found in the shell's environment. `inherit pkgs.zsh;` is concise.
+ inherit (pkgs) zsh;
+
+ # Environment variables and commands to run when the shell starts.
+ shellHook = ''
+ # Add any exports, hooks, aliases, or anything else here
+
+ # Exec zsh to replace the current shell process with zsh.
+ # This ensures your prompt and zsh configurations load correctly.
+ exec zsh
+ '';
+ };
+ }
+ );
+}
diff --git a/src/journal/SOLID: Does They Matter.md b/src/journal/SOLID: Does They Matter.md
new file mode 100644
index 0000000..9de47f1
--- /dev/null
+++ b/src/journal/SOLID: Does They Matter.md
@@ -0,0 +1,270 @@
+Date: 2025-11-??
+Desc: SOLID principles are very well known, but are they really that important?
+# SOLID: Do They Matter
+
+
+
+###### Image source: [Geeks for Geeks](https://www.geeksforgeeks.org/system-design/solid-principle-in-programming-understand-with-real-life-examples/)
+
+
+###### Author: Hayden Hargreaves
+
+###### Published: 11/??/2025
+
+## Background
+
+If you have not heard of the SOLID principles, you are in the right place! SOLID is an acronym for
+the first five **object-oriented design** (OOD) principles, invented by Robert C. Martin who is commonly
+known as [Uncle Bob](https://en.wikipedia.org/wiki/Robert_C._Martin). The goal of the SOLID principles is to establish best practices for developing
+maintainable and extensible software. Adapting these principles into your own code can help you avoid
+[code smells](https://en.wikipedia.org/wiki/Code_smell), refactor code and develop Agile software.
+
+>
+> "If you think good architecture is expensive, try bad architecture." ~Uncle Bob
+>
+
+The five principles are as follows:
+- **S** - Single-responsibility Principle
+- **O** - Open-closed Principle
+- **L** - Liskov Substitution Principle
+- **I** - Interface Segregation Principle
+- **D** - Dependency Inversion Principle
+
+This article will serve as an *introduction*, not a complete guide. However, a simple understanding
+of the principles can help you level up as a developer!
+
+
+## Object-Oriented Programming Refresher
+
+Some basic knowledge of object-oriented programming (OOP) is expected for best success when reading this
+article. Regardless, a simple refresher can't hurt! Object-oriented programming is exactly as it sounds,
+**object based programming.** Code written in OOP languages is organized into "objects", which are self-contained
+units that combine data (attributes) and functions that operate on the data (methods). The OOP approach
+*can* simplify complex systems, promote code reusability and modularity which makes OOP code easier to
+maintain and scale. There are four main principles of object-oriented principles: **encapsulation**,
+**inheritance**, **abstraction** and **polymorphism**. I will write a dedicated article about these four
+principles soon, which will also be found here in my journal.
+
+To understand the SOLID principles, the most important thing to remember is **what a class is;** a
+class is a blueprint or template for creating objects. An object is a unique instance of a class.
+
+
+There are many object-oriented languages and the concepts taught in this article are not unique to a
+specific language, they can be applied to any language which implements OOP structure (even Python!).
+Some languages include: **[C++](https://en.wikipedia.org/wiki/C%2B%2B)**, **[C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language))**, **[Java](https://en.wikipedia.org/wiki/Java_(programming_language))**, **[Ruby](https://en.wikipedia.org/wiki/Ruby_(programming_language))**, and more. The examples provided in this article
+will be in C++, but as mentioned previously, they apply to any OOP language!
+
+## Single-Responsibility Principle
+
+The **[Single-Responsibility Principle](https://en.wikipedia.org/wiki/Single-responsibility_principle)** states:
+
+>
+> "A class should have one and only one reason to change, meaning that a class should have only one
+> job." ~Robert "Uncle Bob" Martin
+>
+
+### The Misunderstood Principle
+
+The SRP is the simplest, yet most commonly misunderstood principle. The goal of the SRP is to **prevent
+unexpected side effects** by keeping each *unit* (class) simple and with only a single purpose. A class
+that has many responsibilities will frequently need to be changed as requirements change, which can
+lead to more bugs. When a class is changed, it can impact classes that depend on it, which can result
+in unexpected bugs in code that did not *seem* to change. However, a class with a **single responsibility**
+will be changed much less, reducing the number of sneaky bugs that result from code refactors.
+
+
+### Easier to Understand
+
+Another benefit of implementing the single-responsibility principle is that resulting code becomes much
+easier to understand. A class that has a single purpose is much easier to explain to a co-worker or intern.
+However, this is another common place of misunderstanding. Some developers take the SRP a bit too far
+and **over-simplify** their code, for example: writing a new class for each function!? When they later
+want to write some real code, they need to inject dozens of dependencies just to achieve a single task!
+
+There exists a healthy balance of responsibility and simplicity, which can be hard to understand at first.
+The best thing you can do is keep the SRP in mind, but not follow it **too strictly**. Do not use it as
+your "programming bible." Use common sense, there is no point in classes that only contain a single function!
+
+### Code Example
+
+To display this concept we will look at a **Shape** class which needs to be draw to an output. Below
+is an implementation which does not adhere to the single-responsibility principle.
+
+```cpp
+class Shape {
+public:
+ Shape(double w, double h) : width(w), height(h) {};
+
+ // Responsibility 1: Core Business Logic (Math)
+ double calculateArea() const {
+ return this->width * this->height;
+ }
+
+ // Responsibility 2: Presentation/Output (Drawing)
+ void draw() const {
+ // Imagine complex rendering code here...
+ std::cout << "Drawing a rectangle of size " << this->width << "x"
+ << this->height << "\n";
+ }
+
+private:
+ double width;
+ double height;
+};
+```
+
+However, as the comments note, this class has more than one responsibility. The class is responsible
+for storing shape data and computing the area as well as rendering it to the output. Imagine we have
+hundreds of shapes, we don't want to write hundreds of different ways to render each shape! This
+example is a tad simple, but it helps us understand why we need to split responsibilities as code scales.
+
+To fix this, we can create a **ShapeRenderer** class and simplify our **Shape** class.
+
+```cpp
+// 1. ShapeSRP: Responsibility = Core Business Logic ONLY (Data and Math)
+class ShapeSRP {
+public:
+ ShapeSRP(double w, double h) : width(w), height(h) {}
+
+ // Methods for data access and core calculation
+ double getWidth() const { return width; }
+ double getHeight() const { return height; }
+
+ // Stays here as it's the core purpose of the data
+ double calculateArea() const {
+ return width * height;
+ }
+
+private:
+ double width;
+ double height;
+};
+
+// 2. ShapeRenderer: Responsibility = Presentation/Output ONLY
+class ShapeRenderer {
+public:
+ // This class's sole job is to handle how the Shape is visualized.
+ void draw(const ShapeSRP& shape) const {
+ // The rendering logic is isolated here.
+ std::cout << "--- Graphics Renderer Output ---\n";
+ std::cout << "Drawing a shape with area: " << shape.calculateArea() << "\n";
+ std::cout << "Using dimensions: " << shape.getWidth() << "x" << shape.getHeight() << "\n";
+ }
+};
+```
+
+Now we have successfully implemented a scalable and modular class which can be used by many shapes!
+Using polymorphism we can achieve an even better solution, which is not the focus of this article, but
+further encourages the idea.
+
+```cpp
+#include
+#include
+
+// 1. Abstract Base Class: Defines the contract for all shapes
+class Shape {
+public:
+ // Core Business Logic: Must be implemented by derived classes
+ virtual double calculateArea() const = 0;
+
+ // Virtual destructor is crucial for proper cleanup with polymorphism
+ virtual ~Shape() = default;
+};
+
+// Concrete Shape 1: Rectangle
+class Rectangle : public Shape {
+public:
+ Rectangle(double w, double h) : width(w), height(h) {}
+
+ // Implements the specific area calculation for a rectangle
+ double calculateArea() const override { return width * height; }
+
+ // Getters needed for the renderer
+ double getWidth() const { return width; }
+ double getHeight() const { return height; }
+
+private:
+ double width;
+ double height;
+};
+
+// Concrete Shape 2: Circle
+class Circle : public Shape {
+public:
+ Circle(double r) : radius(r) {}
+
+ // Implements the specific area calculation for a circle
+ double calculateArea() const override { return M_PI * radius * radius; }
+
+ // Getters needed for the renderer
+ double getRadius() const { return radius; }
+
+private:
+ double radius;
+};
+
+// Renderer Interface (Contract for drawing)
+class Renderer {
+public:
+ // The renderer must be able to handle any kind of Shape
+ virtual void render(const Shape &shape) const = 0;
+ virtual ~Renderer() = default;
+};
+
+// Console Renderer Implementation
+class ConsoleRenderer : public Renderer {
+public:
+ void render(const Shape &shape) const override {
+ std::cout << "\n--- Console Output (Simple) ---\n";
+
+ // This dynamic_cast is often necessary when a Renderer needs specific data,
+ // but it's important to keep the logic here, separate from the Shape class!
+ if (const auto *rect = dynamic_cast(&shape)) {
+ std::cout << "Type: Rectangle\n";
+ std::cout << "Dimensions: " << rect->getWidth() << "x"
+ << rect->getHeight() << "\n";
+ } else if (const auto *circ = dynamic_cast(&shape)) {
+ std::cout << "Type: Circle\n";
+ std::cout << "Radius: " << circ->getRadius() << "\n";
+ } else {
+ std::cout << "Type: Unknown Shape\n";
+ }
+
+ // **Polymorphic call:** This works for all shapes!
+ std::cout << "Calculated Area: " << shape.calculateArea() << "\n";
+ }
+};
+```
+
+This has taken our shape renderer example to new heights! But by now, you should be able to understand
+the pros and cons of the **S**ingle-responsibility principle.
+
+
+## Open/Closed Principle
+
+define the rule
+why it exists
+what is attempts to achieve
+
+
+## Liskov Substitution Principle
+define the rule
+why it exists
+what is attempts to achieve
+
+
+## Interface Segregation Principle
+define the rule
+why it exists
+what is attempts to achieve
+
+
+## Dependency Inversion Principle
+define the rule
+why it exists
+what is attempts to achieve
+
+## SOLID Only For OOP?
+
+
+## "Don't Repeat Yourself" From Uncle Bob
diff --git a/src/journal/What is a Functional Programming Language: Featuring Elixir.md b/src/journal/What is a Functional Programming Language: Featuring Elixir.md
index dd15e84..0ffd67c 100644
--- a/src/journal/What is a Functional Programming Language: Featuring Elixir.md
+++ b/src/journal/What is a Functional Programming Language: Featuring Elixir.md
@@ -9,7 +9,7 @@ Desc: I have decided to begin the journey of learning functional programming. He
###### Author: Hayden Hargreaves
-###### Published: 05/??/2025
+###### Published: 05/21/2025
## Background
@@ -287,17 +287,8 @@ a full stack web application using the Phoenix Framework. This app will allow us
a love for cooking and having to store all my recipes in my notes app is cumbersome. Plus, my parents are **amazing** cooks and I would to be able to "borrow"
their recipes and save them for myself, without having to copy them manually.
-
-##### More about the app, and what I liked and hated.
-
-This article is under construction. Come back later for more!
-
-
## Elixir Review
-After writing a *quality* full stack application I have learned enough about the language to develop an opinion.
-
-This is what I found...
-
-
+The learning process has been put on pause to focus on work, but when I make it back to
+Elixir, I will finish the conclusion!
diff --git a/static/journal/SOLID.png b/static/journal/SOLID.png
new file mode 100644
index 0000000..a184476
Binary files /dev/null and b/static/journal/SOLID.png differ