darvis/nuki
A Laravel package for integrating Nuki smart locks. Configure API credentials, query locks and doors, trigger lock and unlock actions, and handle Nuki webhooks through a clean, fluent PHP interface.
Install the package and publish its config, migrations, and (optionally) views:
composer require darvis/nuki
php artisan vendor:publish --tag="nuki-config"
php artisan vendor:publish --tag="nuki-migrations"
php artisan migrate
Set your Nuki API credentials and the UI toggle in .env, then open /nuki — the package ships its own routes, layout, dashboard, activity timeline, profile, and sub-user editor, all under the nuki route prefix. If you already have an application user model, decide up front whether you use package users (the package's own auth_users guard and login at /nuki/login) or your host application's users; the behaviour of nearly everything else depends on that choice.
First real use case: create a main user attached to an account and see the locks.
php artisan nuki:user-create --account=<account_key>
The command (new in 1.3.0) is repeatable and attaches the new main user as owner. Then point auth_users.redirect_after_login at wherever you want signed-in package users to land, and log in at /nuki/login. From the dashboard you get lock listing, battery/door state, and lock/unlock actions; the activity timeline gives you the webhook/log history per lock.
If you prefer to look at code first, read config/nuki.php, then the route file and NukiAccount (roles and permission rows), then the middleware — those three define the whole access model.
Choose your user source deliberately. With package users enabled, the package owns login, guards, and the account switcher. Without package users, everything stays visible to whoever your host app has already authenticated, and the 1.3.0 restrictions don't apply. Don't mix the two within one installation.
Attach main users to accounts explicitly. The account switcher only lists attached accounts. Since 1.3.0, creating an account on /nuki/accounts auto-attaches the creator as owner, but pre-existing accounts, seeded accounts, or accounts created programmatically are not touched. Use the documented pattern in seeders and imports:
$user->accounts()->syncWithoutDetaching([
$account->id => ['role' => \Darvis\Nuki\Models\NukiAccount::ROLE_OWNER],
]);
Use ROLE_MEMBER for people who should manage locks but not the account itself.
Model sub-user permissions, not roles, for log visibility. A sub user only sees locks they hold an active permission row for, and only sees log entries for locks where that row carries view_logs. When you provision sub users in code, grant permissions as a set — a lock the sub user can operate but not view_logs will appear without history, which is usually what you want for e.g. cleaners or delivery access.
Put your own routes behind the package guard. Darvis\Nuki\Http\Middleware\AuthenticateNukiUser (new) redirects guests to /nuki/login instead of your app's login route. This is the supported way to build custom Nuki screens:
Route::middleware(['web', AuthenticateNukiUser::class])
->prefix('nuki/custom')
->group(function () { /* ... */ });
Pair it with RedirectIfNukiUser on any page a signed-in package user shouldn't see.
Keep the UI toggle honest. NUKI_UI_ENABLED=false is a legitimate headless mode: you keep the API bindings, models, and webhook handling and build your own screens. If you go headless, do all your custom screens behind AuthenticateNukiUser, and never link to nuki.dashboard unconditionally.
Filter activity by lock in your own code. /nuki/activity?lock=<id> is the reference behaviour: 403 for a lock the user has no permission for, filtered results otherwise. Mirror that check in your own controllers rather than trusting a request parameter.
Extend by publishing, not by forking. Publish views to restyle the dashboard; publish config to change route prefix, guard name, redirect targets, and webhook settings. Use the package models' relations (accounts(), locks, permissions) for reporting instead of querying Nuki's API yourself.
syncWithoutDetaching with owner), then let them work./nuki/accounts) have no owner attachment. The auto-attach only happens on create. Existing accounts need a one-off backfill — write it as an idempotent command so re-running is safe.layouts/app.blade.php changed in 1.3.0 to tolerate missing UI routes and to link the brand to auth_users.redirect_after_login. A stale published layout reintroduces the 500s when NUKI_UI_ENABLED=false.redirectGuestsTo() closure if you added it per the 1.2.1 docs. Leaving it is harmless, but it's now dead configuration that will confuse the next person reading your bootstrap/app.php.view_logs. Query the pivot table before touching the UI.nuki:user-create is all-or-nothing on unknown account keys. A typo in one --account flag aborts the whole command and creates no user — safe for scripts, but check exit codes in CI/deploy hooks.403 on /nuki/sub-users from a main user signals an attachment gap, not a bug.How can I help you explore Laravel packages today?