diff --git a/composer.json b/composer.json
index 3f20219e..c3fc37e9 100644
--- a/composer.json
+++ b/composer.json
@@ -46,7 +46,8 @@
         "phpstan/phpstan-deprecation-rules": "^1.1",
         "phpunit/phpunit": "^11.4",
         "fakerphp/faker": "^1.23",
-        "laravel/framework": "^10.0 || ^11.0"
+        "laravel/framework": "^10.0 || ^11.0",
+        "orchestra/testbench": "^9.5"
     },
     "conflict": {
         "laravel/lumen": "*"
@@ -61,7 +62,10 @@
     },
     "autoload-dev": {
         "psr-4": {
-            "LaravelDoctrineTest\\ORM\\": "tests/"
+            "LaravelDoctrineTest\\ORM\\": "tests/",
+            "Workbench\\App\\": "workbench/app/",
+            "Workbench\\Database\\Factories\\": "workbench/database/factories/",
+            "Workbench\\Database\\Seeders\\": "workbench/database/seeders/"
         }
     },
     "suggest": {
@@ -95,6 +99,21 @@
             "vendor/bin/phpunit",
             "vendor/bin/phpstan analyze src --level 1"
         ],
-        "coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage"
+        "coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage",
+        "post-autoload-dump": [
+            "@clear",
+            "@prepare"
+        ],
+        "clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
+        "prepare": "@php vendor/bin/testbench package:discover --ansi",
+        "build": "@php vendor/bin/testbench workbench:build --ansi",
+        "serve": [
+            "Composer\\Config::disableProcessTimeout",
+            "@build",
+            "@php vendor/bin/testbench serve --ansi"
+        ],
+        "lint": [
+            "@php vendor/bin/phpstan analyse --verbose --ansi"
+        ]
     }
-}
+}
\ No newline at end of file
diff --git a/src/DoctrineServiceProvider.php b/src/DoctrineServiceProvider.php
index 69dfbcad..d6ef931b 100644
--- a/src/DoctrineServiceProvider.php
+++ b/src/DoctrineServiceProvider.php
@@ -10,10 +10,8 @@
 use Doctrine\ORM\Proxy\Autoloader;
 use Doctrine\Persistence\ManagerRegistry;
 use Illuminate\Contracts\Container\Container;
-use Illuminate\Contracts\Validation\Factory as ValidationFactory;
 use Illuminate\Notifications\ChannelManager;
 use Illuminate\Support\ServiceProvider;
-use Illuminate\Support\Str;
 use InvalidArgumentException;
 use LaravelDoctrine\ORM\Auth\DoctrineUserProvider;
 use LaravelDoctrine\ORM\Configuration\Cache\CacheManager;
@@ -38,7 +36,6 @@
 use function assert;
 use function class_exists;
 use function config_path;
-use function property_exists;
 
 class DoctrineServiceProvider extends ServiceProvider
 {
@@ -50,13 +47,9 @@ public function boot(): void
         $this->extendAuthManager();
         $this->extendNotificationChannel();
 
-        if (! $this->isLumen()) {
-            $this->publishes([
-                $this->getConfigPath() => config_path('doctrine.php'),
-            ], 'config');
-        }
-
-        $this->ensureValidatorIsUsable();
+        $this->publishes([
+            $this->getConfigPath() => config_path('doctrine.php'),
+        ], 'config');
     }
 
     /**
@@ -83,28 +76,6 @@ public function register(): void
         $this->registerPresenceVerifierProvider();
     }
 
-    protected function ensureValidatorIsUsable(): void
-    {
-        if (! $this->isLumen()) {
-            return;
-        }
-
-        assert(property_exists($this->app, 'availableBindings'));
-
-        if ($this->shouldRegisterDoctrinePresenceValidator()) {
-            // due to weirdness the default presence verifier overrides one set by a service provider
-            // so remove them so we can re add our implementation later
-            unset($this->app->availableBindings['validator']);
-            unset($this->app->availableBindings[ValidationFactory::class]);
-        } else {
-            // resolve the db,
-            // this makes `isset($this->app['db']) == true`
-            // which is required to set the presence verifier
-            // in the default ValidationServiceProvider implementation
-            $this->app['db'];
-        }
-    }
-
     /**
      * Merge config
      */
@@ -114,14 +85,6 @@ protected function mergeConfig(): void
             $this->getConfigPath(),
             'doctrine',
         );
-
-        if (! $this->isLumen()) {
-            return;
-        }
-
-        $this->app->configure('cache');
-        $this->app->configure('database');
-        $this->app->configure('doctrine');
     }
 
     /**
@@ -232,15 +195,7 @@ protected function registerExtensions(): void
      */
     protected function registerPresenceVerifierProvider(): void
     {
-        if ($this->isLumen()) {
-            $this->app->singleton('validator', function () {
-                $this->app->register(PresenceVerifierProvider::class);
-
-                return $this->app->make('validator');
-            });
-        } else {
-            $this->app->register(PresenceVerifierProvider::class);
-        }
+        $this->app->register(PresenceVerifierProvider::class);
     }
 
     /**
@@ -279,7 +234,7 @@ protected function extendAuthManager(): void
 
     /**
      * Boots the extension manager at the appropriate time depending on if the app
-     * is running as Laravel HTTP, Lumen HTTP or in a console environment
+     * is running as Laravel HTTP or in a console environment
      */
     protected function bootExtensionManager(): void
     {
@@ -354,11 +309,6 @@ protected function registerConsoleCommands(): void
         ]);
     }
 
-    protected function isLumen(): bool
-    {
-        return Str::contains($this->app->version(), 'Lumen');
-    }
-
     protected function shouldRegisterDoctrinePresenceValidator(): bool
     {
         return $this->app['config']->get('doctrine.doctrine_presence_verifier', true);
diff --git a/src/Testing/Concerns/InteractsWithEntities.php b/src/Testing/Concerns/InteractsWithEntities.php
deleted file mode 100644
index ae980130..00000000
--- a/src/Testing/Concerns/InteractsWithEntities.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace LaravelDoctrine\ORM\Testing\Concerns;
-
-use PHPUnit\Framework\Assert;
-
-use function collect;
-use function count;
-use function is_object;
-use function print_r;
-
-use const PHP_EOL;
-
-trait InteractsWithEntities
-{
-    /** @return object */
-    public function entityExists(string $class, mixed $id): mixed
-    {
-        $entity = $this->entityManager()->find($class, $id);
-
-        Assert::assertNotNull($entity, 'A [' . $class . '] entity was not found by id: ' . print_r($id, true));
-
-        return $entity;
-    }
-
-    public function entityDoesNotExist(string $class, mixed $id): void
-    {
-        Assert::assertNull(
-            $this->entityManager()->find($class, $id),
-            'A [' . $class . '] entity was found by id: ' . print_r($id, true),
-        );
-    }
-
-    /**
-     * @param mixed[] $criteria
-     *
-     * @return mixed[]
-     */
-    public function entitiesMatch(string $class, array $criteria, int|null $count = null): mixed
-    {
-        $entities = $this->entityManager()->getRepository($class)->findBy($criteria);
-
-        Assert::assertNotEmpty($entities, 'No [' . $class . '] entities were found with the given criteria: ' . $this->outputCriteria($criteria));
-
-        if ($count !== null) {
-            Assert::assertCount(
-                $count,
-                $entities,
-                'Expected to find ' . $count . ' [' . $class . '] entities, but found ' . count($entities) .
-                ' with the given criteria: ' . $this->outputCriteria($criteria),
-            );
-        }
-
-        return $entities;
-    }
-
-    /** @param mixed[] $criteria */
-    public function noEntitiesMatch(string $class, array $criteria): void
-    {
-        Assert::assertEmpty(
-            $this->entityManager()->getRepository($class)->findBy($criteria),
-            'Some [' . $class . '] entities were found with the given criteria: ' . $this->outputCriteria($criteria),
-        );
-    }
-
-    /**
-     * Replaces entities with their ids in the criteria array and print_r them
-     *
-     * @param mixed[] $criteria
-     */
-    private function outputCriteria(array $criteria): string
-    {
-        $criteria = collect($criteria)->map(function ($value) {
-            if (! is_object($value)) {
-                return $value;
-            }
-
-            $unityOfWork = $this->entityManager()->getUnitOfWork();
-            if ($unityOfWork->isInIdentityMap($value)) {
-                return $unityOfWork->getEntityIdentifier($value);
-            }
-
-            return $value;
-        })->all();
-
-        return print_r($criteria, true);
-    }
-
-    protected function entityManager(): mixed
-    {
-        if (! isset($this->app)) {
-            Assert::markTestSkipped(
-                'Tests that interact with entities through Doctrine need to have Laravel\'s Application object.' . PHP_EOL .
-                'Please extend Laravel\'s TestCase to use this trait.',
-            );
-        }
-
-        return $this->app->make('em');
-    }
-}
diff --git a/testbench.yaml b/testbench.yaml
new file mode 100644
index 00000000..d5e9cf31
--- /dev/null
+++ b/testbench.yaml
@@ -0,0 +1,20 @@
+providers:
+  - LaravelDoctrine\ORM\DoctrineServiceProvider
+
+workbench:
+  start: '/'
+  install: true
+  health: false
+  discovers:
+    web: fale
+    api: false
+    commands: false
+    components: false
+    views: false
+  build:
+    - asset-publish
+    - create-sqlite-db
+    - db-wipe
+  assets:
+    - laravel-assets
+  sync: []
diff --git a/tests/Feature/Configuration/Cache/CacheManagerTest.php b/tests/Feature/Configuration/Cache/CacheManagerTest.php
index 0cc64c33..7405dbbf 100644
--- a/tests/Feature/Configuration/Cache/CacheManagerTest.php
+++ b/tests/Feature/Configuration/Cache/CacheManagerTest.php
@@ -19,18 +19,18 @@ class CacheManagerTest extends TestCase
 {
     protected CacheManager $manager;
 
-    protected Container $app;
+    protected Container $testApp;
 
     protected Repository $config;
 
     protected function setUp(): void
     {
-        $this->app = m::mock(Container::class);
-        $this->app->shouldReceive('make')->andReturn(m::self());
-        $this->app->shouldReceive('get')->with('doctrine.cache.default', 'array')->andReturn('array');
+        $this->testApp = m::mock(Container::class);
+        $this->testApp->shouldReceive('make')->andReturn(m::self());
+        $this->testApp->shouldReceive('get')->with('doctrine.cache.default', 'array')->andReturn('array');
 
         $this->manager = new CacheManager(
-            $this->app,
+            $this->testApp,
         );
 
         parent::setUp();
@@ -38,7 +38,7 @@ protected function setUp(): void
 
     public function testDriverReturnsTheDefaultDriver(): void
     {
-        $this->app->shouldReceive('resolve')->andReturn(new ArrayCacheProvider());
+        $this->testApp->shouldReceive('resolve')->andReturn(new ArrayCacheProvider());
 
         $this->assertInstanceOf(ArrayCacheProvider::class, $this->manager->driver());
         $this->assertInstanceOf(ArrayAdapter::class, $this->manager->driver()->resolve());
@@ -49,7 +49,7 @@ public function testDriverCanReturnAGivenDriver(): void
         $config = m::mock(Repository::class);
         $app    = m::mock(Application::class);
 
-        $this->app->shouldReceive('resolve')->andReturn(new FileCacheProvider(
+        $this->testApp->shouldReceive('resolve')->andReturn(new FileCacheProvider(
             $config,
             $app,
         ));
diff --git a/tests/Feature/Configuration/Cache/FileCacheProviderTest.php b/tests/Feature/Configuration/Cache/FileCacheProviderTest.php
index 248a9706..de844bf1 100644
--- a/tests/Feature/Configuration/Cache/FileCacheProviderTest.php
+++ b/tests/Feature/Configuration/Cache/FileCacheProviderTest.php
@@ -15,7 +15,10 @@ public function getProvider(): mixed
     {
         $config = m::mock(Repository::class);
         $config->shouldReceive('get')
-            ->with('cache.stores.file.path', '/storage/framework/cache')
+            ->with(
+                'cache.stores.file.path',
+                $this->applicationBasePath() . '/storage/framework/cache',
+            )
             ->once()
             ->andReturn('/tmp');
 
diff --git a/tests/Feature/Configuration/Cache/PhpFileCacheProviderTest.php b/tests/Feature/Configuration/Cache/PhpFileCacheProviderTest.php
index ba0a0a65..bc305183 100644
--- a/tests/Feature/Configuration/Cache/PhpFileCacheProviderTest.php
+++ b/tests/Feature/Configuration/Cache/PhpFileCacheProviderTest.php
@@ -15,7 +15,10 @@ public function getProvider(): mixed
     {
         $config = m::mock(Repository::class);
         $config->shouldReceive('get')
-            ->with('cache.stores.file.path', '/storage/framework/cache')
+            ->with(
+                'cache.stores.file.path',
+                $this->applicationBasePath() . '/storage/framework/cache',
+            )
             ->once()
             ->andReturn('/tmp');
 
diff --git a/tests/Feature/Configuration/Connections/ConnectionManagerTest.php b/tests/Feature/Configuration/Connections/ConnectionManagerTest.php
index 896c7dd3..332ee3c4 100644
--- a/tests/Feature/Configuration/Connections/ConnectionManagerTest.php
+++ b/tests/Feature/Configuration/Connections/ConnectionManagerTest.php
@@ -19,20 +19,20 @@ class ConnectionManagerTest extends TestCase
 {
     protected ConnectionManager $manager;
 
-    protected Container $app;
+    protected Container $testApp;
 
     protected Repository $config;
 
     protected function setUp(): void
     {
-        $this->app = m::mock(Container::class);
-        $this->app->shouldReceive('make')->andReturn(m::self());
+        $this->testApp = m::mock(Container::class);
+        $this->testApp->shouldReceive('make')->andReturn(m::self());
 
         $this->config = m::mock(Repository::class);
         $this->config->shouldReceive('get');
 
         $this->manager = new ConnectionManager(
-            $this->app,
+            $this->testApp,
         );
 
         parent::setUp();
@@ -40,7 +40,7 @@ protected function setUp(): void
 
     public function testDriverReturnsTheDefaultDriver(): void
     {
-        $this->app->shouldReceive('resolve')->andReturn(
+        $this->testApp->shouldReceive('resolve')->andReturn(
             (new MysqlConnection($this->config))->resolve(),
         );
 
@@ -50,7 +50,7 @@ public function testDriverReturnsTheDefaultDriver(): void
 
     public function testDriverCanReturnAGivenDriver(): void
     {
-        $this->app->shouldReceive('resolve')->andReturn(
+        $this->testApp->shouldReceive('resolve')->andReturn(
             (new SqliteConnection($this->config))->resolve(),
         );
 
diff --git a/tests/Feature/Configuration/MetaData/MetaDataManagerTest.php b/tests/Feature/Configuration/MetaData/MetaDataManagerTest.php
index 11490e47..67fb2db0 100644
--- a/tests/Feature/Configuration/MetaData/MetaDataManagerTest.php
+++ b/tests/Feature/Configuration/MetaData/MetaDataManagerTest.php
@@ -15,15 +15,15 @@ class MetaDataManagerTest extends TestCase
 {
     protected MetaDataManager $manager;
 
-    protected Container $app;
+    protected Container $testApp;
 
     protected function setUp(): void
     {
-        $this->app = m::mock(Container::class);
-        $this->app->shouldReceive('make')->andReturn(m::self());
+        $this->testApp = m::mock(Container::class);
+        $this->testApp->shouldReceive('make')->andReturn(m::self());
 
         $this->manager = new MetaDataManager(
-            $this->app,
+            $this->testApp,
         );
 
         parent::setUp();
@@ -31,7 +31,7 @@ protected function setUp(): void
 
     public function testDriverReturnsTheDefaultDriver(): void
     {
-        $this->app->shouldReceive('resolve')->andReturn(new XmlDriver('locator', '.xml'));
+        $this->testApp->shouldReceive('resolve')->andReturn(new XmlDriver('locator', '.xml'));
 
         $this->assertInstanceOf(XmlDriver::class, $this->manager->driver());
     }
diff --git a/tests/Feature/Testing/Concerns/InteractsWithEntitiesTest.php b/tests/Feature/Testing/Concerns/InteractsWithEntitiesTest.php
deleted file mode 100644
index bb9371dd..00000000
--- a/tests/Feature/Testing/Concerns/InteractsWithEntitiesTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace LaravelDoctrineTest\ORM\Feature\Testing\Concerns;
-
-use Doctrine\ORM\EntityManagerInterface;
-use Doctrine\ORM\EntityRepository;
-use Illuminate\Contracts\Container\Container;
-use LaravelDoctrine\ORM\Testing\Concerns\InteractsWithEntities;
-use LaravelDoctrineTest\ORM\MockeryTestCase;
-use Mockery;
-use PHPUnit\Framework\ExpectationFailedException;
-
-class InteractsWithEntitiesTest extends MockeryTestCase
-{
-    use InteractsWithEntities;
-
-    protected EntityManagerInterface $em;
-    protected Container $app;
-
-    public function setUp(): void
-    {
-        $this->em = Mockery::mock(EntityManagerInterface::class);
-
-        $this->app = Mockery::mock(Container::class);
-        $this->app
-            ->allows('make')
-            ->with('em')
-            ->andReturn($this->em);
-
-        parent::setUp();
-    }
-
-    public function testEntitiesMatchWithMatch(): void
-    {
-        $repository = Mockery::mock(EntityRepository::class);
-        $repository->expects('findBy')
-            ->with(['someField' => 'someValue'])
-            ->once()
-            ->andReturn(['entity']);
-
-        $this->em->expects('getRepository')
-            ->with('SomeClass')
-            ->once()
-            ->andReturn($repository);
-
-        $this->entitiesMatch('SomeClass', ['someField' => 'someValue']);
-    }
-
-    public function testEntitiesMatchWithoutMatch(): void
-    {
-        $repository = Mockery::mock(EntityRepository::class);
-        $repository->expects('findBy')
-            ->with(['someField' => 'someValue'])
-            ->once()
-            ->andReturn([]);
-
-        $this->em->expects('getRepository')
-            ->with('SomeClass')
-            ->once()
-            ->andReturn($repository);
-
-        $this->expectException(ExpectationFailedException::class);
-        $this->entitiesMatch('SomeClass', ['someField' => 'someValue']);
-    }
-
-    public function testNoEntitiesMatchWithMatch(): void
-    {
-        $repository = Mockery::mock(EntityRepository::class);
-        $repository->expects('findBy')
-            ->with(['someField' => 'someValue'])
-            ->once()
-            ->andReturn(['entity']);
-
-        $this->em->expects('getRepository')
-            ->with('SomeClass')
-            ->once()
-            ->andReturn($repository);
-
-        $this->expectException(ExpectationFailedException::class);
-        $this->noEntitiesMatch('SomeClass', ['someField' => 'someValue']);
-    }
-
-    public function testNoEntitiesMatchWithoutMatch(): void
-    {
-        $repository = Mockery::mock(EntityRepository::class);
-        $repository->expects('findBy')
-            ->with(['someField' => 'someValue'])
-            ->once()
-            ->andReturn([]);
-
-        $this->em->expects('getRepository')
-            ->with('SomeClass')
-            ->once()
-            ->andReturn($repository);
-
-        $this->noEntitiesMatch('SomeClass', ['someField' => 'someValue']);
-    }
-}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 315aaa79..c20aabf4 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -4,29 +4,20 @@
 
 namespace LaravelDoctrineTest\ORM;
 
-use Illuminate\Foundation\Application;
-use PHPUnit\Framework\TestCase as PHPUnitTestCase;
+use Orchestra\Testbench\Concerns\WithWorkbench;
+use Orchestra\Testbench\TestCase as OrchestraTestCase;
 
-class TestCase extends PHPUnitTestCase
+class TestCase extends OrchestraTestCase
 {
-    private Application $application;
+    use WithWorkbench;
 
     protected function setUp(): void
     {
-        $this->application = new Application();
-
         parent::setUp();
     }
 
     protected function tearDown(): void
     {
-        unset($this->application);
-
         parent::tearDown();
     }
-
-    public function getApplication(): Application
-    {
-        return $this->application;
-    }
 }
diff --git a/workbench/app/Models/.gitkeep b/workbench/app/Models/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/workbench/app/Models/User.php b/workbench/app/Models/User.php
new file mode 100644
index 00000000..1405251f
--- /dev/null
+++ b/workbench/app/Models/User.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Workbench\App\Models;
+
+// use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Foundation\Auth\User as Authenticatable;
+use Illuminate\Notifications\Notifiable;
+use Laravel\Sanctum\HasApiTokens;
+
+class User extends Authenticatable
+{
+    use HasFactory, Notifiable;
+
+    /**
+     * The attributes that are mass assignable.
+     *
+     * @var array<int, string>
+     */
+    protected $fillable = [
+        'name',
+        'email',
+        'password',
+    ];
+
+    /**
+     * The attributes that should be hidden for serialization.
+     *
+     * @var array<int, string>
+     */
+    protected $hidden = [
+        'password',
+        'remember_token',
+    ];
+
+    /**
+     * The attributes that should be cast.
+     *
+     * @var array<string, string>
+     */
+    protected $casts = [
+        'email_verified_at' => 'datetime',
+        'password' => 'hashed',
+    ];
+}
diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php
new file mode 100644
index 00000000..e8cec9c2
--- /dev/null
+++ b/workbench/app/Providers/WorkbenchServiceProvider.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Workbench\App\Providers;
+
+use Illuminate\Support\ServiceProvider;
+
+class WorkbenchServiceProvider extends ServiceProvider
+{
+    /**
+     * Register services.
+     */
+    public function register(): void
+    {
+        //
+    }
+
+    /**
+     * Bootstrap services.
+     */
+    public function boot(): void
+    {
+        //
+    }
+}
diff --git a/workbench/bootstrap/app.php b/workbench/bootstrap/app.php
new file mode 100644
index 00000000..6ead72ab
--- /dev/null
+++ b/workbench/bootstrap/app.php
@@ -0,0 +1,19 @@
+<?php
+
+use Illuminate\Foundation\Application;
+use Illuminate\Foundation\Configuration\Exceptions;
+use Illuminate\Foundation\Configuration\Middleware;
+
+use function Orchestra\Testbench\default_skeleton_path;
+
+return Application::configure(basePath: $APP_BASE_PATH ?? default_skeleton_path())
+    ->withRouting(
+        web: __DIR__.'/../routes/web.php',
+        commands: __DIR__.'/../routes/console.php',
+    )
+    ->withMiddleware(function (Middleware $middleware) {
+        //
+    })
+    ->withExceptions(function (Exceptions $exceptions) {
+        //
+    })->create();
diff --git a/workbench/bootstrap/providers.php b/workbench/bootstrap/providers.php
new file mode 100644
index 00000000..3ac44ad1
--- /dev/null
+++ b/workbench/bootstrap/providers.php
@@ -0,0 +1,5 @@
+<?php
+
+return [
+    //
+];
diff --git a/workbench/database/factories/.gitkeep b/workbench/database/factories/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/workbench/database/factories/UserFactory.php b/workbench/database/factories/UserFactory.php
new file mode 100644
index 00000000..dfcab01b
--- /dev/null
+++ b/workbench/database/factories/UserFactory.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Workbench\Database\Factories;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Str;
+use Workbench\App\Models\User;
+
+/**
+ * @template TModel of \Workbench\App\Models\User
+ *
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<TModel>
+ */
+class UserFactory extends Factory
+{
+    /**
+     * The current password being used by the factory.
+     */
+    protected static ?string $password;
+
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var class-string<TModel>
+     */
+    protected $model = User::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array<string, mixed>
+     */
+    public function definition(): array
+    {
+        return [
+            'name' => fake()->name(),
+            'email' => fake()->unique()->safeEmail(),
+            'email_verified_at' => now(),
+            'password' => static::$password ??= Hash::make('password'),
+            'remember_token' => Str::random(10),
+        ];
+    }
+
+    /**
+     * Indicate that the model's email address should be unverified.
+     */
+    public function unverified(): static
+    {
+        return $this->state(fn (array $attributes) => [
+            'email_verified_at' => null,
+        ]);
+    }
+}
diff --git a/workbench/database/migrations/.gitkeep b/workbench/database/migrations/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/workbench/database/seeders/DatabaseSeeder.php b/workbench/database/seeders/DatabaseSeeder.php
new file mode 100644
index 00000000..ce9bd159
--- /dev/null
+++ b/workbench/database/seeders/DatabaseSeeder.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Workbench\Database\Seeders;
+
+use Illuminate\Database\Seeder;
+// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
+use Workbench\Database\Factories\UserFactory;
+
+class DatabaseSeeder extends Seeder
+{
+    /**
+     * Seed the application's database.
+     */
+    public function run(): void
+    {
+        // UserFactory::new(10)->create();
+
+        UserFactory::new()->create([
+            'name' => 'Test User',
+            'email' => 'test@example.com',
+        ]);
+    }
+}
diff --git a/workbench/resources/views/.gitkeep b/workbench/resources/views/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/workbench/routes/console.php b/workbench/routes/console.php
new file mode 100644
index 00000000..eff2ed24
--- /dev/null
+++ b/workbench/routes/console.php
@@ -0,0 +1,8 @@
+<?php
+
+use Illuminate\Foundation\Inspiring;
+use Illuminate\Support\Facades\Artisan;
+
+Artisan::command('inspire', function () {
+    $this->comment(Inspiring::quote());
+})->purpose('Display an inspiring quote')->hourly();
diff --git a/workbench/routes/web.php b/workbench/routes/web.php
new file mode 100644
index 00000000..86a06c53
--- /dev/null
+++ b/workbench/routes/web.php
@@ -0,0 +1,7 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+
+Route::get('/', function () {
+    return view('welcome');
+});