diff --git a/src/components/ModalRoot.svelte b/src/components/ModalRoot.svelte
new file mode 100644
index 0000000..86bad7f
--- /dev/null
+++ b/src/components/ModalRoot.svelte
@@ -0,0 +1,61 @@
+
+
+
+
+ {#if modal}
+
{modal.title}
+
{modal.message}
+ {/if}
+
+
diff --git a/src/lib/util/modal/index.ts b/src/lib/util/modal/index.ts
new file mode 100644
index 0000000..25b941c
--- /dev/null
+++ b/src/lib/util/modal/index.ts
@@ -0,0 +1,27 @@
+import { v4 } from "uuid";
+
+export interface Modal {
+ title: string;
+ message: string;
+}
+
+export class ModalManager {
+ private static listeners: {
+ id: string;
+ callback: (data: Modal) => void;
+ }[] = [];
+
+ static addListener(callback: (data: Modal) => void) {
+ const id = v4();
+ this.listeners.push({ id, callback });
+ return id;
+ }
+
+ static removeListener(id: string) {
+ this.listeners = this.listeners.filter((listener) => listener.id !== id);
+ }
+
+ static notify(data: Modal) {
+ this.listeners.forEach((listener) => listener.callback(data));
+ }
+}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 8ae0185..52c16bc 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -4,6 +4,7 @@
import Logo from "../components/LogoWithTextHorizontal.svelte";
import { CodeBranchOutline, DiscordSolid, DownloadOutline } from "flowbite-svelte-icons";
import { browser } from "$app/environment";
+ import ModalManager from "$components/ModalRoot.svelte";
let scrolled = false;
let cookies: {
@@ -43,8 +44,8 @@