Whether you need a high-performance web application, full-stack architecture advisory, or an engineer who ships with urgency and care.
Jump directly on my calendar to talk about goals, timeline, and fit.
Bubble Sort is a sorting algorithm. It works by comparing two neighbouring elements and swapping them until the list is sorted.
Compare: Look at the first two elements
Swap: If the first element is greater than the second element, swap them.
Move: Move to the next pair and repeat until you reach the end of the list.
Repeat: Go back to the start and repeat the process until the list is sorted.
Example
Consider the following list [4, 6, 1, 3, 5, 2]
Compare the first two elements. 4 and 6.
6 is greater than 4. Move to the next index.
Move to the next pair, 6 and 1.
6 > 1, swap them.
The new list becomes [4, 1, 6, 3, 5, 2]
Move to the next pair. 6 and 3. 6 > 3 , swap them -> [4, 1, 3, 6, 5, 2]
Move to the next pair. 6 and 5. 6 > 5, swap them -> [4, 1, 3, 5, 6, 2]
Move to the next pair. 6 and 2. Again 6 > 2, swap them -> [4, 1, 3, 5, 2, 6]
The first iteration is completed.
Now move to the start and follow the same steps until the list is sorted.
Example Code
Explore more articles on software architecture, frontend craftsmanship, and backend engineering.

Insertion Sort is one of the most intuitive sorting algorithms out there.
Imagine you’re sitting at a table playing a card game. The dealer hands you a pile of unsorted cards face down. You pick up the cards one by one to arrange them in your hand from smallest to largest.
Here is how your brain naturally handles it:
You pick up the first card. It’s a 7. Since it's the only card in your hand, it's already "sorted."
You pick up the second card. It’s a 3. You look at the 7, realize 3 is smaller, and insert it to the left of the 7.
You pick up a third card. It’s a 5. You compare it to the 7 (bigger, so you move past it) and then the 3 (smaller). You insert the 5 right between the 3 and the 7.
That is literally all Insertion Sort is! It builds a sorted list one item at a time by constantly "inserting" the current item into its correct position among the items already sorted.
Assume the very first element in the array is already sorted.
Move to the next element (let's call this the Key).
Compare the Key with the elements before it (to its left).
Shift all elements that are greater than the Key to the right to make room.
Insert the Key into its correct, empty slot.
Repeat for all remaining elements until the whole array is sorted.
Let's watch this happen with a real array of numbers: [5, 2, 4, 6, 1, 3].
Start: [5, 2, 4, 6, 1, 3] The first element (5) is our sorted zone.
Iteration 1: Key is 2. Compare 2 with 5. Since 5 is bigger, shift 5 to the right and insert 2.
Array becomes: [2, 5, 4, 6, 1, 3]
Iteration 2: Key is 4. Compare 4 with 5 (shift 5 right), then compare 4 with 2 (2 is smaller, so stop). Insert 4.
Array becomes: [2, 4, 5, 6, 1, 3]
Iteration 3: Key is 6. Compare 6 with 5. Since 6 is already bigger than 5, it's in the right spot! No shifting needed.
Array becomes: [2, 4, 5, 6, 1, 3]
Iteration 4: Key is 1. This is a tiny number, so it compares against 6, 5, 4, and 2, shifting all of them to the right, and drops into the very front.
Array becomes: [1, 2, 4, 5, 6, 3]
Iteration 5: Key is 3. Compare and shift 6, 5, and 4 to the right. Stop at 2. Insert 3.
Array becomes: [1, 2, 3, 4, 5, 6]
Here is how we write this in clean, readable JavaScript. Paste this into your browser console or code editor to play around with it!
function insertionSort(arr) {
// Start from the second element (index 1) because index 0 is already "sorted"
for (let i = 1; i < arr.length; i++) {
let currentKey = arr[i];
let j = i - 1;
// Look backward through the sorted section.
// If an element is larger than our currentKey, shift it one position to the right.
while (j >= 0 && arr[j] > currentKey) {
arr[j + 1] = arr[j];
j--;
// Move left to check the next element
}
// Insert the currentKey into its correct, empty position
arr[j + 1] = currentKey;
}
return arr;
}
const numbers = [5, 2, 4, 6, 1, 3];
console.log("Sorted Array:", insertionSort(numbers)); // Output: [1, 2, 3, 4, 5, 6]Imagine you give this algorithm an array that is already sorted, like [1, 2, 3, 4, 5]. The algorithm will check each number once, realize it doesn't need to shift anything, and smoothly finish. It runs in linear time, which is incredibly fast!
Imagine the array is completely backward, like [5, 4, 3, 2, 1]. For every single number, the algorithm has to compare and shift every single other number before it. This results in quadratic time. If your array grows 10x larger, the time it takes grows 100x larger!
Because Insertion Sort rearranges elements directly inside the original array without creating a copy or a new array, it uses virtually no extra memory. This is called sorting in-place.
If Insertion Sort can get terribly slow with large datasets (O(n^2)), why do we care about it?
Because it shines in specific real-world situations:
Small datasets: For lists with just a few items, Insertion Sort is actually faster than algorithms like Quick Sort because it has almost zero administrative overhead.
Nearly sorted data: If you are constantly adding a few new entries to a database that is already mostly sorted, Insertion Sort will clean it up in record time.

Creating a todo app in JS is easy as we write the code. Before starting without a project we must have a basic understanding of HTML, CSS, and JavaScript.
Basic knowledge of HTML
Basic knowledge of CSS
Basic knowledge of JS
Let's understand the app we are going to build. It will be a simple to-do app where users can add, edit, and delete items.
First, create a directory for the todo app. Create a file inside for HTML, CSS, and JavaScript.
mkdir todo && cd todotouch app.js && touch styles.css && touch index.htmlAdd the following code to index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/meistericons@latest/fonts/mni.css"
/>
<link rel="stylesheet" href="./styles.css" />
<title>Todo App - HTML, CSS and JS</title>
</head>
<body>
<main class="container">
<h1>Todos</h1>
<form class="">
<input
type="text"
name="todo"
id="todo"
placeholder="+ Add New Todo"
name="Take a walk"
/>
<button type="submit">Add</button>
</form>
<div class="tab_container">
<span class="active_tab tab">Remaning Todos</span>
<span class="tab">Completed Todos</span>
</div>
<strong class="active__todo">Remaning Todos</strong>
<ul class="todo__container"></ul>
</main>
<script src="./app.js"></script>
</body>
</html>Add the following code to styles.css
body,
html,
:root,
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 20rem;
height: 30rem;
border-radius: 2rem;
border: 1px solid rgb(34, 36, 192);
padding: 2rem;
position: fixed;
top: 10rem;
left: 38%;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 1rem;
}
div {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
margin: 1rem 0;
}
.todo__active {
border-bottom: 4px solid rgb(34, 36, 192);
}
.active__todo {
font-size: 1.25rem;
font-weight: 600;
}
ul {
margin-top: 1rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
li {
list-style-type: none;
display: flex;
gap: 0.25rem;
}
label {
font-size: 1rem;
font-weight: 500;
}
.tab_container {
display: flex;
gap: 1rem;
}
.tab {
font-weight: 600;
font-size: 0.85rem;
}
.tab:hover {
cursor: pointer;
}
.active_tab {
border-bottom: 4px solid rgb(34, 36, 192);
font-weight: 700;
font-size: 1rem;
}
.todo__container {
height: 15rem;
overflow-y: scroll;
}
.todo {
display: flex;
align-items: center;
justify-content: space-between;
}
.todo__item__span {
display: flex;
align-items: center;
gap: 0.5rem;
}Add the following code to the app.js file.
// List of Tasks
let todos = [
{ title: "Example 1", completed: false },
{ title: "Example 2", completed: false },
{ title: "Example 3", completed: false },
];
const todoContainer = document.querySelector(".todo__container");
const remainingTodoTab = document.querySelectorAll(".tab")[0];
const completedTodoTab = document.querySelectorAll(".tab")[1];
const todoHeader = document.querySelector(".active__todo");
// RemainingTasks event listerner.
remainingTodoTab.addEventListener("click", () => {
completedTodoTab.classList.remove("active_tab");
remainingTodoTab.classList.add("active_tab");
todoHeader.innerHTML = "Remaining Todos";
clearTodoList();
todos
.filter(({ completed }) => !completed)
.forEach((remainingTodo) => {
createTodoItem(remainingTodo.title);
});
});
// CompletedTasks event listener.
completedTodoTab.addEventListener("click", () => {
remainingTodoTab.classList.remove("active_tab");
completedTodoTab.classList.add("active_tab");
todoHeader.innerHTML = "Completed Todos";
clearTodoList();
todos
.filter(({ completed }) => completed === true)
.forEach((completedTodo) => {
createTodoItem(completedTodo.title, true);
});
});
// Clear Task List
const clearTodoList = () => {
todoContainer.innerHTML = "";
};
/**
* Remove task from tasks list.
* @param {*} removeTodo - String to remove from tasks list.
*/
const removeTodo = (removeTodo) => {
todos = todos.filter((todo) => todo.title !== removeTodo);
};
/**
*
* @param {*} task - String to add to tasks list.
* @param {*} isCompleted - Status of the task.
*/
const createTodoItem = (task, isCompleted = false) => {
const newListItem = document.createElement("li");
newListItem.classList.add("todo");
const newTodoSpan = document.createElement("span");
newTodoSpan.classList.add("todo__item__span");
const newTodo = document.createElement("label");
const input = document.createElement("input");
const deleteIcon = document.createElement("i");
deleteIcon.classList.add("mni-delete-aB");
// Delete Task Click Event Listner.
deleteIcon.addEventListener("click", () => {
removeTodo(task);
newListItem.remove();
});
if (isCompleted) {
input.checked = true;
newListItem.style.textDecoration = "line-through";
} else {
input.checked = false;
}
input.type = "checkbox";
/**
* Update checkbox status.
* @param {*} e - Events in input element.
*/
input.onchange = (e) => {
const currentTodo = todos.find((todo) => todo.title === e.target.name);
if (e.target.checked) {
e.target.parentElement.style.textDecoration = "line-through";
currentTodo.completed = true;
} else {
currentTodo.completed = false;
e.target.parentElement.style.textDecoration = "none";
}
newListItem.remove();
};
input.name = task;
newListItem.appendChild(newTodoSpan);
newTodoSpan.appendChild(input);
newTodoSpan.appendChild(newTodo);
newListItem.appendChild(deleteIcon);
newTodo.innerHTML = task;
todoContainer.appendChild(newListItem);
if (!todos.length) {
todos.push({ title: task, completed: false });
}
};
// Create a list of tasks
todos.forEach((todo) => {
createTodoItem(todo.title);
});
// Add task to the list.
const addTodo = (e) => {
e.preventDefault();
const todo = document.getElementById("todo").value;
if (todo.length > 0 && remainingTodoTab.classList.contains("active_tab")) {
todos.push({ title: todo, completed: false });
createTodoItem(todo);
}
document.getElementById("todo").value = "";
};
document.querySelector("form").addEventListener("submit", addTodo);
Let's understand each of the lines of code.
Initially, a list of example tasks is added.
let todos = [
{ title: "Example 1", completed: false },
{ title: "Example 2", completed: false },
{ title: "Example 3", completed: false },
];We will add an event listener for the form submission and add a function for it.
const addTodo = (e) => {
e.preventDefault();
const todo = document.getElementById("todo").value;
if (todo.length > 0 && remainingTodoTab.classList.contains("active_tab")) {
todos.push({ title: todo, completed: false });
createTodoItem(todo);
}
document.getElementById("todo").value = "";
};
document.querySelector("form").addEventListener("submit", addTodo);We also need to create a function to append a new task list item after the user submits the form.
const createTodoItem = (task, isCompleted = false) => {};First, we create the tags necessary for the list item to check if the selected task is completed.
if (isCompleted) {
input.checked = true;
newListItem.style.textDecoration = "line-through";
} else {
input.checked = false;
}
input.type = "checkbox";Add an event handler for the input to update the completed and remaining tasks.
/**
* Update checkbox status.
* @param {*} e - Events in input element.
*/
input.onchange = (e) => {
const currentTodo = todos.find((todo) => todo.title === e.target.name);
if (e.target.checked) {
e.target.parentElement.style.textDecoration = "line-through";
currentTodo.completed = true;
} else {
currentTodo.completed = false;
e.target.parentElement.style.textDecoration = "none";
}
newListItem.remove();
};
input.name = task;Finally, append all the created tags to the html body
newListItem.appendChild(newTodoSpan);
newTodoSpan.appendChild(input);
newTodoSpan.appendChild(newTodo);
newListItem.appendChild(deleteIcon);
newTodo.innerHTML = task;
todoContainer.appendChild(newListItem);
if (!todos.length) {
todos.push({ title: task, completed: false });
}Now, let us add an event listener to our delete icon.
// Delete Task Click Event Listner.
deleteIcon.addEventListener("click", () => {
removeTodo(task);
newListItem.remove();
});
and the function to remove the task.
// Clear Task List
const clearTodoList = () => {
todoContainer.innerHTML = "";
};
/**
* Remove task from tasks list.
* @param {*} removeTodo - String to remove from tasks list.
*/
const removeTodo = (removeTodo) => {
todos = todos.filter((todo) => todo.title !== removeTodo);
};We have built a complete to-do app where users can add tasks. View Remaining and completed tasks. Update tasks to be completed and/or uncompleted. We have done it all using our knowledge of HTML, CSS, and javascript. You can now easily update the UI to your liking and extra features to the app to make it even better.

Todo app is a simple web app that can get you started with React. React makes it easy to accomplish our task.
Basic knowledge of React.
Basic knowledge of React Hooks.
Basic knowledge of HTML, CSS, and JavaScript.
Let's start by Creating a React app with the following command. For this example, we will be using the Vite to create the Todo React app
npm create vite@latest todo --tempalate react-swc-tsNavigate into the directory and install the dependencies.
cd todo && npm i && npm run devNow we can see the starter for a Vite React project. Edit the src/App.tsx page to get started.
Initially, create a component for the Input so that we can reuse it across the App.
//components/Input/Input.tsx
import { ComponentPropsWithoutRef } from "react";
import "./styles.css";
interface IInput extends ComponentPropsWithoutRef<"fieldset"> {
inputProps: ComponentPropsWithoutRef<"input">;
}
export default function Input({ inputProps }: IInput) {
return (
<fieldset className="input__container">
<label htmlFor="todo" className="input__label">
Add Todo
</label>
<input
{...inputProps}
type="text"
name="todo"
id="todo"
className="input__input"
/>
</fieldset>
);
}
Add the styles for it.
//components/Input/styles.css
.input__container {
display: flex;
flex-direction: column;
gap: 0.25rem;
border: none;
}
.input__label {
font-size: 1rem;
font-weight: 700;
}
.input__input {
padding: 0.5rem 1rem;
border-radius: 1rem;
border: 1px solid rgba(0, 0, 0, 0.4);
outline: none;
}Clear everything in the App.tsx and get started with the code below.
//src/App.tsx
<main className="container">
<h1 className="title">Todos</h1>
</main>We can now add a form to our UI to begin adding todos to our application.
<form onSubmit={handleAddTodo} className="add__todo__form">
<Input inputProps={{ name: "todo", value: todo, onChange: handleOnChange }} />
<button type="submit" className="add__todo__button">
Add
</button>
</form>To update the todos we need to listen for changes in our input. We can save our values from the input in a useState React hook.
const [todo, setTodo] = useState("");Similarly, add the onChange function to add our todo.
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
const { value } = e.target;
setTodo(value);
};In this function, we listen for changes in the input and append the resulting value to our todo state using setTodo.
Similarly, the form will be submitted to the handleAddTodo function. Here, we prevent the default behavior of the browser and add todos to our setTodos useState hook.
const [todos, setTodos] = useState<{ title: string; completed: boolean }[]>([]);
const handleAddTodo = (e: SyntheticEvent) => {
e.preventDefault();
setTodos((prev) => [...prev, { title: todo, completed: false }]);
setTodo("");
};Continue by building tabs to view the remaining and completed todos. We can handle the state of our active tab by again using the useState React hook.
const [activeTab, setActiveTab] = useState("Remaining Todos");We can update the active tab value by listening to a click event in the tabs.
<div className="tabs__container">
{["Remaining Todos", "Completed Todos"].map((tab) => (
<button
key={tab}
className={`tabs__tab ${
activeTab === tab ? "tabs__tab__active" : ""
}`}
onClick={() => setActiveTab(tab)}
>
{tab}{" "}
{tab === "Remaining Todos"
? remainingTodos.length > 0 && `(${remainingTodos.length})`
: completedTodos.length > 0 && `(${completedTodos.length})`}
</button>
))}
</div>In the above onClick function we make use of the setActiveTab hook to update our activeTab value.
Now we can memoize our remaining and completed todos.
const remainingTodos = useMemo(() => {
return todos.filter((todo) => !todo.completed);
}, [todos]);
const completedTodos = useMemo(() => {
return todos.filter((todo) => todo.completed);
}, [todos]);Finally, render the list of our todos to the UI. Before, rendering the UI we must also check for the active tab state to get the active tab todos.
<ul className="todos__container">
{(activeTab === "Remaining Todos"
? remainingTodos
: completedTodos
).map((todo) => (
<li key={todo.title} className="todo__list__item">
<span className="todo__list__item__input__container">
<input
type="checkbox"
checked={todo.completed}
name={todo.title}
onChange={(e) => {
setTodos((prev) =>
prev.map((t) =>
t.title === todo.title
? { ...t, completed: e.target.checked }
: t
)
);
}}
/>
{todo.title}
</span>
<DeleteB
onClick={() => {
setTodos((prev) => prev.filter((t) => t.title !== todo.title));
}}
/>
</li>
))}
</ul>Add styles to the page.
//src/index.css
html,
body,
:root,
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.title {
font-size: 2.5rem;
font-weight: 900;
}
.add__todo__form {
display: flex;
align-items: flex-end;
gap: 1rem;
}
.add__todo__button {
padding: 0.5rem 1rem;
border-radius: 1.5rem;
border: none;
outline: none;
}
.container {
width: 25rem;
position: absolute;
top: 25%;
left: calc(50% - 10rem);
display: flex;
flex-direction: column;
gap: 1.25rem;
padding: 2rem 2.5rem;
border-radius: 2rem;
border: 1px solid rgb(58, 40, 216);
}
.todo__list__item {
list-style-type: none;
display: flex;
gap: 0.25rem;
align-items: center;
justify-content: space-between;
padding: 0.25rem 1rem;
}
.tabs__container {
display: flex;
align-items: center;
gap: 1rem;
}
.tabs__tab {
white-space: nowrap;
font-size: 1rem;
font-weight: 500;
outline: none;
border: none;
background: transparent;
}
.tabs__tab__active {
border-bottom: 1px solid blue;
}
.todos__container {
height: 20rem;
overflow-y: scroll;
}
.todo__list__item__input__container {
display: flex;
gap: 0.25rem;
align-items: center;
}Here, we created a to-do app in React using Vite and React hooks. You can now further update the UI and add additional functionalities to your to-do app to make it even better.

Let's start by cloning our already made todo app. We will be testing the crud function and also checking for UI updates. Vitest is easy to get started with. Just follow along and you will begin testing your apps soon.
Add Vitest,jsdom and necessary testing libraries for UI testing to get started.
npm i -D vitest @testing-library/jest-dom @testing-library/user-event @types/jest @vitest/ui jsdomYou can additionally add the following scripts to package .json
"scripts": {
"test": "vitest",
"test:ui": "vitest --ui",
"coverage": "vitest run --coverage"
}Before testing our application, we need to set up some files to get started. Start by creating a new file test-utils that will have all the utilities for our tests.
//tests/test-utils.tsx
import { cleanup, render } from "@testing-library/react";
import { afterEach } from "vitest";
afterEach(() => {
cleanup();
});
function customRender(ui: React.ReactElement, options = {}) {
return render(ui, {
// wrap provider(s) here if needed
wrapper: ({ children }) => children,
...options,
});
}
export * from "@testing-library/react";
export { default as userEvent } from "@testing-library/user-event";
// override render export
export { customRender as render };//tests/setup.ts
import '@testing-library/jest-dom';We need now to update our Vite config to include test files.
// vite.config.ts
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
// you might want to disable it, if you don't have tests that rely on CSS
// since parsing CSS is slow
css: true,
},
})First, let's start by performing component testing. For this, we can create a test file to test our input component. We can test as many scenarios as we like. Here, we will test if the component is rendered properly and if the input can change values and update as we require. Initially, we will test to see if the component in rendered to the document.
//components/Input/Input.test.tsx
import { render, screen, userEvent } from "../../utils/test-utils";
import Input from "./Input";
test("should render the input component.", () => {
render(<Input label="Add Todo" inputProps={{}} />);
expect(screen.getByText(/Add Todo/i)).toBeInTheDocument();
expect(screen.getByRole("textbox", { name: "Add Todo" })).toBeInTheDocument();
});First, we render the component making use of @testing-library/react and we will check if the component is rendered. We can additionally check for props and values the input component should have as the props have been passed in. for this we can again make use of helper functions provided by @testing-library/react to get the component properties. Here, we test to see if the input component has the label of "Add Todo" and we also check for the input box having the name 'Add Todo'.
We can now test our input for value changes and updates.
test("should update input value on change.", async () => {
render(<Input label="Add Todo" inputProps={{}} />);
const input = screen.getByRole("textbox", { name: "Add Todo" });
expect(input).toBeInTheDocument();
await userEvent.type(input, "new todo");
expect(input).toHaveValue("new todo");
});Here, we render the input then we check if the input box is present in the document. If the input box check passes we can then type anything we want into the input box. We then check if the input has the same value as we typed.
Now we can test our addtodo functionality in the app. Continue by creating a new file AddTodo.test.tsx . We can begin by checking if the UI for the form is present in the document.
//src/AddTodo.test.tsx
import App from "./App";
import { render, screen, userEvent } from "./utils/test-utils";
test("should render the todo form.", () => {
render(<App />);
expect(screen.getByText(/Add Todo/i)).toBeInTheDocument();
expect(screen.getByRole("textbox", { name: "Add Todo" })).toBeInTheDocument();
const button = screen.getByRole("button", { name: /add/i });
expect(button).toBeInTheDocument();
});Now we can test the functionality of the add todo form. Here, we again test by rendering the App component and then check for the title of the remaining todo in the document. Then we add a new todo to the input and click on the button for adding. We then finally check if the newly added todo is also present in the UI document.
test("should add todo to the remaining todos list.", async () => {
render(<App />);
expect(screen.getByText(/Remaining Todos/i)).toBeInTheDocument();
const input = screen.getByRole("textbox", { name: /add todo/i });
expect(input).toBeInTheDocument();
await userEvent.type(input, "new todo");
const button = screen.getByRole("button", { name: /add/i });
expect(button).toBeInTheDocument();
await userEvent.click(button);
expect(screen.getByText(/new todo/i)).toBeInTheDocument();
});We successfully tested different scenarios for the todo app. We also made it possible to pass all the tests. Implement similarly in your apps now.