tenancy/hyn-nova
Integrates Hyn multi-tenancy with Laravel Nova so each tenant gets its own isolated admin panel. Provides tenant-aware resources, middleware, and configuration, letting you manage tenants and their data safely without route or data conflicts across the application.
tenancy/hyn-nova is glue, not a standalone product — it assumes you already have a working hyn/multi-tenant install and Laravel Nova on the central (non-tenant) domain. Treat it as a thin layer that makes Nova aware of the current Website/Tenant from Hyn\Tenancy\Environment.
Minimal setup:
composer require tenancy/hyn-nova
php artisan vendor:publish --provider="Tenancy\HynNova\Providers\NovaServiceProvider" --tag=config
php artisan migrate # central DB only
Then look first at:
vendor/tenancy/hyn-nova/src/ — the list of Nova resources/tools the package registers. This is the whole surface area; the package is small.config/hyn-nova.php (if published) — resource class names, middleware, and route bindings.app/Providers/NovaServiceProvider.php — anything the package doesn't auto-register you add here.The first practical use case is almost always administration of tenants from Nova: list Website/Hostname/Tenant records, create a tenant, attach a hostname, and switch into a tenant to inspect its data. If that's all you need, the package is a reasonable shortcut over hand-rolling a TenantResource.
Be aware the repo has ~12 stars and low activity. Validate against your exact hyn/multi-tenant and Nova major versions before committing; pin both in composer.json.
Registering the package's resources. If the provider doesn't auto-discover, expose the resources explicitly:
// app/Providers/NovaServiceProvider.php
public function resources(array $resources)
{
return array_merge($resources, [
\Tenancy\HynNova\Resources\Tenant::class,
\Tenancy\HynNova\Resources\Website::class,
\Tenancy\HynNova\Resources\Hostname::class,
]);
}
Treat central vs tenant resources distinctly. The package can only sensibly manage central models (Website, Hostname, Tenant). Anything that lives in a tenant database needs explicit scoping. The safe pattern is a base resource that resolves Environment on each request:
abstract class TenantResource extends Resource
{
public static function indexQuery(NovaRequest $request, $query)
{
$env = app(\Hyn\Tenancy\Environment::class);
if ($tenant = $env->tenant()) {
$query->on($tenant->database()->connection());
}
return $query;
}
}
Do this per resource rather than relying on the package — connection switching in Nova will not happen automatically for your models.
Tenant switching via an action or tool. The most useful daily pattern is a "View as tenant" action on Website:
public function handle(ActionFields $fields, Collection $models)
{
$env = app(\Hyn\Tenancy\Environment::class);
$env->tenant($models->first()->tenant);
return Action::redirect('/nova/resources/orders'); // tenant-scoped resource
}
Persist this in the session so subsequent Nova requests stay in tenant context; don't rely on hostname identification for the Nova paths.
Provisioning through Nova actions. Wire tenant creation to the hyn/multi-tenant commands/services rather than raw Eloquent inserts. A CreateTenant action that runs tenancy:tenant:create + database migration in one job is far more reliable than saving Tenant and Website models from a form.
Policies per tenant. If you let multiple admins in, attach policies to the package resources and check $user->tenant_id against the resolved tenant. Nova's global search and lens queries can otherwise leak cross-tenant rows.
hyn/multi-tenant's EagerIdentification/HostnameIdentification middleware must not run on the central Nova domain, or Nova will resolve an empty/incorrect tenant. Keep Nova on a hostname that is not registered as a Hostname record.Environment::tenant() swaps the default DB connection. Anything cached (Nova's resource cache, config cache, route cache) or held in a singleton that touched the DB before the switch will point at the wrong database. Avoid DB access in Nova service providers' boot.Environment inside handle(). The package does not do this for you.nova-api and asset URLs are generated from APP_URL. Under a tenant hostname they'll still resolve to central — that's usually what you want, but don't mix tenant-scoped resources onto the tenant domain.--tenants/--force via hyn's migration support. Running plain php artisan migrate will only hit the central DB.php artisan tenancy:debug (or dumping app(Environment::class)->tenant()) inside a Nova request is the fastest way to see which connection is actually active.hyn/multi-tenant to a tested set, and cover the tenant-switch flow with a feature test (assertDatabaseHas against the tenant connection) before upgrading.How can I help you explore Laravel packages today?