diff --git a/application/app/DataTransferObjects/ReviewData.php b/application/app/DataTransferObjects/ReviewData.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d3935584c335cd9dfd82eb2704361b275457ed7
--- /dev/null
+++ b/application/app/DataTransferObjects/ReviewData.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\DataTransferObjects;
+
+use Carbon\Carbon;
+use App\Enums\StatusEnum;
+use Spatie\LaravelData\Data;
+use Spatie\LaravelData\Attributes\Validation\In;
+use Spatie\TypeScriptTransformer\Attributes\TypeScript;
+use Spatie\TypeScriptTransformer\Attributes\Optional as TypeScriptOptional;
+
+#[TypeScript]
+class ReviewData extends Data
+{
+    public function __construct(
+        public ?int $id,
+
+        #[TypeScriptOptional]
+        public ?int $parent_id,
+
+        #[TypeScriptOptional]
+        public ?int $user_id,
+
+        public int $model_id,
+
+        public string $model_type,
+
+        #[TypeScriptOptional]
+        public ?string $title,
+
+        public string $content,
+
+        public ?string $status,
+
+        #[TypeScriptOptional]
+        public ?Carbon $published_at,
+
+        public string $type,
+
+        public int $ranking_total,
+
+        public int $helpful_total,
+
+        public int $not_helpful_total,
+    ) {}
+}
diff --git a/application/app/Enums/PermissionEnum.php b/application/app/Enums/PermissionEnum.php
index 86912ba5f4687b56079da1700ec1d989d8ddf17c..4e4660332edfd3e60fce0011dbcc5dca3f11ce0f 100644
--- a/application/app/Enums/PermissionEnum.php
+++ b/application/app/Enums/PermissionEnum.php
@@ -57,8 +57,5 @@
  */
 final class PermissionEnum extends Enum
 {
-    protected static function values(): \Closure
-    {
-        return fn(string $name): string|int => str_replace('_', ' ', mb_strtolower($name));
-    }
+    use Traits\HasValues;
 }
diff --git a/application/app/Enums/RoleEnum.php b/application/app/Enums/RoleEnum.php
index 7385757e57119920f64ada93da000dccce0c4453..8e47e7e982a020a875010bd80dda97faf006e130 100644
--- a/application/app/Enums/RoleEnum.php
+++ b/application/app/Enums/RoleEnum.php
@@ -15,8 +15,5 @@
  */
 final class RoleEnum extends Enum
 {
-    protected static function values(): \Closure
-    {
-        return fn(string $name): string|int => str_replace('_', ' ', mb_strtolower($name));
-    }
+    use Traits\HasValues;
 }
diff --git a/application/app/Enums/StatusEnum.php b/application/app/Enums/StatusEnum.php
new file mode 100644
index 0000000000000000000000000000000000000000..d6450e23abbccd58c99fb4f5024ff97ebad277e4
--- /dev/null
+++ b/application/app/Enums/StatusEnum.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Enums;
+
+use Spatie\Enum\Laravel\Enum;
+
+/**
+ * @method static self draft()
+ * @method static self pending()
+ * @method static self published()
+ */
+class StatusEnum extends Enum
+{
+    use Traits\HasValues;
+}
diff --git a/application/app/Enums/Traits/HasValues.php b/application/app/Enums/Traits/HasValues.php
new file mode 100644
index 0000000000000000000000000000000000000000..caf0dde1e8211b523be48b1f48eaada985dec87f
--- /dev/null
+++ b/application/app/Enums/Traits/HasValues.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Enums\Traits;
+
+trait HasValues
+{
+    public static function values(): \Closure
+    {
+        return fn(string $name): string|int => str_replace('_', ' ', mb_strtolower($name));
+    }
+}
diff --git a/application/app/Models/Review.php b/application/app/Models/Review.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a40320f7f2c42436fc329c36bac975d10e9e7bb
--- /dev/null
+++ b/application/app/Models/Review.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace App\Models;
+
+use App\Models\Model;
+
+
+class Review extends Model {}
diff --git a/application/app/Models/ReviewModeration.php b/application/app/Models/ReviewModeration.php
index 5243f8cbc11bf2664ee9e51694da473578d69b1b..9ac362e50e614f5629d7eb15a0f4420cba21d857 100644
--- a/application/app/Models/ReviewModeration.php
+++ b/application/app/Models/ReviewModeration.php
@@ -4,10 +4,6 @@
 
 namespace App\Models;
 
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Database\Eloquent\Model;
+use App\Models\Model;
 
-class ReviewModeration extends Model
-{
-    use HasFactory;
-}
+class ReviewModeration extends Model {}
diff --git a/application/app/Policies/ReviewModerationPolicy.php b/application/app/Policies/ReviewModerationPolicy.php
index bfbd34513950e054e24f2ef290867e8ac6d6a432..688a1b19c08f924649aca7839a074c059f9bc400 100644
--- a/application/app/Policies/ReviewModerationPolicy.php
+++ b/application/app/Policies/ReviewModerationPolicy.php
@@ -5,9 +5,7 @@
 namespace App\Policies;
 
 use App\Models\User;
-use App\Enums\RoleEnum;
 use App\Enums\PermissionEnum;
-use Illuminate\Auth\Access\Response;
 
 class ReviewModerationPolicy extends AppPolicy
 {
@@ -16,7 +14,7 @@ class ReviewModerationPolicy extends AppPolicy
      */
     public function viewAny(User $user): bool
     {
-        return parent::canViewAny($user) || $user->hasAnyPermission([PermissionEnum::read_users()->value]);
+        return parent::canViewAny($user);
     }
 
     /**
@@ -24,7 +22,7 @@ public function viewAny(User $user): bool
      */
     public function view(User $user, User $model): bool
     {
-        return parent::canView($user, $model) || $user->hasAnyPermission([PermissionEnum::read_users()->value]);
+        return parent::canView($user, $model);
     }
 
     /**
@@ -32,7 +30,7 @@ public function view(User $user, User $model): bool
      */
     public function create(User $user): bool
     {
-        return parent::canCreate($user) || $user->hasAnyPermission([PermissionEnum::create_users()->value]);
+        return parent::canCreate($user);
     }
 
     /**
@@ -40,7 +38,7 @@ public function create(User $user): bool
      */
     public function update(User $user, User $model): bool
     {
-        return parent::canUpdate($user, $model) || $user->hasAnyPermission([PermissionEnum::update_users()->value]);
+        return parent::canUpdate($user, $model);
     }
 
     /**
@@ -48,6 +46,6 @@ public function update(User $user, User $model): bool
      */
     public function delete(User $user, User $model): bool
     {
-        return parent::canDelete($user, $model) || $user->hasAnyPermission([PermissionEnum::delete_users()->value]);
+        return parent::canDelete($user, $model);
     }
 }
diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewPolicy.php
new file mode 100644
index 0000000000000000000000000000000000000000..f323cc421a4d2fb54c64fc353b19d1161a5e7929
--- /dev/null
+++ b/application/app/Policies/ReviewPolicy.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Policies;
+
+use App\Models\User;
+use App\Enums\PermissionEnum;
+
+class ReviewPolicy extends AppPolicy
+{
+    /**
+     * Determine whether the user can view any models.
+     */
+    public function viewAny(User $user): bool
+    {
+        return parent::canViewAny($user) || $user->hasAnyPermission([PermissionEnum::read_reviews()->value]);
+    }
+
+    /**
+     * Determine whether the user can view the model.
+     */
+    public function view(User $user, User $model): bool
+    {
+        return parent::canView($user, $model) || $user->hasAnyPermission([PermissionEnum::read_reviews()->value]);
+    }
+
+    /**
+     * Determine whether the user can create models.
+     */
+    public function create(User $user): bool
+    {
+        return parent::canCreate($user) || $user->hasAnyPermission([PermissionEnum::create_reviews()->value]);
+    }
+
+    /**
+     * Determine whether the user can update the model.
+     */
+    public function update(User $user, User $model): bool
+    {
+        return parent::canUpdate($user, $model) || $user->hasAnyPermission([PermissionEnum::update_reviews()->value]);
+    }
+
+    /**
+     * Determine whether the user can delete the model.
+     */
+    public function delete(User $user, User $model): bool
+    {
+        return parent::canDelete($user, $model) || $user->hasAnyPermission([PermissionEnum::delete_reviews()->value]);
+    }
+}
diff --git a/application/database/factories/ReviewFactory.php b/application/database/factories/ReviewFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ff978f545b0a31defbf595651e4ba4f6adf8e16
--- /dev/null
+++ b/application/database/factories/ReviewFactory.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Database\Factories;
+
+use App\Models\User;
+use App\Models\Review;
+use App\Models\Proposal;
+use App\Enums\StatusEnum;
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class ReviewFactory extends Factory
+{
+    protected $model = Review::class;
+
+    public function definition()
+    {
+        return [
+            'parent_id' => null, 
+            'user_id' => User::factory(), 
+            'model_id' => Proposal::factory(),
+            'model_type' => Proposal::class, 
+            'title' => $this->faker->sentence(),
+            'content' => $this->faker->paragraph(),
+            'status' => $this->faker->randomElement(StatusEnum::toArray()),
+            'published_at' => $this->faker->optional()->dateTime(),
+            'type' => 'App\Models\Comment',
+            'ranking_total' => $this->faker->numberBetween(0, 100),
+            'helpful_total' => $this->faker->numberBetween(0, 100),
+            'not_helpful_total' => $this->faker->numberBetween(0, 100),
+        ];
+    }
+
+    /**
+     * Indicate that the review is published.
+     *
+     * @return \Illuminate\Database\Eloquent\Factories\Factory
+     */
+    public function published()
+    {
+        return $this->state([
+            'status' => StatusEnum::approved()->value,
+            'published_at' => now(),
+        ]);
+    }
+}
diff --git a/application/database/factories/ReviewModerationFactory.php b/application/database/factories/ReviewModerationFactory.php
index 07e277ee23c424feebfceba98923222782b23609..169446416e01edecbd828e9ee135bc96d2f94fd8 100644
--- a/application/database/factories/ReviewModerationFactory.php
+++ b/application/database/factories/ReviewModerationFactory.php
@@ -1,5 +1,7 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Database\Factories;
 
 use Illuminate\Database\Eloquent\Factories\Factory;
diff --git a/application/database/migrations/2024_11_12_182901_create_reviews_table.php b/application/database/migrations/2024_11_12_182901_create_reviews_table.php
new file mode 100644
index 0000000000000000000000000000000000000000..4977a217de18ed5d1b2d42c3c4159f092d6bfd59
--- /dev/null
+++ b/application/database/migrations/2024_11_12_182901_create_reviews_table.php
@@ -0,0 +1,40 @@
+<?php
+
+use App\Enums\StatusEnum;
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('reviews', function (Blueprint $table) {
+            $table->id();
+            $table->timestamps();
+            $table->bigInteger('parent_id')->nullable();
+            $table->foreignId('user_id')->constrained('users')->nullable();
+            $table->bigInteger('model_id');
+            $table->string('model_type');
+            $table->string('title')->nullable();
+            $table->text('content');
+            $table->enum('status', StatusEnum::toArray())->default(StatusEnum::pending()->value)->nullable;
+            $table->timestamp('published_at')->nullable();
+            $table->char('type')->default('App\Models\Comment');
+            $table->integer('ranking_total')->default(0);
+            $table->integer('helpful_total')->default(0);
+            $table->integer('not_helpful_total')->default(0);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('reviews');
+    }
+};
diff --git a/application/database/seeders/ReviewSeeder.php b/application/database/seeders/ReviewSeeder.php
new file mode 100644
index 0000000000000000000000000000000000000000..1924adbd805a1163ace8ff5db6ced9a9f9744b17
--- /dev/null
+++ b/application/database/seeders/ReviewSeeder.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Database\Seeders;
+
+use App\Models\Review;
+use Illuminate\Database\Seeder;
+use Illuminate\Database\Console\Seeds\WithoutModelEvents;
+
+class ReviewSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     */
+    public function run(): void
+    {
+        Review::factory(10)->create();
+    }
+}
diff --git a/application/resources/types/generated.d.ts b/application/resources/types/generated.d.ts
index 975763350ba1f271e36338dcb46d6146d7f3b9a4..d4b4ef8692bab8514bc8b463b64568c8dbc7e346 100644
--- a/application/resources/types/generated.d.ts
+++ b/application/resources/types/generated.d.ts
@@ -1,4 +1,20 @@
 declare namespace App.DataTransferObjects {
+    export type GroupData = {
+        id: number | null;
+        user_id?: number;
+        name?: string;
+        bio?: Array<any>;
+        slug?: string;
+        status?: string;
+        meta_title?: string;
+        website?: string;
+        twitter?: string;
+        discord?: string;
+        github?: string;
+        created_at?: string;
+        updated_at?: string;
+        deleted_at?: string;
+    };
     export type IdeascaleProfileData = {
         id: number | null;
         ideascaleId?: number;
@@ -53,6 +69,21 @@ declare namespace App.DataTransferObjects {
         quickpitch?: string;
         quickpitch_length?: number;
     };
+    export type ReviewData = {
+        id: number | null;
+        parent_id?: number;
+        user_id?: number;
+        model_id: number;
+        model_type: string;
+        title?: string;
+        content: string;
+        status: string | null;
+        published_at?: string;
+        type: string;
+        ranking_total: number;
+        helpful_total: number;
+        not_helpful_total: number;
+    };
     export type ReviewModerationData = {
         id: number | null;
         reviewer_id?: number;