diff --git a/astro/services/Club.go b/astro/services/Club.go
index 3935fce2e9812739793cb3bb75483089d847672b..51e7a3333c5becfe80216b5eea74e9ac29671388 100644
--- a/astro/services/Club.go
+++ b/astro/services/Club.go
@@ -19,15 +19,3 @@ type Club struct {
 func (n *Nation) GetFlagPath() string {
 	return "https://flagsapi.com/" + n.NationCode + "/flat/64.png"
 }
-
-func (r *Nation) Load() []Nation {
-	return LoadData[Nation]("../resources/nations.json")
-}
-
-func (r *Region) Load() []Region {
-	return LoadData[Region]("../resources/regions.json")
-}
-
-func (c *Club) Load() []Club {
-	return LoadData[Club]("../resources/clubs.json")
-}
diff --git a/astro/services/Util.go b/astro/services/Util.go
index b7540a357b6e0259765e35f40df6a686fc7adf8b..b357fed01a2e3ac93a318a74d6dd006b4608f1f6 100644
--- a/astro/services/Util.go
+++ b/astro/services/Util.go
@@ -1,10 +1,5 @@
 package services
 
-import (
-	"encoding/json"
-	"os"
-)
-
 // Category : Age category
 type Category uint8
 
@@ -129,31 +124,3 @@ func (s State) String() string {
 		return "Unknown"
 	}
 }
-
-// ---- Generic JSON loader ----
-type loadable interface {
-	Load()
-}
-
-func LoadData[T any](filename string) []T {
-	// Read the file
-	jsonFile, err := os.Open(filename)
-	if err != nil {
-		panic(err)
-	}
-	defer func(jsonFile *os.File) {
-		err := jsonFile.Close()
-		if err != nil {
-			panic(err)
-		}
-	}(jsonFile)
-
-	// Decode the JSON
-	var data []T
-	err = json.NewDecoder(jsonFile).Decode(&data)
-	if err != nil {
-		panic(err)
-	}
-
-	return data
-}
diff --git a/astro/resources/clubs.json b/frontend/public/resources/clubs.json
similarity index 100%
rename from astro/resources/clubs.json
rename to frontend/public/resources/clubs.json
diff --git a/astro/resources/nations.json b/frontend/public/resources/nations.json
similarity index 100%
rename from astro/resources/nations.json
rename to frontend/public/resources/nations.json
diff --git a/astro/resources/regions.json b/frontend/public/resources/regions.json
similarity index 100%
rename from astro/resources/regions.json
rename to frontend/public/resources/regions.json
diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte
index 3a159356f37d76fddd073d2d9e7f6a75eceecb65..60569b27ae4730ce75455d25ea7d49cf6f57da3c 100644
--- a/frontend/src/App.svelte
+++ b/frontend/src/App.svelte
@@ -5,6 +5,7 @@
     import Registrations from "./components/Registrations.svelte";
     import * as Session from "../bindings/changeme/astro/services/session";
     import { Competition } from "../bindings/changeme/astro/services/models";
+    import NewPlayerForm from "./components/NewPlayerForm.svelte";
 
     let competitions: Competition[] = [];
 
@@ -17,11 +18,12 @@
 
 <div class="container">
     <NavBar />
-    {#if competitions.length <= competitionID}
+    <NewPlayerForm />
+    <!-- {#if competitions.length <= competitionID}
         <p>Loading...</p>
     {:else}
         <Registrations competition={competitions[competitionID]} />
-    {/if}
+    {/if} -->
 </div>
 
 <style>
diff --git a/frontend/src/components/NewPlayerForm.svelte b/frontend/src/components/NewPlayerForm.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..91954998debc8ba0c35f029c273baf7e8d05abb1
--- /dev/null
+++ b/frontend/src/components/NewPlayerForm.svelte
@@ -0,0 +1,117 @@
+<script lang="ts">
+    import { onMount } from "svelte";
+    import * as Models from "../../bindings/changeme/astro/services/models";
+    import * as Session from "../../bindings/changeme/astro/services/session";
+    import swal from "sweetalert";
+
+    export let competition: Models.Competition;
+
+    let clubs: Models.Club[] = [];
+
+    let playerFirstname: string = "",
+        playerLastname: string = "",
+        playerClub: string = "";
+
+    // Fetch /resources/clubs
+    async function loadClubs() {
+        var json = await fetch("/resources/clubs.json").then((r) => r.json());
+        clubs = json.map((c: any) => new Models.Club(c));
+    }
+
+    onMount(loadClubs);
+</script>
+
+<div class="form">
+    <label for="player-firstname">Firstname</label>
+    <input
+        type="text"
+        id="player-firstname"
+        name="player-firstname"
+        placeholder="John"
+        required
+        bind:value={playerFirstname}
+    />
+
+    <label for="player-lastname">Lastname</label>
+    <input
+        type="text"
+        id="player-lastname"
+        name="player-lastname"
+        placeholder="Doe"
+        required
+        bind:value={playerLastname}
+    />
+
+    <label for="player-club">Club</label>
+    <input
+        type="text"
+        id="player-club"
+        name="player-club"
+        placeholder="Club"
+        list="clubs"
+        required
+        bind:value={playerClub}
+    />
+
+    <button
+        type="submit"
+        on:click={async () => {
+            // First check if the club exists
+            let club = clubs.find((c) => c.club_name == playerClub);
+
+            if (club === undefined) {
+                await swal("Error", "Club does not exist", "error");
+                return;
+            }
+
+            // Check if the name is not empty
+            if (playerFirstname == "" || playerLastname == "") {
+                await swal("Error", "Name cannot be empty", "error");
+                return;
+            }
+
+            // Create the player
+            let player = new Models.Player({
+                PlayerFirstname: playerFirstname,
+                PlayerLastname: playerLastname,
+                PlayerClub: club,
+            });
+
+            // Send the player to the backend
+            Session.AddPlayerToCompetition(competition.CompetitionID, player);
+
+            // Clear the form
+            playerFirstname = "";
+            playerLastname = "";
+            playerClub = "";
+        }}>Add player</button
+    >
+
+    <datalist id="clubs">
+        {#each clubs as club}
+            <option value={club.club_name} />
+        {/each}
+    </datalist>
+</div>
+
+<style>
+    .form {
+        max-width: 30%;
+        margin: 0 auto;
+        border-radius: 5px;
+        padding: 40px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        background: #e9ecef;
+    }
+
+    input {
+        width: 200px;
+        margin-bottom: 10px;
+        padding: 10px;
+        font-size: 1em;
+        border-radius: 10px;
+        border: solid 1px #003566;
+    }
+</style>