diff --git a/app/templates/players.html b/app/templates/players.html
new file mode 100755
index 0000000000000000000000000000000000000000..d8b95836cf1100fefd12855550485989bb70a1a2
--- /dev/null
+++ b/app/templates/players.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<html lang="en">
+
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <title>Template</title>
+        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
+            integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
+        <link href="../static/css/style.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <div id="header"></div>
+        <main role="main">
+            <div class="container">
+                <table class="table">
+                    <thead>
+                        <tr>
+                            <th scope="col">Name</th>
+                            <th scope="col">Team</th>
+                            <th scope="col">Age</th>
+                            <th scope="col">Salary (p/w)</th>
+                            <th scope="col">Contract duration (years)</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {% for player in players %}
+                        <tr>
+                            <td scope="row"><a href="/player/{{ player.name }}">{{ player.name }}</a></td>
+                            <td><a href="/team/{{ player.team }}">{{ player.team }}</a></td>
+                            <td>{{ player.dob }}</td>
+                            <td>£{{ player.salary }},000</td>
+                            <td>{{ player.contract_duration }}</td>
+                        </tr>
+                        {% endfor %}
+                    </tbody>
+                </table>
+            </div>
+        </main>
+
+        <div id="footer"></div>
+        <!-- JQuery CDN -->
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"
+            integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ=="
+            crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+
+        <!-- Render header footer template -->
+        <script src="../static/js/tools.js"></script>
+
+        <!-- Bootstrap JS -->
+        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
+            integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
+            crossorigin="anonymous"></script>
+        <script>
+            loadTemplate(() => { })
+        </script>
+    </body>
+
+</html>
diff --git a/classes.png b/classes.png
new file mode 100644
index 0000000000000000000000000000000000000000..83c31942513324e9918d8838918049294055e31e
Binary files /dev/null and b/classes.png differ
diff --git a/data/__init__.py b/data/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/data/processing.py b/data/processing.py
index a597a65eb4c24b5f8b558cadbc67c2484c1d4ff3..4ca5488a3cf2089cee47a32588f3098c3404e6af 100644
--- a/data/processing.py
+++ b/data/processing.py
@@ -7,72 +7,15 @@ import os
 import pandas as pd
 
 
-def read_csv():
-    # Reads the CSV file and returns a pandas dataframe
-    absolute_path = os.path.dirname(os.path.abspath(__file__))
-    csv_path = os.path.join(absolute_path, "players_file.csv")
-    data = pd.read_csv(csv_path, encoding="unicode_escape")
-    return data
-
-
-def get_objects(data):
-    # Returns a list of row objects
-    objects = []
-    for index, row in data.iterrows():
-        player = DataObject(
-            id=index,
-            name=row["PLAYER NAME"],
-            dob=row["DATE OF BIRTH"],
-            gender=row["GENDER"],
-            date_signed_up=row["DATE SIGNED UP"],
-            current_team=row["CURRENT TEAM"],
-            team_location=row["TEAM LOCATION"],
-            team_manager=row["TEAM MANAGER"],
-            salary=row["SALARY (£k/Week)"],
-            contract_start=row["START OF CONTRACT"],
-            contract_duration=row["CONTRACT DURATION"],
-            games_played=row["GAMES PLAYED THIS YEAR "],
-            games_won=row["GAMES WON"],
-            fg1=row["FG1"],
-            fg2=row["FG2"],
-            fg3=row["FG3"],
-            fg4=row["FG4"],
-            fg5=row["FG5"],
-        )
-        objects.append(player)
-    return objects
-
-
-def filter_teams(data):
-    # Read all team names. If a team name is duplicated, remove it
-    team_names = []
-    for team in data:
-        team_names.append(team.team)
-
-    # Remove duplicate team names
-    team_names = list(dict.fromkeys(team_names))
-
-    # Create a list of team objects from the team names
-    teams = []
-    for team in data:
-        if team.team in team_names:
-            teams.append(Team(team))
-            team_names.remove(team.team)
-    return teams
-
-
-def filter_players(data):
-    players = []
-    for player in data:
-        players.append(Player(player))
-    return players
-
-
 class DataObject:
+    """
+    Data object for each row in the CSV file
+    """
+
     def __init__(
         self,
-        id,
-        name,
+        id: int,
+        name: str,
         dob,
         gender,
         date_signed_up,
@@ -90,6 +33,32 @@ class DataObject:
         fg4,
         fg5,
     ) -> None:
+        """
+        __init__ method for DataObject class
+
+        Args:
+            id (int): Player ID
+            name (str): Player name
+            dob (str): Date of birth
+            gender (str): Player gender
+            date_signed_up (str): Date signed up
+            current_team (str): Current team
+            team_location (str): Team location
+            team_manager (str): Team manager
+            salary (float): Salary
+            contract_start (str): Start of contract
+            contract_duration (str): Contract duration
+            games_played (int): Games played this year
+            games_won (int): Games won
+            fg1 (int): Field goal 1
+            fg2 (int): Field goal 2
+            fg3 (int): Field goal 3
+            fg4 (int): Field goal 4
+            fg5 (int): Field goal 5
+
+        Returns:
+            DataObject object
+        """
         self.id = id
         self.name = name
         self.dob = dob
@@ -111,14 +80,40 @@ class DataObject:
 
 
 class Team:
+    """
+    Team object for each team in the CSV file
+    """
+
     def __init__(self, data: DataObject) -> None:
+        """
+        __init__ method for Team class
+
+        Args:
+            data (DataObject): Data object for each row in the CSV file
+
+        Returns:
+            Team object
+        """
         self.name = data.team
         self.location = data.team_location
         self.manager = data.team_manager
 
 
 class Player:
+    """
+    Player object for each player in the CSV file
+    """
+
     def __init__(self, data: DataObject) -> None:
+        """
+        __init__ method for Player class
+
+        Args:
+            data (DataObject): Data object for each row in the CSV file
+
+        Returns:
+            Player object
+        """
         self.id = data.id
         self.name = data.name
         self.dob = data.dob
@@ -135,3 +130,78 @@ class Player:
         self.fg3 = data.fg3
         self.fg4 = data.fg4
         self.fg5 = data.fg5
+
+
+def read_csv() -> pd.DataFrame:
+    """
+    Reads the CSV file and returns a pandas dataframe
+
+    Returns:
+        pd.DataFrame: Pandas dataframe of the CSV file
+    """
+    # Reads the CSV file and returns a pandas dataframe
+    absolute_path = os.path.dirname(os.path.abspath(__file__))
+    csv_path = os.path.join(absolute_path, "players_file.csv")
+    data = pd.read_csv(csv_path, encoding="unicode_escape")
+    return data
+
+
+def get_objects(data: pd.DataFrame) -> list[DataObject]:
+    """
+    Creates a list of DataObject objects from the pandas dataframe
+
+    Args:
+        data (pd.DataFrame): Pandas dataframe of the CSV file
+
+    Returns:
+        list[DataObject]: List of DataObject objects
+    """
+    objects = []
+    for index, row in data.iterrows():
+        player = DataObject(
+            id=index,
+            name=row["PLAYER NAME"],
+            dob=row["DATE OF BIRTH"],
+            gender=row["GENDER"],
+            date_signed_up=row["DATE SIGNED UP"],
+            current_team=row["CURRENT TEAM"],
+            team_location=row["TEAM LOCATION"],
+            team_manager=row["TEAM MANAGER"],
+            salary=row["SALARY (£k/Week)"],
+            contract_start=row["START OF CONTRACT"],
+            contract_duration=row["CONTRACT DURATION"],
+            games_played=row["GAMES PLAYED THIS YEAR "],
+            games_won=row["GAMES WON"],
+            fg1=row["FG1"],
+            fg2=row["FG2"],
+            fg3=row["FG3"],
+            fg4=row["FG4"],
+            fg5=row["FG5"],
+        )
+        objects.append(player)
+    return objects
+
+
+def filter_teams(data):
+    # Read all team names. If a team name is duplicated, remove it
+    team_names = []
+    for team in data:
+        team_names.append(team.team)
+
+    # Remove duplicate team names
+    team_names = list(dict.fromkeys(team_names))
+
+    # Create a list of team objects from the team names
+    teams = []
+    for team in data:
+        if team.team in team_names:
+            teams.append(Team(team))
+            team_names.remove(team.team)
+    return teams
+
+
+def filter_players(data):
+    players = []
+    for player in data:
+        players.append(Player(player))
+    return players
diff --git a/packages.png b/packages.png
new file mode 100644
index 0000000000000000000000000000000000000000..17d1d1e450984aad8b6bbc3e4c8238a81a11bc3a
Binary files /dev/null and b/packages.png differ