diff --git a/src/public/assets/images/564387.jpg b/src/public/assets/images/564387.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/public/assets/images/6511b6a6483bc-564387.jpg b/src/public/assets/images/6511b6a6483bc-564387.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/public/css/catalog.css b/src/public/css/catalog.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/server/app/Controller/CatalogController.php b/src/server/app/Controller/CatalogController.php
new file mode 100644
index 0000000000000000000000000000000000000000..1108ae99fb66d58db72a8f38fd3b45a552e77ba9
--- /dev/null
+++ b/src/server/app/Controller/CatalogController.php
@@ -0,0 +1,70 @@
+<?php
+
+require_once __DIR__ . '/../App/Controller.php';
+require_once __DIR__ . '/../App/View.php';
+require_once __DIR__ . '/../Service/CatalogService.php';
+require_once __DIR__ . '/../Repository/CatalogRepository.php';
+require_once __DIR__ . '/../Config/Database.php';
+require_once __DIR__ . '/../Model/CatalogCreateRequest.php';
+require_once __DIR__ . '/../Exception/ValidationException.php';
+
+
+class CatalogController
+{
+    private CatalogService $catalogService;
+
+    public function __construct()
+    {
+        $connection = Database::getConnection();
+        $catalogRepository = new CatalogRepository($connection);
+        $this->catalogService = new CatalogService($catalogRepository);
+    }
+
+    public function index(): void
+    {
+        View::render('catalog/index', [
+            'title' => 'Drawl | Catalog',
+            'styles' => [
+                './css/catalog.css',
+            ],
+        ]);
+    }
+
+    public function create(): void
+    {
+        View::render('catalog/create', [
+            'title' => 'Drawl | Add Catalog',
+            'styles' => [
+                './css/catalog.css',
+            ],
+        ]);
+    }
+
+    public function postCreate(): void
+    {
+        $request = new CatalogCreateRequest();
+        $request->category = $_POST['category'];
+        $request->title = $_POST['title'];
+        $request->description = $_POST['description'];
+
+        $request->poster = $_FILES['poster'];
+
+        if (isset($_FILES["trailer"]) && $_FILES["trailer"]["error"] === UPLOAD_ERR_OK) {
+            $request->trailer = $_FILES["trailer"];
+        }
+
+        try {
+            $this->catalogService->create($request);
+            View::redirect('/catalog');
+        } catch (ValidationException $exception) {
+            echo $exception->getMessage();
+            View::render('catalog/create', [
+                'title' => 'Drawl | Add Catalog',
+                'error' => $exception->getMessage(),
+                'styles' => [
+                    './css/catalog.css',
+                ],
+            ]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/server/app/Model/CatalogCreateRequest.php b/src/server/app/Model/CatalogCreateRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7cf79313380cf181654b8e004bc6a4bdb77fe658
--- /dev/null
+++ b/src/server/app/Model/CatalogCreateRequest.php
@@ -0,0 +1,10 @@
+<?php
+
+class CatalogCreateRequest
+{
+    public ?string $title = null;
+    public ?string $description = null;
+    public $poster = null;
+    public ?string $trailer = null;
+    public ?string $category = null;
+}
\ No newline at end of file
diff --git a/src/server/app/Model/CatalogCreateResponse.php b/src/server/app/Model/CatalogCreateResponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..1752af5a9e52b5eb30ec5ecb0bc6583496deda25
--- /dev/null
+++ b/src/server/app/Model/CatalogCreateResponse.php
@@ -0,0 +1,8 @@
+<?php
+
+require_once __DIR__ . '/../Domain/Catalog.php';
+
+class CatalogCreateResponse
+{
+    public Catalog $catalog;
+}
\ No newline at end of file
diff --git a/src/server/app/Service/CatalogService.php b/src/server/app/Service/CatalogService.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdffd694a8c60224860e470c1069d8d5ad8f66cf
--- /dev/null
+++ b/src/server/app/Service/CatalogService.php
@@ -0,0 +1,82 @@
+<?php
+
+require_once __DIR__ . '/../Model/CatalogCreateRequest.php';
+require_once __DIR__ . '/../Model/CatalogCreateResponse.php';
+require_once __DIR__ . '/../Repository/CatalogRepository.php';
+require_once __DIR__ . '/../Config/Database.php';
+
+class CatalogService
+{
+    private CatalogRepository $catalogRepository;
+
+    public function __construct(CatalogRepository $catalogRepository)
+    {
+        $this->catalogRepository = $catalogRepository;
+    }
+
+    public function create(CatalogCreateRequest $request): CatalogCreateResponse
+    {
+        $this->validateCatalogCreateRequest($request);
+
+        try {
+            Database::beginTransaction();
+
+            $catalog = new Catalog();
+
+            echo $request->poster['name'];
+
+            $filename = $this->uploadFile($request->poster);
+
+            $catalog->title = $request->title;
+            $catalog->description = $request->description;
+            $catalog->poster = $filename;
+            $catalog->trailer = $request->trailer ? $request->trailer['name'] : null;
+            $catalog->category = $request->category;
+
+            $this->catalogRepository->save($catalog);
+
+            $response = new CatalogCreateResponse();
+            $response->catalog = $catalog;
+
+            Database::commitTransaction();
+            return $response;
+        } catch (\Exception $exception) {
+            Database::rollbackTransaction();
+            throw $exception;
+        }
+    }
+
+    private function uploadFile($file): string
+    {
+        $filename = basename($file['name']);
+        $target_dir = "assets/images/";
+        $target_file = $target_dir . $filename;
+
+        // SANITIZE FILE
+        if (file_exists($target_file)) {
+            echo "Sorry, file already exists.";
+            $filename = uniqid() . '-' . $filename;
+            $target_file = $target_dir . $filename;
+        }
+
+        if (move_uploaded_file($file["tmp_name"], $target_file)) {
+            echo "The file " . htmlspecialchars($filename) . " has been uploaded.";
+        } else {
+            echo "Sorry, there was an error uploading your file.";
+        }
+
+        return $filename;
+    }
+
+    private function validateCatalogCreateRequest(CatalogCreateRequest $request)
+    {
+        if (
+            $request->title == null || trim($request->title) == ""
+        ) {
+            throw new ValidationException("Title, description cannot be blank");
+        }
+
+        // more validations goes here
+    }
+
+}
\ No newline at end of file
diff --git a/src/server/app/View/catalog/create.php b/src/server/app/View/catalog/create.php
new file mode 100644
index 0000000000000000000000000000000000000000..847891ca22009e29de2d22d1cb07a40a6d639e0a
--- /dev/null
+++ b/src/server/app/View/catalog/create.php
@@ -0,0 +1,20 @@
+<h2>Add Catalog</h2>
+<form action="/catalog/create" method="POST" enctype="multipart/form-data">
+    <label>Category</label><br>
+    <input type="radio" name="category" value="ANIME" required checked> Anime
+    <input type="radio" name="category" value="DRAMA" required> Drama<br><br>
+
+    <label>Title</label><br>
+    <input type="text" name="title" maxlength="40" required><br><br>
+
+    <label>Description</label><br>
+    <textarea name="description" maxlength="255"></textarea><br><br>
+
+    <label>Poster (Max 200MB)</label><br>
+    <input type="file" name="poster" accept="image/*" required><br><br>
+
+    <label>Video (Max 30 seconds)</label><br>
+    <input type="file" name="video" accept="video/*"><br><br>
+
+    <input type="submit" value="Submit">
+</form>
\ No newline at end of file
diff --git a/src/server/app/View/catalog/index.php b/src/server/app/View/catalog/index.php
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/server/routes/view.php b/src/server/routes/view.php
index 5fe11fe81a63f88d01b92110939fd7a5374fc857..e095182220a27c115fb21919fc1fc54d62f826f5 100644
--- a/src/server/routes/view.php
+++ b/src/server/routes/view.php
@@ -2,6 +2,8 @@
 require_once __DIR__ . "/../app/App/Router.php";
 require_once __DIR__ . "/../app/Controller/HomeController.php";
 require_once __DIR__ . "/../app/Controller/UserController.php";
+require_once __DIR__ . "/../app/Controller/CatalogController.php";
+
 
 // Register routes
 // Home controllers
@@ -11,5 +13,10 @@ Router::add('GET', '/', HomeController::class, 'index', []);
 Router::add('GET', '/signup', UserController::class, 'signUp', []);
 Router::add('POST', '/signup', UserController::class, 'postSignUp', []);
 
+// Catalog controllers
+Router::add('GET', '/catalog', CatalogController::class, 'index', []);
+Router::add('GET', '/catalog/create', CatalogController::class, 'create', []);
+Router::add('POST', '/catalog/create', CatalogController::class, 'postCreate', []);
+
 // Execute
-Router::run();
+Router::run();
\ No newline at end of file