diff --git a/Dockerfile b/Dockerfile
index e29d064d6b5e3eaafad16cd0da74d5ab9db3f8e4..1d2b0aa6ff4ad1548abfb3c16a5a76a2509afb21 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,3 +1,11 @@
-FROM php:8.0-apache
+FROM php:8.1-apache
+    
+RUN apt-get update && apt-get upgrade -y
+RUN apt-get install -y libxml2-dev libpq-dev
+RUN docker-php-ext-install pgsql pdo pdo_pgsql && docker-php-ext-enable pgsql pdo pdo_pgsql
+RUN a2enmod rewrite && service apache2 restart
+RUN chown -R :www-data /var/www/html/
 
-RUN docker-php-ext-install pdo pdo_mysql
\ No newline at end of file
+WORKDIR /var
+
+EXPOSE 80
\ No newline at end of file
diff --git a/app/Models/Event.php b/app/Models/Event.php
deleted file mode 100644
index 94ec0d38200f8e5d4b30acc731426dd08ce58f3c..0000000000000000000000000000000000000000
--- a/app/Models/Event.php
+++ /dev/null
@@ -1,216 +0,0 @@
-<?php
-
-require_once(__DIR__ . '/../../db/connect.php');
-require_once(__DIR__ . '/../util.php');
-
-class EventModel {
-
-        public function createEvent($event_name, $stock, $event_price, $event_date, $event_location, $gambar, $vid) {
-        global $db;
-        $success = true;
-    
-        if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) {
-            $imageFilePath = '../assets/images/' . $gambar['name'];
-    
-            // Move the uploaded file to the desired directory
-            if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) {
-                echo "File uploaded successfully";
-            } else {
-                echo "Error moving file to destination";
-                $imageFilePath = null; // Set to null if there's an error
-            }
-        } else {
-            echo "No image uploaded";
-            $imageFilePath = null; // Set to null if no file is uploaded
-        }
-
-        if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) {
-            $vidFilePath = '../assets/videos/' . $vid['name'];
-    
-            // Move the uploaded file to the desired directory
-            if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) {
-                echo "File uploaded successfully";
-            } else {
-                echo "Error moving file to destination";
-                $vidFilePath = null; // Set to null if there's an error
-            }
-        } else {
-            echo "No video uploaded";
-            $vidFilePath = null; // Set to null if no file is uploaded
-        }
-
-        if ($imageFilePath === null || $vidFilePath === null) {
-            $success = false;
-            return $success;
-        }
-    
-        $stmt = $db->prepare("INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) VALUES (?, ?, ?, ?, ?, ?, ?)");
-    
-        if ($stmt->execute([$event_name, $stock, $event_price, $event_date, $event_location, $imageFilePath, $vidFilePath])) {
-            echo "Event created successfully";
-            return $success;
-        } else {
-            echo "Error creating event: " . print_r($stmt->errorInfo(), true);
-            $success = false;
-            return $success;
-        }
-    }
-    
-    public function updateEvent($event_id, $event_name, $event_price, $event_date, $event_location, $gambar, $vid) {
-        global $db;
-        $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);
-    
-        echo "Updating Event with ID: $event_id, Name: $event_name, Price: $event_price, Date: $event_date, Location: $event_location";
-        
-        if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) {
-            $imageFilePath = '../assets/images/' . $gambar['name'];
-    
-            // Move the uploaded file to the desired directory
-            if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) {
-                echo "File uploaded successfully<br>";
-            } else {
-                echo "Error moving file to destination<br>";
-                $imageFilePath = null; // Set to null if there's an error
-            }
-        } else {
-            echo "No image uploaded<br>";
-            $imageFilePath = null; // Set to null if no file is uploaded
-        }
-
-        if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) {
-            $vidFilePath = '../assets/videos/' . $vid['name'];
-    
-            // Move the uploaded file to the desired directory
-            if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) {
-                echo "File uploaded successfully<br>";
-            } else {
-                echo "Error moving file to destination<br>";
-                $vidFilePath = null; // Set to null if there's an error
-            }
-        } else {
-            echo "No video uploaded<br>";
-            $vidFilePath = null; // Set to null if no file is uploaded
-        }
-        
-        // chek wheter image or video is null or not
-        if ($imageFilePath === null && $vidFilePath === null) {
-            $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location' WHERE event_id = $event_id";
-        } elseif ($imageFilePath === null) {
-            $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location', vid = '$vidFilePath' WHERE event_id = $event_id";
-        } elseif ($vidFilePath === null) {
-            $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location', gambar = '$imageFilePath' WHERE event_id = $event_id";
-        } else {
-            $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location', gambar = '$imageFilePath', vid = '$vidFilePath' WHERE event_id = $event_id";
-        }
-    
-        $rowCount = $db->exec($sql);
-    
-        if ($rowCount !== false) {
-            echo "Event updated successfully. Rows affected: $rowCount";
-        } else {
-            echo "Error updating event: " . print_r($db->errorInfo(), true);
-        }
-        return "Event updated successfully";
-    }
-    
-    
-    
-    public function deleteEvent($eventId) {
-        global $db;
-    
-        try {
-            // Delete associated pembelian records
-            $stmtPembelian = $db->prepare("DELETE FROM pembelian WHERE ticket_id IN (SELECT ticket_id FROM tickets WHERE event_id = ?)");
-            $stmtPembelian->execute([$eventId]);
-    
-            // Delete associated tickets
-            $stmtTickets = $db->prepare("DELETE FROM tickets WHERE event_id = ?");
-            $stmtTickets->execute([$eventId]);
-    
-            // Delete the event
-            $stmtEvent = $db->prepare("DELETE FROM events WHERE event_id = ?");
-            $stmtEvent->execute([$eventId]);
-    
-            echo "Event, associated tickets, and pembelian records deleted successfully<br>";
-    
-            return "Event, associated tickets, and pembelian records deleted successfully";
-        } catch (PDOException $e) {
-            echo "Error: " . $e->getMessage() . "<br>";
-    
-            return "Error: " . $e->getMessage();
-        }
-    }
-    
-    public function getAllEvents() {
-        global $db;
-        $stmt = $db->prepare("SELECT * FROM events");
-        $stmt->execute();
-        return $stmt->fetchAll(PDO::FETCH_ASSOC);
-    }
-
-    public function getEvent($eventId) {
-        global $db;
-        $stmt = $db->prepare("SELECT * FROM events WHERE event_id = ?");
-        $stmt->execute([$eventId]);
-        return $stmt->fetch(PDO::FETCH_ASSOC);
-    }
-
-    public function getLastEventId() {
-        global $db;
-        $stmt = $db->prepare("SELECT event_id FROM events ORDER BY event_id DESC LIMIT 1");
-        $stmt->execute();
-        return $stmt->fetch(PDO::FETCH_ASSOC)['event_id'];
-    }
-
-    public function searchEvents($searchQuery, $sortKey, $minStock) {
-        global $db;
-
-        try {
-            $sql = "SELECT * FROM events WHERE 1"; // Start with a true condition
-
-            // Add search condition 
-            if (!empty($searchQuery)) {
-                $sql .= " AND (LOWER(event_name) LIKE CONCAT('%', :query, '%') OR LOWER(event_location) LIKE CONCAT('%', :query, '%'))";
-            }
-
-
-            // Add filter condition 
-            if ($minStock !== null) {
-                $sql .= " AND event_stock >= :minStock";
-            }
-
-            // Add sort condition
-            if ($sortKey === 'name') {
-                $sql .= " ORDER BY event_name ASC";
-            } elseif ($sortKey === 'location') {
-                $sql .= " ORDER BY event_location ASC";
-            }
-
-            $stmt = $db->prepare($sql);
-
-            // Bind search query parameter
-            if (!empty($searchQuery)) {
-                $lowerSearchQuery = strtolower("%" . $searchQuery . "%");
-                $stmt->bindParam(':query', $lowerSearchQuery, PDO::PARAM_STR);
-            }
-
-            // Bind filter parameter 
-            if ($minStock !== null) {
-                $stmt->bindParam(':minStock', $minStock, PDO::PARAM_INT);
-            }
-
-            $stmt->execute();
-
-            return $stmt->fetchAll(PDO::FETCH_ASSOC);
-        } catch (PDOException $e) {
-            throw new Exception("Error searching events: " . $e->getMessage());
-        }
-    }
-
-    
-
-
-}
-?>
-
-
diff --git a/app/Models/Pembelian.php b/app/Models/Pembelian.php
deleted file mode 100644
index 0fcf741d91a4773be623aefe0029031038b12efb..0000000000000000000000000000000000000000
--- a/app/Models/Pembelian.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-// app/models/Pembelian.php
-
-require_once(__DIR__ . '/../../db/connect.php');
-require_once(__DIR__ . '/../util.php');
-
-class PembelianModel {
-    public function createPembelian($ticketId, $userId, $createdTime) {
-        global $db;
-
-        $stmt = $db->prepare("INSERT INTO pembelian (ticket_id, user_id, pembelian_created_time) VALUES (?, ?, ?)");
-        if ($stmt->execute([$ticketId, $userId, $createdTime])) {
-            $stmt = $db->prepare("SELECT event_id FROM tickets WHERE ticket_id = ?");
-            $stmt->execute([$ticketId]);
-            $result = $stmt->fetch(PDO::FETCH_ASSOC);
-
-            if ($result) {
-                $eventId = $result['event_id'];
-
-                // Decrement the event's stock by 1
-                $stmt = $db->prepare("UPDATE events SET event_stock = event_stock - 1 WHERE event_id = ?");
-                return $stmt->execute([$eventId]);
-            }
-        }
-    }
-
-    public function getPembelian($pembelianId) {
-        global $db;
-
-        $stmt = $db->prepare("SELECT * FROM pembelian WHERE pembelian_id = ?");
-        $stmt->execute([$pembelianId]);
-
-        return $stmt->fetch(PDO::FETCH_ASSOC);
-    }
-
-    public function updatePembelian($pembelianId, $ticketId, $userId, $createdTime) {
-        global $db;
-
-        $stmt = $db->prepare("UPDATE pembelian SET ticket_id = ?, user_id = ?, pembelian_created_time = ? WHERE pembelian_id = ?");
-        $stmt->execute([$ticketId, $userId, $createdTime, $pembelianId]);
-
-        return "Pembelian updated successfully";
-    }
-
-    public function deletePembelian($pembelianId) {
-        global $db;
-
-        $stmt = $db->prepare("DELETE FROM pembelian WHERE pembelian_id = ?");
-        $stmt->execute([$pembelianId]);
-
-        return "Pembelian deleted successfully";
-    }
-
-    public function getAllPembelian(){
-        global $db;
-        $stmt = $db->prepare("SELECT * FROM pembelian");
-        $stmt->execute();
-        return $stmt->fetchAll(PDO::FETCH_ASSOC);
-    }
-
-    public function getAllPembelianWithDetails(){
-        global $db;
-        $stmt = $db->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id ORDER BY pembelian_created_time DESC");
-        $stmt->execute();
-        return $stmt->fetchAll(PDO::FETCH_ASSOC);
-    }
-
-    public function getPembelianByUserId($userId){
-        global $db;
-        $stmt = $db->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id WHERE user_id = ? ORDER BY pembelian_created_time DESC");
-        $stmt->execute([$userId]);
-        return $stmt->fetchAll(PDO::FETCH_ASSOC);
-    }
-}
-?>
diff --git a/app/Views/login/login.php b/app/Views/login/login.php
deleted file mode 100644
index 2ca035a560f262411451a7f910311c690fa21fdb..0000000000000000000000000000000000000000
--- a/app/Views/login/login.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-    session_start();
-?>
-<!DOCTYPE html>
-<html lang="en">
-
-    <head>
-        <title>Login • TICKET KU</title>
-        <meta charset="UTF-8">
-        <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
-        <link rel="stylesheet" type="text/css" href="../../../styles/auth.css">
-    </head>
-
-    <body>
-        <div class="login-container">
-            <h1>Login</h1>
-            <form id="loginForm" method="post" action="../../router.php">
-                <!-- Aslinya email atau username bisa(?) -->
-                <label for="email">Email or Username</label>
-                <input type="text" id="identifier" name="loginIdentifier" required>
-                
-                <label for="password">Password</label>
-                <input type="password" id="password" name="loginPassword" required>
-
-                <?php
-                // Check if there is an error message in the session
-                if (isset($_SESSION['message'])) {
-                    echo '<p>' . $_SESSION['message'] . '</p>';
-                    unset($_SESSION['message']); // Remove the error message from the session
-                }
-                ?>
-                <button type="submit" name="userAction" value="login">Login</button>
-            </form>
-            <p>Don't have an account? <a href="register.php">Register</a></p>
-        </div>
-    </body>
-</html>
\ No newline at end of file
diff --git a/app/router.php b/app/router.php
deleted file mode 100644
index 7156e5c4dea8e7de894027f76c3b7fb0b37c0ccd..0000000000000000000000000000000000000000
--- a/app/router.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-require_once './Controllers/PembelianController.php';
-require_once './Controllers/TicketController.php';
-require_once './Controllers/UserController.php';
-require_once './Controllers/EventController.php';
-
-$eventController = new EventController();
-$pembelianController = new PembelianController();
-$ticketController = new TicketController();
-$userController = new UserController();
-
-if ($_SERVER["REQUEST_METHOD"] == "POST") {
-    if (isset($_POST["eventAction"])) {
-        $eventController->handleRequest();
-    } elseif (isset($_POST["ticketAction"])) {
-        $ticketController->handleRequest();
-    } elseif (isset($_POST["userAction"])) {
-        $userController->handleRequest();
-    } elseif (isset($_POST["purchaseAction"])) {
-        $pembelianController->handleRequest();
-    }
-
-} elseif ($_SERVER["REQUEST_METHOD"] == "GET") {
-    if (isset($_GET["eventAction"]) && isset($_GET["eventId"])) {
-        $eventController->handleRequest();
-    } elseif (isset($_GET["ticketAction"])) {
-        $ticketController->handleRequest();
-    } elseif (isset($_GET["userAction"])) {
-        $userController->handleRequest();
-    }
-}
-?>
\ No newline at end of file
diff --git a/app/util.php b/app/util.php
deleted file mode 100644
index da3c6d57c9624c8dcc4ed19faa9297280b76715d..0000000000000000000000000000000000000000
--- a/app/util.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-function preprocess($str) {
-    return str_replace(' ', '%20', $str);
-}
-
-function formatPrice($price) {
-    return number_format($price,0,',','.');
-}
-
-function isEmailValid($email) {
-    return filter_var($email, FILTER_VALIDATE_EMAIL);
-}
-?>
\ No newline at end of file
diff --git a/database/1-create-table-users.sql b/database/1-create-table-users.sql
new file mode 100644
index 0000000000000000000000000000000000000000..b138fb00e6995f74d60e1779e04cb399fefdff38
--- /dev/null
+++ b/database/1-create-table-users.sql
@@ -0,0 +1,8 @@
+CREATE TABLE IF NOT EXISTS users (
+  user_ID SERIAL PRIMARY KEY,
+  user_name VARCHAR(255),
+  username VARCHAR(255) UNIQUE,
+  user_email VARCHAR(255) UNIQUE,
+  user_hashedPass VARCHAR(255),
+  isAdmin BOOLEAN
+);
\ No newline at end of file
diff --git a/database/2-create-table-events.sql b/database/2-create-table-events.sql
new file mode 100644
index 0000000000000000000000000000000000000000..80c7f2615c49a6f979ce5645488165c1d3e55e7f
--- /dev/null
+++ b/database/2-create-table-events.sql
@@ -0,0 +1,10 @@
+CREATE TABLE IF NOT EXISTS events (
+  event_id SERIAL PRIMARY KEY,
+  event_name VARCHAR(255),
+  event_stock INT,
+  event_price INT,
+  event_date TIMESTAMP,
+  event_location VARCHAR(255),
+  gambar VARCHAR(255),
+  vid VARCHAR(255)
+);
\ No newline at end of file
diff --git a/database/3-create-table-tickets.sql b/database/3-create-table-tickets.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0de3886b985ffe29f246aae4482fd3e48014d84d
--- /dev/null
+++ b/database/3-create-table-tickets.sql
@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS tickets (
+  ticket_id SERIAL PRIMARY KEY,
+  ticket_name VARCHAR(255),
+  event_id INT,
+  FOREIGN KEY (event_id) REFERENCES events(event_id) ON DELETE SET NULL
+);
diff --git a/database/4-create-table-pembelian.sql b/database/4-create-table-pembelian.sql
new file mode 100644
index 0000000000000000000000000000000000000000..05e8eacab283585a2c45d7a7c8cad6a0ea321475
--- /dev/null
+++ b/database/4-create-table-pembelian.sql
@@ -0,0 +1,8 @@
+CREATE TABLE IF NOT EXISTS pembelian (
+  pembelian_id SERIAL PRIMARY KEY,
+  ticket_id INT,
+  user_id INT,
+  pembelian_created_time TIMESTAMP,
+  FOREIGN KEY (ticket_id) REFERENCES tickets(ticket_id),
+  FOREIGN KEY (user_id) REFERENCES users(user_ID) ON DELETE SET NULL
+);
diff --git a/database/5-create-table-subscription.sql b/database/5-create-table-subscription.sql
new file mode 100644
index 0000000000000000000000000000000000000000..9f78283a64a43410fd26416c7ea047a88b24ef8f
--- /dev/null
+++ b/database/5-create-table-subscription.sql
@@ -0,0 +1,8 @@
+CREATE TABLE IF NOT EXISTS subscription (
+  creator_id INT NOT NULL,
+  subscriber_id INT NOT NULL,
+  status VARCHAR(10) NOT NULL DEFAULT 'PENDING',
+  creator_name VARCHAR(255) NOT NULL,
+  PRIMARY KEY (creator_id, subscriber_id),
+  FOREIGN KEY (subscriber_id) REFERENCES users(user_ID) ON DELETE CASCADE
+);
diff --git a/database/6-seed.sql b/database/6-seed.sql
new file mode 100644
index 0000000000000000000000000000000000000000..36241df86b2e292f4b88fdba181e83692d30af87
--- /dev/null
+++ b/database/6-seed.sql
@@ -0,0 +1,36 @@
+-- Generate and insert 100 dummy events with random data
+DO $$ 
+DECLARE
+    i INT;
+BEGIN
+    FOR i IN 1..100 LOOP
+        INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid)
+        VALUES (
+            'Event ' || i,
+            FLOOR(RANDOM() * 10) + 1,
+            FLOOR(RANDOM() * 91) + 10,
+            NOW() + (i || ' days')::INTERVAL,
+            'Location ' || i,
+            'assets/images/' || (i % 16 + 1) || '.jpg',
+            'assets/videos/video.mp4'
+        );
+
+        -- Generate and insert tickets corresponding to the event's event_stock
+        FOR j IN 1..(FLOOR(RANDOM() * 10) + 1) LOOP
+            INSERT INTO tickets (ticket_name, event_id)
+            VALUES (
+                'Ticket ' || j || ' for Event ' || i,
+                (SELECT MAX(event_id) FROM events)
+            );
+        END LOOP;
+    END LOOP;
+END $$;
+
+-- Insert user data
+INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin)
+VALUES
+    ('John Doe', 'john_doe', 'john@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'true'),
+    ('Jane Smith', 'jane_smith', 'jane@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'false'),
+    ('Admin User', 'admin_user', 'admin@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'true'),
+    ('Alice Johnson', 'alice', 'alice@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'false'),
+    ('Bob Williams', 'bob', 'bob@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'false');
diff --git a/db/connect.php b/db/connect.php
deleted file mode 100644
index 7ab45efbe3d2a27d58375be1bff764bafec8698a..0000000000000000000000000000000000000000
--- a/db/connect.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-    $host = 'db';  
-    $dbname = 'tubes1_WBD';  
-    $user = 'root';  
-    $pass = 'your_password';
-
-    try {
-        $db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
-
-        // Execute SQL statements from init.sql
-        $sqlInit = file_get_contents(__DIR__ . '/init.sql');
-        $db->exec($sqlInit);
-
-        // echo "Connected successfully and database initialized!<br/>";
-    } catch (PDOException $e) {
-        // echo "Connection failed: " . $e->getMessage();
-    }
-
-?>
diff --git a/db/data.php b/db/data.php
deleted file mode 100644
index 2b8c7e4f4a634b064b2c17efcd8c5b352b7c3b4c..0000000000000000000000000000000000000000
--- a/db/data.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-include 'connect.php';
-
-// Make sure $db is defined and not null
-if (isset($db)) {
-    try {
-        $db->beginTransaction();
-
-        // Insert events and tickets as before
-        $sqlEvent = <<<EOF
-            INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) VALUES
-            ('Music Concert', 2, 20, '2023-09-30 10:00:00', 'jakarta', 'assets/images/1.jpg', 'assets/videos/video.mp4'),
-            ('Art Exhibition', 2, 15, '2023-10-05 15:30:00', 'prancis', 'assets/images/2.png', 'assets/videos/video.mp4'),
-            ('Sports Tournament', 2, 40, '2023-11-12 18:45:00', 'italy', 'assets/images/3.jpg', 'assets/videos/video.mp4'),
-            ('Comedy Show', 2, 30, '2023-12-03 20:00:00', 'jakarta', 'assets/images/4.jpg', 'assets/videos/video.mp4'),
-            ('Tech Conference', 2, 60, '2024-01-18 14:15:00', 'ITB', 'assets/images/5.jpg', 'assets/videos/video.mp4');
-         EOF;
-
-         $sqlTicket = <<<EOF
-            INSERT INTO tickets (ticket_name, event_id) VALUES
-            ('General Admission', 1),
-            ('VIP Pass', 1),
-            ('Standard Ticket', 2),
-            ('Student Discount', 2),
-            ('Early Bird Special', 3),
-            ('Premium Access', 3),
-            ('Weekend Pass', 4),
-            ('Group Discount', 4),
-            ('Conference Pass', 5),
-            ('Exhibitor Pass', 5);
-         EOF;
-
-        $db->exec($sqlEvent);
-        $db->exec($sqlTicket);
-
-        // Dummy user data with hashed passwords
-        $userData = [
-            ['John Doe', 'john_doe', 'john@example.com', password_hash('password_1', PASSWORD_DEFAULT), 1],
-            ['Jane Smith', 'jane_smith', 'jane@example.com', password_hash('password_2', PASSWORD_DEFAULT), 0],
-            ['Admin User', 'admin_user', 'admin@example.com', password_hash('password_3', PASSWORD_DEFAULT), 1],
-            ['Alice Johnson', 'alice', 'alice@example.com', password_hash('password_4', PASSWORD_DEFAULT), 0],
-            ['Bob Williams', 'bob', 'bob@example.com', password_hash('password_5', PASSWORD_DEFAULT), 0]
-        ];
-
-        $sqlUser = "INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) VALUES (?, ?, ?, ?, ?)";
-        $stmt = $db->prepare($sqlUser);
-
-        foreach ($userData as $user) {
-            $stmt->execute($user);
-        }
-
-        $stmt->closeCursor();
-
-      //   // Insert pembelian data
-      //   $sqlPembelian = <<<EOF
-      //       INSERT INTO pembelian (ticket_id, user_id, pembelian_created_time) VALUES
-      //       (1, 1, '2023-10-01 12:30:00'),
-      //       (3, 2, '2023-10-06 16:15:00'),
-      //       (2, 3, '2023-11-15 20:00:00'),
-      //       (5, 4, '2023-12-05 10:45:00'),
-      //       (8, 5, '2024-01-20 08:30:00');
-      //    EOF;
-
-      //    $db->exec($sqlPembelian);
-
-         // Commit the transaction
-         $db->commit();
-
-         echo "Successfully inserted dummy data.<br/>";
-      } catch (PDOException $e) {
-         $db->rollBack();
-         echo "Error: " . $e->getMessage();
-      }
-   } else {
-      echo "Error: Database connection not established.";
-   }
-
-   $db = null;
-?>
diff --git a/db/init.php b/db/init.php
deleted file mode 100644
index d5efdd7fbee4a7978546eb4828d86c6a208c781c..0000000000000000000000000000000000000000
--- a/db/init.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-include 'connect.php';
-
-$dotenvContents = file_get_contents(__DIR__ . '/../.env');
-$dotenvLines = explode("\n", $dotenvContents);
-
-foreach ($dotenvLines as $line) {
-    // Skip empty lines and comments
-    if (!empty($line) && strpos($line, '=') !== false && strpos($line, '#') !== 0) {
-        list($name, $value) = explode('=', $line, 2);
-        $_ENV[$name] = $value;
-        putenv("$name=$value");
-    }
-}
-
-error_reporting(E_ALL);
-ini_set('display_errors', 1);
-
-
-include 'reset.php';
-include 'data.php';
-
-$db = null;
-
-// echo "Database initialization successful!";
-?>
diff --git a/db/init.sql b/db/init.sql
deleted file mode 100644
index 0beaedfc29604f9454f333b3a4411b5108553768..0000000000000000000000000000000000000000
--- a/db/init.sql
+++ /dev/null
@@ -1,48 +0,0 @@
-CREATE DATABASE IF NOT EXISTS tubes1_WBD;
-
-USE tubes1_WBD;
-
-CREATE TABLE IF NOT EXISTS events (
-  event_id INT AUTO_INCREMENT PRIMARY KEY,
-  event_name CHAR(255),
-  event_stock INT,
-  event_price INT,
-  event_date DATETIME,
-  event_location CHAR(255),
-  gambar VARCHAR(255),
-  vid VARCHAR(255)
-);
-
-CREATE TABLE IF NOT EXISTS tickets (
-  ticket_id INT AUTO_INCREMENT PRIMARY KEY,
-  ticket_name CHAR(255),
-  event_id INT,
-  FOREIGN KEY (event_id) REFERENCES events(event_id) ON DELETE SET NULL
-);
-
-CREATE TABLE IF NOT EXISTS users (
-  user_ID INT AUTO_INCREMENT PRIMARY KEY,
-  user_name CHAR(255),
-  username CHAR(255) UNIQUE,
-  user_email VARCHAR(255) UNIQUE,
-  user_hashedPass CHAR(255),
-  isAdmin BOOLEAN
-);
-
-CREATE TABLE IF NOT EXISTS pembelian (
-  pembelian_id INT AUTO_INCREMENT PRIMARY KEY,
-  ticket_id INT,
-  user_id INT,
-  pembelian_created_time DATETIME,
-  FOREIGN KEY (ticket_id) REFERENCES tickets(ticket_id),
-  FOREIGN KEY (user_id) REFERENCES users(user_ID) ON DELETE SET NULL
-);
-
-CREATE TABLE IF NOT EXISTS subscription (
-  creator_id int NOT NULL,
-  subscriber_id int NOT NULL,
-  status enum('PENDING','ACCEPTED','REJECTED') NOT NULL DEFAULT 'PENDING',
-  creator_name char(255) NOT NULL,
-  PRIMARY KEY (creator_id, subscriber_id),
-  FOREIGN KEY (subscriber_id) REFERENCES users(user_ID) ON DELETE CASCADE
-);
\ No newline at end of file
diff --git a/db/reset.php b/db/reset.php
deleted file mode 100644
index 1e98b7a351e2e637d0fa059e489aad7e4f08635b..0000000000000000000000000000000000000000
--- a/db/reset.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-   include 'connect.php';
-
-   try {
-      $db->exec("DROP TABLE IF EXISTS pembelian");
-      $db->exec("DROP TABLE IF EXISTS tickets");
-      $db->exec("DROP TABLE IF EXISTS events");
-      $db->exec("DROP TABLE IF EXISTS users");
-
-      // echo "Successfully reset the database<br/>";
-   } catch (PDOException $e) {
-      // echo "Error: " . $e->getMessage();
-   }
-   $db = null;
-?>
\ No newline at end of file
diff --git a/src/.htaccess b/src/.htaccess
new file mode 100644
index 0000000000000000000000000000000000000000..122631ddccca95f9c7deb4126fa8f005bb799d5f
--- /dev/null
+++ b/src/.htaccess
@@ -0,0 +1,13 @@
+DirectoryIndex index.php
+
+RewriteEngine On
+
+RewriteBase /
+
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+
+RewriteRule ^(.*)$ index.php [QSA]
+
+php_value post_max_size 16M
+php_value upload_max_filesize 16M
\ No newline at end of file
diff --git a/styles/auth.css b/src/Client/auth.css
similarity index 100%
rename from styles/auth.css
rename to src/Client/auth.css
diff --git a/app/Views/template/event.php b/src/Client/components/event.php
similarity index 100%
rename from app/Views/template/event.php
rename to src/Client/components/event.php
diff --git a/app/Views/template/footer.php b/src/Client/components/footer.php
similarity index 100%
rename from app/Views/template/footer.php
rename to src/Client/components/footer.php
diff --git a/app/Views/template/history.php b/src/Client/components/history.php
similarity index 100%
rename from app/Views/template/history.php
rename to src/Client/components/history.php
diff --git a/app/Views/template/navbar.php b/src/Client/components/navbar.php
similarity index 90%
rename from app/Views/template/navbar.php
rename to src/Client/components/navbar.php
index ec8dd2abb5c9159fc789683ffbc72588471a9771..d8b9f315cf42e553115cdee21afd786606fc9056 100644
--- a/app/Views/template/navbar.php
+++ b/src/Client/components/navbar.php
@@ -7,7 +7,7 @@
             <li><a href="/app/Views/history/history.php">History</a></li>
             <!-- Logout Button -->
             <li>
-                <form method="post" action="/app/router.php">
+                <form method="post" action="/logout">
                     <button type="submit" name="userAction" value="logout">Logout</button>
                 </form>
             </li>
diff --git a/styles/container.css b/src/Client/container.css
similarity index 100%
rename from styles/container.css
rename to src/Client/container.css
diff --git a/styles/dropdown.css b/src/Client/dropdown.css
similarity index 100%
rename from styles/dropdown.css
rename to src/Client/dropdown.css
diff --git a/styles/footer.css b/src/Client/footer.css
similarity index 100%
rename from styles/footer.css
rename to src/Client/footer.css
diff --git a/styles/form.css b/src/Client/form.css
similarity index 100%
rename from styles/form.css
rename to src/Client/form.css
diff --git a/styles/global.css b/src/Client/global.css
similarity index 100%
rename from styles/global.css
rename to src/Client/global.css
diff --git a/styles/navbar.css b/src/Client/navbar.css
similarity index 100%
rename from styles/navbar.css
rename to src/Client/navbar.css
diff --git a/app/Views/event/create.php b/src/Client/pages/event/create.php
similarity index 95%
rename from app/Views/event/create.php
rename to src/Client/pages/event/create.php
index b486caa397b265e68072d2f4b78ee48646346236..75b6a10b2118c919657b3faf07bebba8ccdc766d 100644
--- a/app/Views/event/create.php
+++ b/src/Client/pages/event/create.php
@@ -1,5 +1,8 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }    
     ob_start();
     if (!isset($_SESSION["user_id"])) {
         echo "here";
diff --git a/app/Views/event/update.php b/src/Client/pages/event/update.php
similarity index 97%
rename from app/Views/event/update.php
rename to src/Client/pages/event/update.php
index 3d638008c04ae889ba49048259af52b843fa0c29..84f1251705869979df5035fc2a46c0a1d5aaa7d7 100644
--- a/app/Views/event/update.php
+++ b/src/Client/pages/event/update.php
@@ -1,5 +1,8 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
     ob_start();
     if (!isset($_SESSION["user_id"])) {
         echo "here";
diff --git a/app/Views/history/history.php b/src/Client/pages/history/history.php
similarity index 96%
rename from app/Views/history/history.php
rename to src/Client/pages/history/history.php
index b2e02634119d3edb062c656a5cdf4a3e41ac6c9d..10b8f5740cda2ae192de1506f1c1c55f56cca2cf 100644
--- a/app/Views/history/history.php
+++ b/src/Client/pages/history/history.php
@@ -1,5 +1,8 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
     ob_start();
     if (!isset($_SESSION["user_id"])) {
         echo "here";
diff --git a/app/Views/home/home.php b/src/Client/pages/home/home.php
similarity index 78%
rename from app/Views/home/home.php
rename to src/Client/pages/home/home.php
index 701666b3ed1ed21f2fa786cc27dd08f05d741bf5..1cd9d381a804b98e292ce9be199e106815df1614 100644
--- a/app/Views/home/home.php
+++ b/src/Client/pages/home/home.php
@@ -1,22 +1,25 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
     ob_start();
     if (!isset($_SESSION["user_id"])) {
         echo "here";
         // User is not authenticated; redirect to login page
-        header("Location: /app/Views/login/login.php");
+        header("Location: login");
         ob_end_flush();
     }
 
-    require_once '../../Controllers/PembelianController.php';
-    require_once '../../Controllers/TicketController.php';
-    require_once '../../Controllers/UserController.php';
-    require_once '../../Controllers/EventController.php';
+    require_once (__DIR__.'/../../../Server/Controllers/PembelianController.php');
+    require_once (__DIR__.'/../../../Server/Controllers/TicketController.php');
+    require_once (__DIR__.'/../../../Server/Controllers/UserController.php');
+    require_once (__DIR__.'/../../../Server/Controllers/EventController.php');
 
     $eventController = new EventController();
     $pembelianController = new PembelianController();
     $ticketController = new TicketController();
-    $userController = new UserController();
+    $userController = new \Server\Controllers\UserController();
 
     // Handle search query
     $searchQuery = isset($_GET['search']) ? $_GET['search'] : '';
@@ -36,7 +39,7 @@
     $currentPage = $paginationData['page'];
     $maxPage = $paginationData['maxpage'];
 
-    $isAdmin = $userController->getUser($_SESSION['user_id'])['isAdmin'];
+    $isAdmin = $userController->getUser($_SESSION['user_id'])['isadmin'];
 ?>
 
 <!DOCTYPE html>
@@ -46,20 +49,20 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>HOME • TICKET KU</title>
-    <link rel="stylesheet" type="text/css" href="/../../styles/global.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/form.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/footer.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/navbar.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/container.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/auth.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/dropdown.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/pagination.css">
-    <link rel="stylesheet" type="text/css" href="/../../styles/media.css">
+    <link rel="stylesheet" type="text/css" href="/../../global.css">
+    <link rel="stylesheet" type="text/css" href="/../../form.css">
+    <link rel="stylesheet" type="text/css" href="/../../footer.css">
+    <link rel="stylesheet" type="text/css" href="/../../navbar.css">
+    <link rel="stylesheet" type="text/css" href="/../../container.css">
+    <link rel="stylesheet" type="text/css" href="/../../auth.css">
+    <link rel="stylesheet" type="text/css" href="/../../dropdown.css">
+    <link rel="stylesheet" type="text/css" href="/../../pagination.css">
+    <link rel="stylesheet" type="text/css" href="/../../media.css">
 </head>
 
 <body>
 <!-- Navbar -->
-    <?php include '../template/navbar.php';?>
+    <?php include (__DIR__.'/../../components/navbar.php');?>
 
     <div class="main-content">
         <div class="column">
@@ -67,19 +70,20 @@
                 <button onclick="openCreateEventPage()" id="createEventBtn" class="admin">Create Event</button>
             <?php endif; ?>
             <div class="row">
-                <input type="text" id="searchInput" placeholder="Search.." value="<?= htmlspecialchars($searchQuery)?>" style="width:250%;">
+                <input type="text" id="searchInput" placeholder="Search.." value="<?= isset($searchQuery) ? htmlspecialchars($searchQuery) : '' ?>" style="width:250%;">
                 <select name="sort" id="sortSelect" class="styled-select">
                     <option value="" <?= empty($sortKey) ? 'selected' : '' ?>>No Sorting</option>
                     <option value="name" <?= $sortKey === 'name' ? 'selected' : '' ?>>Sort by Name</option>
                     <option value="location" <?= $sortKey === 'location' ? 'selected' : '' ?>>Sort by Location</option>
                 </select>
                 <!-- Change input type to "text" for minimum stock -->
-                <input type="text" id="minStockInput" name="min_stock" placeholder="Min Stock" value="<?= htmlspecialchars($minStock) ?>">
+                <input type="text" id="minStockInput" name="min_stock" placeholder="Min Stock" value="<?= isset($minStock) ? htmlspecialchars($minStock) : 0 ?>"
+">
                 <button type="submit" id="search-button">Search</button>
             </div>
             
             <?php foreach ($events as $event) :    
-                include '../template/event.php';
+                include (__DIR__.'/../../components/event.php');
             endforeach;?>
 
             <div class="pagination">
@@ -112,7 +116,7 @@
         </div>
     </div>
     
-    <?php include '../template/footer.php';?>
+    <?php include (__DIR__.'/../../components/footer.php');?>
 
     <script defer>
         function toggleMenu() {
@@ -142,7 +146,7 @@
                 const sortKey = document.getElementById('sortSelect').value;
 
                 // Construct the URL with search, min_stock, and sort parameters
-                const url = `/app/Views/home/home.php?search=${encodeURIComponent(searchQuery)}&min_stock=${encodeURIComponent(minStock)}&sort=${encodeURIComponent(sortKey)}`;
+                const url = `/home?search=${encodeURIComponent(searchQuery)}&min_stock=${encodeURIComponent(minStock)}&sort=${encodeURIComponent(sortKey)}`;
 
                 // Redirect to the updated URL
                 window.location.href = url;
diff --git a/src/Client/pages/login/login.php b/src/Client/pages/login/login.php
new file mode 100644
index 0000000000000000000000000000000000000000..017eba77ce35f882a7c4bf9b1cbf47ab1f9522d4
--- /dev/null
+++ b/src/Client/pages/login/login.php
@@ -0,0 +1,40 @@
+<?php
+if (session_status() == PHP_SESSION_NONE) {
+    // If a session is not already started, start a new one
+    session_start();
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <title>Login • TICKET KU</title>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
+    <link rel="stylesheet" type="text/css" href="../../auth.css">
+</head>
+
+<body>
+    <div class="login-container">
+        <h1>Login</h1>
+        <form id="loginForm" method="post" action="login">
+            <!-- Aslinya email atau username bisa(?) -->
+            <label for="email">Email or Username</label>
+            <input type="text" id="identifier" name="loginIdentifier" required>
+            
+            <label for="password">Password</label>
+            <input type="password" id="password" name="loginPassword" required>
+
+            <?php
+            // Check if there is an error message in the session
+            if (isset($_SESSION['message'])) {
+                echo '<p>' . $_SESSION['message'] . '</p>';
+                unset($_SESSION['message']); // Remove the error message from the session
+            }
+            ?>
+            <button type="submit" name="userAction" value="login">Login</button>
+        </form>
+        <p>Don't have an account? <a href="register">Register</a></p>
+    </div>
+</body>
+</html>
diff --git a/app/Views/login/register.php b/src/Client/pages/login/register.php
similarity index 81%
rename from app/Views/login/register.php
rename to src/Client/pages/login/register.php
index bdd3a0966d3145b309d50affbab88467c515ea29..660b237cd1d8bd7427fe0e40d4941d6492bc5095 100644
--- a/app/Views/login/register.php
+++ b/src/Client/pages/login/register.php
@@ -1,5 +1,8 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
 ?>
 <!DOCTYPE html>
 <html lang="en">
@@ -8,13 +11,13 @@
         <title>Register • TICKET KU</title>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
-        <link rel="stylesheet" type="text/css" href="../../../styles/auth.css">
+        <link rel="stylesheet" type="text/css" href="../../auth.css">
     </head>
 
     <body>
         <div class="register-container">
             <h1>Register</h1>
-            <form id="registerForm" method="post" action="../../router.php">
+            <form id="registerForm" method="post" action="register">
                 <label for="userName">Name</label>
                 <input type="text" id="userName" name="userName" required>
 
@@ -41,7 +44,7 @@
 
                 <button type="submit" name="userAction" value="createUser">Register</button>
             </form>
-            <p>Already have an account? <a href="login.php">Login</a></p>
+            <p>Already have an account? <a href="login">Login</a></p>
         </div>
     </body>
 </html>
\ No newline at end of file
diff --git a/app/Views/pembelian/pembelian.php b/src/Client/pages/pembelian/pembelian.php
similarity index 96%
rename from app/Views/pembelian/pembelian.php
rename to src/Client/pages/pembelian/pembelian.php
index 00d8ce4560b65c3e8d7c566cda67c1ad52ecbfbc..e8b2cfad7daad63cfd7b0bac446709cd840bc7c6 100644
--- a/app/Views/pembelian/pembelian.php
+++ b/src/Client/pages/pembelian/pembelian.php
@@ -1,5 +1,8 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
     ob_start();
     if (!isset($_SESSION["user_id"])) {
         echo "here";
diff --git a/app/Views/profile/edit_profile.php b/src/Client/pages/profile/edit_profile.php
similarity index 100%
rename from app/Views/profile/edit_profile.php
rename to src/Client/pages/profile/edit_profile.php
diff --git a/app/Views/profile/view_profile.php b/src/Client/pages/profile/view_profile.php
similarity index 95%
rename from app/Views/profile/view_profile.php
rename to src/Client/pages/profile/view_profile.php
index 2eab3bcced344f665141e7c4879a072fa6607f73..7c3c492596ce2e88bac20d1e174093508d4ecf5c 100644
--- a/app/Views/profile/view_profile.php
+++ b/src/Client/pages/profile/view_profile.php
@@ -1,5 +1,8 @@
 <?php
-    session_start();
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
     ob_start();
     if (!isset($_SESSION["user_id"])) {
         echo "here";
diff --git a/styles/pagination.css b/src/Client/pagination.css
similarity index 100%
rename from styles/pagination.css
rename to src/Client/pagination.css
diff --git a/app/Controllers/EventController.php b/src/Server/Controllers/EventController.php
similarity index 97%
rename from app/Controllers/EventController.php
rename to src/Server/Controllers/EventController.php
index 2961a637e58138af8df7c7c26365bee9aff3b89e..0e5c9be2ce8f9e58f260092527fa55aa20a80549 100644
--- a/app/Controllers/EventController.php
+++ b/src/Server/Controllers/EventController.php
@@ -1,8 +1,7 @@
 <?php
-// app/Controllers/EventController.php
 
 ob_start();
-require_once(__DIR__ . '/../Models/Event.php');
+include(__DIR__ . '../../Models/Event.php');
 require_once(__DIR__ . '/TicketController.php');
 
 
@@ -10,7 +9,7 @@ class EventController {
     private $eventModel;
 
     public function __construct() {
-        $this->eventModel = new EventModel();
+        $this->eventModel = new \Server\Models\EventModel();
     }
 
     public function createEvent($event_name, $stock, $event_price, $event_date, $event_location, $gambar, $vid){
diff --git a/src/Server/Controllers/HomeController.php b/src/Server/Controllers/HomeController.php
new file mode 100644
index 0000000000000000000000000000000000000000..edb1b11791f9ff6066ce07cc2a7fc8906eccbc2d
--- /dev/null
+++ b/src/Server/Controllers/HomeController.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Server\Controllers;
+
+class HomeController {
+    public function __construct(){}
+    public function home()
+    {
+        include (__DIR__.'/../../Client/pages/home/home.php');
+    }
+}
\ No newline at end of file
diff --git a/app/Controllers/PembelianController.php b/src/Server/Controllers/PembelianController.php
similarity index 96%
rename from app/Controllers/PembelianController.php
rename to src/Server/Controllers/PembelianController.php
index 9f5526def638e8436eec7807ffeff1778b9b542e..5f5701d1ca0c89316e0a11613fe54f96c3b84971 100644
--- a/app/Controllers/PembelianController.php
+++ b/src/Server/Controllers/PembelianController.php
@@ -10,11 +10,10 @@ class PembelianController {
     
     
     public function __construct() {
-        $this->pembelianModel = new PembelianModel();
+        $this->pembelianModel = new \Server\Models\PembelianModel();
     }
 
     public function createPembelian($ticketId, $userId, $createdTime) {
-        $pembelianModel = new PembelianModel();
         return $this->pembelianModel->createPembelian($ticketId, $userId, $createdTime);
     }
 
diff --git a/app/Controllers/SubscriptionController.php b/src/Server/Controllers/SubscriptionController.php
similarity index 100%
rename from app/Controllers/SubscriptionController.php
rename to src/Server/Controllers/SubscriptionController.php
diff --git a/app/Controllers/TicketController.php b/src/Server/Controllers/TicketController.php
similarity index 96%
rename from app/Controllers/TicketController.php
rename to src/Server/Controllers/TicketController.php
index 962586f10ebe910073345edf0e57faa66d2b421c..8d2944d1caebee23162052f5944727596ac0f275 100644
--- a/app/Controllers/TicketController.php
+++ b/src/Server/Controllers/TicketController.php
@@ -8,7 +8,7 @@ class TicketController {
     private $ticketModel;
 
     public function __construct() {
-        $this->ticketModel = new TicketModel();
+        $this->ticketModel = new \Server\Models\TicketModel();
     }
 
     public function createTicket($name, $eventId) {
diff --git a/app/Controllers/UserController.php b/src/Server/Controllers/UserController.php
similarity index 64%
rename from app/Controllers/UserController.php
rename to src/Server/Controllers/UserController.php
index 3ae2e6c4c5ede827e7bf481525c9e222bda0eafd..6bf0731f73c13ca45eca90d6520f1afe6bcb44b4 100644
--- a/app/Controllers/UserController.php
+++ b/src/Server/Controllers/UserController.php
@@ -1,14 +1,15 @@
 <?php
-// app/controllers/userController.php
-ob_start();
-require_once(__DIR__ . '/../Models/User.php');
+
+namespace Server\Controllers;
+
+include (__DIR__.'/../Models/User.php');
 
 
 class UserController {
     private $userModel;
 
     public function __construct() {
-        $this->userModel = new UserModel();
+        $this->userModel = new \Server\Models\UserModel();
     }
 
     public function createUser($name, $username, $email, $hashedPass, $isAdmin) {
@@ -32,8 +33,15 @@ class UserController {
     }
     
     public function registerUser($name, $username, $email, $password, $isAdmin) {
-        return $this->createUser($name, $username, $email, password_hash($password,PASSWORD_DEFAULT), $isAdmin);
+        $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
+    
+        if ($hashedPassword === false) {
+            return ['success' => false, 'message' => 'Password hashing failed'];
+        }
+    
+        return $this->createUser($name, $username, $email, $hashedPassword, $isAdmin);
     }
+    
 
     public function loginByEmail($email,$password) {
         $user = $this->userModel->getUserByEmail($email);
@@ -45,18 +53,6 @@ class UserController {
             return "wrong credentials";
         }
     }
-
-    public function loginByUsername($username,$password) {
-        $user = $this->userModel->getUserByUsername($username);
-        if ($user !== false && password_verify($password, $user['user_hashedPass'])) {
-            session_start();
-            $_SESSION["user_id"] = $user['user_ID'];
-            return "success";
-        } else {
-            session_start();
-            return "wrong credentials";
-        }
-    }
     
     public function logout() {
         session_start();
@@ -72,6 +68,90 @@ class UserController {
     public function editProfile($user_id, $name, $username, $email) {
         return $this->userModel->editProfile($user_id, $name, $username, $email);
     }
+
+    public function loginview() {
+        if (session_status() == PHP_SESSION_NONE) {
+            // If a session is not already started, start a new one
+            session_start();
+        }
+        // Check if the user is already logged in, redirect to home if true
+        if (isset($_SESSION['user_id'])) {
+            header("Location: /home");
+            ob_end_flush();
+            exit();
+        }
+
+        include (__DIR__.'/../../Client/pages/login/login.php');
+    }
+
+    public function login() {
+        // Check if the required parameters are set in the POST request
+        if (isset($_POST['loginIdentifier']) && isset($_POST['loginPassword'])) {
+            $emailOrUsername = $_POST['loginIdentifier'];
+            $password = $_POST['loginPassword'];
+    
+            if (filter_var($emailOrUsername, FILTER_VALIDATE_EMAIL)) {
+                $user = $this->userModel->getUserByEmail($emailOrUsername);
+            } else {
+                $user = $this->userModel->getUserByUsername($emailOrUsername);
+            }
+    
+            if ($user !== false) {
+                if (password_verify($password, $user['user_hashedpass'])) {
+                    session_start();
+                    $_SESSION["user_id"] = $user['user_id'];
+                    header("Location: /home");
+                    ob_end_flush();
+                    exit();
+                } else {
+                    session_start();
+                    $_SESSION['message'] = "Wrong Password";
+                    header("Location: /login");
+                    ob_end_flush();
+                    exit();
+                }
+            } else {
+                session_start();
+                $_SESSION['message'] = "Wrong credentials";
+                header("Location: /login");
+                ob_end_flush();
+                exit();
+            }
+        } else {
+            // Handle missing parameters
+            session_start();
+            $_SESSION['message'] = "Missing login parameters";
+            header("Location: /login");
+            ob_end_flush();
+            exit();
+        }
+    }    
+
+    public function registerview() {
+        include (__DIR__."/../../Client/pages/login/register.php");
+    }
+
+    public function register() {
+        $userName = $_POST['userName'];
+        $userUsername = $_POST['userUsername'];
+        $userEmail = $_POST['userEmail'];
+        $userPassword = $_POST['userPassword'];
+        $isAdmin = isset($_POST['isAdmin']) ? 1 : 0;
+        $response = $this->registerUser($userName,$userUsername,$userEmail,$userPassword,$isAdmin);
+
+        $success = $response['success'];
+        if($success){
+            session_start();
+            $_SESSION['message'] = "You have successfully registered. Please log in";
+            header("Location:login");
+            ob_end_flush();
+        } else {
+            session_start();
+            $_SESSION['error_message'] = $response['message'];
+            header("Location:register");
+            ob_end_flush();
+        }
+    }
     
     public function handleRequest() {
         if (isset($_POST['userAction'])) {
diff --git a/src/Server/Models/Event.php b/src/Server/Models/Event.php
new file mode 100644
index 0000000000000000000000000000000000000000..85a902113d132e4f336c19aa5caa940d90963c53
--- /dev/null
+++ b/src/Server/Models/Event.php
@@ -0,0 +1,176 @@
+<?php
+
+namespace Server\Models;
+
+use PDO;
+
+class EventModel extends Model {
+
+    public function createEvent($event_name, $stock, $event_price, $event_date, $event_location, $gambar, $vid) {
+        $success = true;
+
+        if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) {
+            $imageFilePath = '../assets/images/' . $gambar['name'];
+
+            if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) {
+                echo "File uploaded successfully";
+            } else {
+                echo "Error moving file to destination";
+                $imageFilePath = null; // Set to null if there's an error
+            }
+        } else {
+            echo "No image uploaded";
+            $imageFilePath = null; // Set to null if no file is uploaded
+        }
+
+        if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) {
+            $vidFilePath = '../assets/videos/' . $vid['name'];
+
+            if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) {
+                echo "File uploaded successfully";
+            } else {
+                echo "Error moving file to destination";
+                $vidFilePath = null; // Set to null if there's an error
+            }
+        } else {
+            echo "No video uploaded";
+            $vidFilePath = null; // Set to null if no file is uploaded
+        }
+
+        if ($imageFilePath === null || $vidFilePath === null) {
+            $success = false;
+            return $success;
+        }
+
+        $stmt = $this->database->prepare("INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) VALUES (?, ?, ?, ?, ?, ?, ?)");
+
+        if ($stmt->execute([$event_name, $stock, $event_price, $event_date, $event_location, $imageFilePath, $vidFilePath])) {
+            echo "Event created successfully";
+            return $success;
+        } else {
+            echo "Error creating event: " . print_r($stmt->errorInfo(), true);
+            $success = false;
+            return $success;
+        }
+    }
+
+    public function updateEvent($event_id, $event_name, $event_price, $event_date, $event_location, $gambar, $vid) {
+        $sql = "UPDATE events SET event_name = ?, event_price = ?, event_date = ?, event_location = ?";
+
+        if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) {
+            $imageFilePath = '../assets/images/' . $gambar['name'];
+
+            if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) {
+                echo "File uploaded successfully<br>";
+            } else {
+                echo "Error moving file to destination<br>";
+                $imageFilePath = null; // Set to null if there's an error
+            }
+
+            $sql .= ", gambar = ?";
+        }
+
+        if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) {
+            $vidFilePath = '../assets/videos/' . $vid['name'];
+
+            if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) {
+                echo "File uploaded successfully<br>";
+            } else {
+                echo "Error moving file to destination<br>";
+                $vidFilePath = null; // Set to null if there's an error
+            }
+
+            $sql .= ", vid = ?";
+        }
+
+        $sql .= " WHERE event_id = ?";
+
+        $stmt = $this->database->prepare($sql);
+
+        $params = [$event_name, $event_price, $event_date, $event_location];
+
+        if ($imageFilePath !== null) {
+            $params[] = $imageFilePath;
+        }
+
+        if ($vidFilePath !== null) {
+            $params[] = $vidFilePath;
+        }
+
+        $params[] = $event_id;
+
+        $rowCount = $stmt->execute($params);
+
+        if ($rowCount !== false) {
+            echo "Event updated successfully. Rows affected: $rowCount";
+        } else {
+            echo "Error updating event: " . print_r($stmt->errorInfo(), true);
+        }
+        return "Event updated successfully";
+    }
+
+    public function deleteEvent($eventId) {
+        try {
+            // Delete associated records or perform necessary cleanup
+
+            $stmtEvent = $this->database->prepare("DELETE FROM events WHERE event_id = ?");
+            $stmtEvent->execute([$eventId]);
+
+            echo "Event deleted successfully<br>";
+
+            return "Event deleted successfully";
+        } catch (PDOException $e) {
+            echo "Error: " . $e->getMessage() . "<br>";
+
+            return "Error: " . $e->getMessage();
+        }
+    }
+
+    public function getAllEvents() {
+        $stmt = $this->database->prepare("SELECT * FROM events");
+        $stmt->execute();
+        return $stmt->fetchAll(PDO::FETCH_ASSOC);
+    }
+
+    public function getEvent($eventId) {
+        $stmt = $this->database->prepare("SELECT * FROM events WHERE event_id = ?");
+        $stmt->execute([$eventId]);
+        return $stmt->fetch(PDO::FETCH_ASSOC);
+    }
+
+    public function getLastEventId() {
+        $stmt = $this->database->prepare("SELECT event_id FROM events ORDER BY event_id DESC LIMIT 1");
+        $stmt->execute();
+        return $stmt->fetch(PDO::FETCH_ASSOC)['event_id'];
+    }
+
+    public function searchEvents($searchQuery, $sortKey, $minStock) {
+        try {
+            if ($minStock == null) {
+                $minStock = 0;
+            }
+    
+            $stmt = "SELECT * FROM events 
+                     WHERE (LOWER(event_name) LIKE LOWER(?) OR LOWER(event_location) LIKE LOWER(?)) 
+                     AND event_stock >= ?";
+    
+            if (!empty($sortKey)) {
+                $stmt .= " ORDER BY ";
+    
+                if ($sortKey === 'name') {
+                    $stmt .= "event_name ASC";
+                } elseif ($sortKey === 'location') {
+                    $stmt .= "event_location ASC";
+                } 
+            }
+    
+            $query = $this->database->prepare($stmt);
+            $query->execute(array('%'.$searchQuery.'%', '%'.$searchQuery.'%', $minStock));
+    
+            return $query->fetchAll(PDO::FETCH_ASSOC);
+        } catch (PDOException $e) {
+            throw new Exception("Error searching events: " . $e->getMessage());
+        }
+    }
+    
+}
diff --git a/src/Server/Models/Model.php b/src/Server/Models/Model.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc2fe6b25246c1204f7827f0509c4d012a633c60
--- /dev/null
+++ b/src/Server/Models/Model.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Server\Models;
+
+use PDO;
+
+class Model {
+    protected $database;
+
+    public function __construct()
+    {
+        $dsn = "pgsql:host=ticketku-php-db;port=5433;dbname=ticketku;";
+        $user = "postgres";
+        $password = "postgres";
+        try {
+            $this->database = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
+        } catch (\PDOException $e) {
+            die($e->getMessage());
+        }
+    }
+
+}
diff --git a/src/Server/Models/Pembelian.php b/src/Server/Models/Pembelian.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed44a4bbb58d2b0d2228725a1dd768060e74e678
--- /dev/null
+++ b/src/Server/Models/Pembelian.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Server\Models;
+
+use PDO;
+
+class PembelianModel extends Model {
+    public function createPembelian($ticketId, $userId, $createdTime) {
+        $stmt = $this->database->prepare("INSERT INTO pembelian (ticket_id, user_id, pembelian_created_time) VALUES (?, ?, ?)");
+
+        if ($stmt->execute([$ticketId, $userId, $createdTime])) {
+            $stmt = $this->database->prepare("SELECT event_id FROM tickets WHERE ticket_id = ?");
+            $stmt->execute([$ticketId]);
+            $result = $stmt->fetch(PDO::FETCH_ASSOC);
+
+            if ($result) {
+                $eventId = $result['event_id'];
+
+                // Decrement the event's stock by 1
+                $stmt = $this->database->prepare("UPDATE events SET event_stock = event_stock - 1 WHERE event_id = ?");
+                return $stmt->execute([$eventId]);
+            }
+        }
+    }
+
+    public function getPembelian($pembelianId) {
+        $stmt = $this->database->prepare("SELECT * FROM pembelian WHERE pembelian_id = ?");
+        $stmt->execute([$pembelianId]);
+
+        return $stmt->fetch(PDO::FETCH_ASSOC);
+    }
+
+    public function updatePembelian($pembelianId, $ticketId, $userId, $createdTime) {
+        $stmt = $this->database->prepare("UPDATE pembelian SET ticket_id = ?, user_id = ?, pembelian_created_time = ? WHERE pembelian_id = ?");
+        $stmt->execute([$ticketId, $userId, $createdTime, $pembelianId]);
+
+        return "Pembelian updated successfully";
+    }
+
+    public function deletePembelian($pembelianId) {
+        $stmt = $this->database->prepare("DELETE FROM pembelian WHERE pembelian_id = ?");
+        $stmt->execute([$pembelianId]);
+
+        return "Pembelian deleted successfully";
+    }
+
+    public function getAllPembelian() {
+        $stmt = $this->database->prepare("SELECT * FROM pembelian");
+        $stmt->execute();
+        return $stmt->fetchAll(PDO::FETCH_ASSOC);
+    }
+
+    public function getAllPembelianWithDetails() {
+        $stmt = $this->database->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id ORDER BY pembelian_created_time DESC");
+        $stmt->execute();
+        return $stmt->fetchAll(PDO::FETCH_ASSOC);
+    }
+
+    public function getPembelianByUserId($userId) {
+        $stmt = $this->database->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id WHERE user_id = ? ORDER BY pembelian_created_time DESC");
+        $stmt->execute([$userId]);
+        return $stmt->fetchAll(PDO::FETCH_ASSOC);
+    }
+}
diff --git a/app/Models/Subscription.php b/src/Server/Models/Subscription.php
similarity index 100%
rename from app/Models/Subscription.php
rename to src/Server/Models/Subscription.php
diff --git a/app/Models/Ticket.php b/src/Server/Models/Ticket.php
similarity index 66%
rename from app/Models/Ticket.php
rename to src/Server/Models/Ticket.php
index 4060c6ede2da98c4e084c8bef084f05fe8651aa4..388049a1f4b367092fa931cac237df96dcba19e0 100644
--- a/app/Models/Ticket.php
+++ b/src/Server/Models/Ticket.php
@@ -1,59 +1,47 @@
 <?php
-// app/models/Ticket.php
 
-require_once(__DIR__ . '/../../db/connect.php');
+namespace Server\Models;
 
+use PDO;
 
-class TicketModel {
+class TicketModel extends Model {
     public function createTicket($name, $eventId) {
-        global $db;
-
-        $stmt = $db->prepare("INSERT INTO tickets (ticket_name, event_id) VALUES (?, ?)");
+        $stmt = $this->database->prepare("INSERT INTO tickets (ticket_name, event_id) VALUES (?, ?)");
         $stmt->execute([$name, $eventId]);
 
         return "Ticket created successfully";
     }
 
     public function getTicket($ticketId) {
-        global $db;
-
-        $stmt = $db->prepare("SELECT * FROM tickets WHERE ticket_id = ?");
+        $stmt = $this->database->prepare("SELECT * FROM tickets WHERE ticket_id = ?");
         $stmt->execute([$ticketId]);
 
         return $stmt->fetch(PDO::FETCH_ASSOC);
     }
 
     public function updateTicket($ticketId, $name, $eventId) {
-        global $db;
-
-        $stmt = $db->prepare("UPDATE tickets SET ticket_name = ?, event_id = ? WHERE ticket_id = ?");
+        $stmt = $this->database->prepare("UPDATE tickets SET ticket_name = ?, event_id = ? WHERE ticket_id = ?");
         $stmt->execute([$name, $eventId, $ticketId]);
 
         return "Ticket updated successfully";
     }
 
     public function updateTicketByEventId($eventId, $name) {
-        global $db;
-
-        $stmt = $db->prepare("UPDATE tickets SET ticket_name = ? WHERE event_id = ?");
+        $stmt = $this->database->prepare("UPDATE tickets SET ticket_name = ? WHERE event_id = ?");
         $stmt->execute([$name, $eventId]);
 
         return "Ticket updated successfully";
     }
 
     public function deleteTicket($ticketId) {
-        global $db;
-
-        $stmt = $db->prepare("DELETE FROM tickets WHERE ticket_id = ?");
+        $stmt = $this->database->prepare("DELETE FROM tickets WHERE ticket_id = ?");
         $stmt->execute([$ticketId]);
 
         return "Ticket deleted successfully";
     }
 
     public function getSmallestAvailableTicket($eventId) {
-        global $db;
-
-        $stmt = $db->prepare("
+        $stmt = $this->database->prepare("
             SELECT t.*, e.*
             FROM tickets t
             JOIN events e ON t.event_id = e.event_id
@@ -73,4 +61,3 @@ class TicketModel {
         return $stmt->fetch(PDO::FETCH_ASSOC);
     }
 }
-?>
diff --git a/app/Models/User.php b/src/Server/Models/User.php
similarity index 69%
rename from app/Models/User.php
rename to src/Server/Models/User.php
index cb3410b23a9c471bcbdda9d7cdec126657941759..818b24b9f3bd2248e51ebeac3aeb12b429a078d6 100644
--- a/app/Models/User.php
+++ b/src/Server/Models/User.php
@@ -1,20 +1,21 @@
 <?php
-// app/models/User.php
 
-require_once(__DIR__ . '/../../db/connect.php');
+namespace Server\Models;
 
+use PDO;
+
+include (__DIR__."/Model.php");
 
-class UserModel {
-    public function createUser($name, $username, $email, $hashedPass, $isAdmin) {
-        global $db;
 
+class UserModel extends Model {
+    public function createUser($name, $username, $email, $hashedPass, $isAdmin) {
         $response = [
             'success'=> true,
             'message'=> ''
         ];
     
         try {
-            $stmt = $db->prepare("INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) VALUES (?, ?, ?, ?, ?)");
+            $stmt = $this->database->prepare("INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) VALUES (?, ?, ?, ?, ?)");
             $stmt->execute([$name, $username, $email, $hashedPass, $isAdmin]);
             $response['message'] = "User created successfully";
             return $response;
@@ -36,9 +37,7 @@ class UserModel {
 
     // User.php
     public function getUser($userId) {
-        global $db;
-
-        $stmt = $db->prepare("SELECT * FROM users WHERE user_ID = ?");
+        $stmt = $this->database->prepare("SELECT * FROM users WHERE user_ID = ?");
         $stmt->execute([$userId]);
 
         if ($stmt) {
@@ -56,54 +55,41 @@ class UserModel {
     }
 
     public function getUserByEmail($email) {
-        global $db;
-
-        $stmt = $db->prepare("SELECT * FROM users WHERE user_email = ?");
+        $stmt = $this->database->prepare("SELECT * FROM users WHERE user_email = ?");
         $stmt->execute([$email]);
 
         return $stmt->fetch(PDO::FETCH_ASSOC);
     }
 
     public function getUserByUsername($username){
-        global $db;
-
-        $stmt = $db->prepare("SELECT * FROM users WHERE username = ?");
+        $stmt = $this->database->prepare("SELECT * FROM users WHERE username = ?");
         $stmt->execute([$username]);
 
         return $stmt->fetch(PDO::FETCH_ASSOC);
     }
 
     public function updateUser($userId, $name, $username, $email, $hashedPass, $isAdmin) {
-        global $db;
-
-        $stmt = $db->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ?, user_hashedPass = ?, isAdmin = ? WHERE user_ID = ?");
+        $stmt = $this->database->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ?, user_hashedPass = ?, isAdmin = ? WHERE user_ID = ?");
         $stmt->execute([$name, $username, $email, $hashedPass, $isAdmin, $userId]);
 
         return "User updated successfully";
     }
 
     public function editProfile($userId, $name, $username, $email) {
-        global $db;
-
-        $stmt = $db->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ? WHERE user_id = ?");
+        $stmt = $this->database->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ? WHERE user_id = ?");
         return $stmt->execute([$name, $username, $email, $userId]);
     }
 
     public function deleteUser($userId) {
-        global $db;
-
-        $stmt = $db->prepare("DELETE FROM users WHERE user_ID = ?");
+        $stmt = $this->database->prepare("DELETE FROM users WHERE user_ID = ?");
         $stmt->execute([$userId]);
 
         return "User deleted successfully";
     }
 
     public function getAllUsers() {
-        global $db;
-
-        $stmt = $db->query("SELECT * FROM users");
+        $stmt = $this->database->query("SELECT * FROM users");
         return $stmt->fetchAll(PDO::FETCH_ASSOC);
     }
-
 }
 ?>
diff --git a/src/Server/Router/Router.php b/src/Server/Router/Router.php
new file mode 100644
index 0000000000000000000000000000000000000000..7849f64bc71a714ec681b609040178f0203db7c3
--- /dev/null
+++ b/src/Server/Router/Router.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Server\Router;
+
+class Router {
+    private array $handlers;
+    private const METHOD_GET = 'GET';
+    private const METHOD_POST = 'POST';
+
+    public function get(string $path, $handler): void
+    {
+        $this->addHandler(self::METHOD_GET, $path, $handler);
+    }
+
+    public function post(string $path, $handler): void
+    {
+        $this->addHandler(self::METHOD_POST, $path, $handler);
+    }
+
+    private function addHandler(string $method, string $path, $handler): void
+    {
+        $this->handlers[$method.$path] = [
+            'path' => $path,
+            'method' => $method,
+            'handler' => $handler,
+        ];
+    }
+
+    public function run()
+    {
+        $requstUri = parse_url($_SERVER['REQUEST_URI']);
+        $requestPath = $requstUri['path'];
+        $method = $_SERVER['REQUEST_METHOD'];
+
+        $callback = null;
+        foreach ($this->handlers as $handler) {
+            if($handler['path'] === $requestPath && $method === $handler['method']) {
+                $callback = $handler['handler'];
+            }
+        }
+
+        if (is_string($callback)) {
+            $parts = explode('@', $callback);
+            if (is_array($parts)) {
+                $className = array_shift($parts);
+                $method = array_shift($parts);
+        
+                // Check if the class exists before creating an instance
+                if (class_exists($className)) {
+                    $handler = new $className;
+        
+                    // Check if the method exists before setting the callback
+                    if (method_exists($handler, $method)) {
+                        $callback = [$handler, $method];
+                    }
+                }
+            }
+        }        
+    
+        if(!$callback) {
+            include 'Client/pages/Errors/NotFound.php';
+            return;
+        }
+
+        call_user_func_array($callback, [
+            array_merge($_GET, $_POST)
+        ]);
+    }
+}
\ No newline at end of file
diff --git a/src/Server/web.php b/src/Server/web.php
new file mode 100644
index 0000000000000000000000000000000000000000..d3dbe64a0333eb86605abd2ca487bc32fc95b9e7
--- /dev/null
+++ b/src/Server/web.php
@@ -0,0 +1,55 @@
+<?php
+
+declare(strict_types=1);
+
+include (__DIR__."/Router/Router.php");
+include (__DIR__."/Controllers/UserController.php");
+include (__DIR__."/Controllers/EventController.php");
+include (__DIR__."/Controllers/HomeController.php");
+
+$router = new \Server\Router\Router();
+
+function checkLoggedIn(): bool {
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
+    return isset($_SESSION['user_id']);
+}
+
+$router->get('/', function() {
+    header('Location: /home');
+    exit();
+});
+
+// Routes for HomeController
+$router->get('/home', [new \Server\Controllers\HomeController(),'home']);
+
+// Routes for UserController
+$router->get('/register', [new \Server\Controllers\UserController(), 'registerview']);
+$router->post('/register', [new \Server\Controllers\UserController(), 'register']);
+$router->post('/register/search-email', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'findEmail']]);
+$router->post('/register/search-username', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'findByUsername']]);
+$router->get('/login', [new \Server\Controllers\UserController(), 'loginview']);
+$router->post('/login', [new \Server\Controllers\UserController(), 'login']);
+$router->post('/logout', function() {
+    // No need to checkLoggedIn() here, as users can access this even if not logged in
+    if (session_status() == PHP_SESSION_NONE) {
+        // If a session is not already started, start a new one
+        session_start();
+    }
+    session_destroy();
+    header('Location: /login');
+    exit();
+});
+$router->post('/profile', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'viewProfile']]);
+$router->post('/profile/edit', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'editProfile']]);
+
+// Routes for EventsController
+// $router->get('/events', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'eventList10view']]);
+// $router->post('/events/create', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'createEvent']]);
+// $router->post('/events/update', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'updateEvent']]);
+// $router->post('/events/delete', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'deleteEvent']]);
+// $router->get('/events/search', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'searchview']]);
+
+$router->run();
diff --git a/src/index.php b/src/index.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6f970c24bd5e2e3475cc2b39d935ed8bb2f456e
--- /dev/null
+++ b/src/index.php
@@ -0,0 +1,11 @@
+<?php
+declare(strict_types=1);
+
+if (session_status() == PHP_SESSION_NONE) {
+    // If a session is not already started, start a new one
+    session_start();
+}
+
+include 'Server/web.php';
+
+?>