Building your first Laravel Nova Tool

Published on by

Building your first Laravel Nova Tool image

Recently, I took advantage of the Black Friday sale and, although I didn’t have a use for it, I purchased a Laravel Nova license. I had been impressed with what I had seen and was desperate to give it a try.

I decided it would be fun to port one of my open-source packages, Laravel Translation to a Nova Tool.

Related: Building a Laravel Translation Package.

If you were unaware, a Tool is Nova’s method of allowing developers to add additional custom functionality to what ships out of the box.

This article will walk you through the process I took when building it.

Nova Documentation

Not knowing where to start, I headed for the documentation. As you would expect from a Laravel product, the documentation is fantastic. There is a section dedicated to building tools as well as all the other ways of customizing Nova.

Within a few minutes, I had a grasp of what I needed to do.

Nova Scaffolding

Nova ships with a CLI command which generates the scaffolding of the tool for you, php artisan nova:tool. When running this command, you pass in the tool’s name in Packagist vendor/name format which it uses when generating the composer.json file. This means it will be ready to publish as soon as development has completed.

The full scaffolding of the tool includes everything needed to get started with development including service providers, starter JavaScript, and SASS files and its class which is used to register the tool in the application.

Nova Service Provider

A tool has its service provider where it can be bootstrapped. This acts much like a Laravel service provider. It extends Illuminate\Support\ServiceProvider used in a standard Laravel application. This means all the methods like loading routes, views, migrations, etc. are available to you.

Unlike a standard Laravel service provider, all the necessary wiring up of views and routes is provided out of the box.

// Views
$this->loadViewsFrom(__DIR__.'/../resources/views', 'nova-translation');
// Routes
Route::middleware(['nova', Authorize::class])

As you can see, there is some Laravel Nova middleware automatically applied to the routes. The nova middleware group which applies any middleware defined in the nova.php configuration file and the Authorize::class which applies any custom authorization set in the tool class. More on this later.

The routes are also registered under your vendor prefix, so they don’t conflict with any other routes.

Finally, your routes are loaded from the routes/api.php file that is automatically generated with the tool.

Nova Tool Class

As previously mentioned, the tool class is created automatically for you. It is named using the studly-cased version of the name you provided when running php artisan nova:tool vendor/name.

You don’t have to do anything in here, but it is possible to modify the way you render your navigation or which assets should be loaded.

For my package, I didn’t need to make any changes to this file.

Nova Navigation

Nova makes it incredibly easy to add a link to your tool in the main sidebar of the application. Once again, this is generated automatically by providing a navigation.blade.php file containing a default navigation link and loading it from the tool class.

public function renderNavigation()
return view('nova-translation::navigation');

You are free to edit this file to suit your needs. Typically, this will involve updating the SVG icon rendered in the navigation. Conveniently, Nova ships with a set of icons you are free to use.

Laravel Nova Frontend

The Nova frontend is a Vue.js application. A new tool is initialized with a tool.js file where you can use Vue’s router to define any routes needed. From there, you are free to build the application as you wish. As you would expect, the route to the index of your app is defined for you, but you are free to update it if required.

Nova.booting((Vue, router) => {
name: 'nova-translation',
path: '/nova-translation',
component: require('./views/LanguagesIndex'),

Tools are compiled using Laravel Mix, and a configuration file is included as part of the scaffolding. This allows you to run development and production builds, and even trigger a rebuild when files change using commands you are likely familiar with such as npm run watch.

One of the things I liked when developing the frontend was the ability to utilize all the Vue components from the core of Nova.

It’s incredibly useful to be able to pull in things like loading views which automatically handle the loading state of your component or dropdown components for building out the user interface.

<loading-view :loading="initialLoading"> // ships with Nova
<loading-card :loading="loading" class="card"> // ships with Nova
// show something custom in here when loading state changes
export default {
data() {
return {
initialLoading: true,
loading: false,
languages: {}
methods: {
listLanguages() {
.then((response) => {
this.languages =;
this.initialLoading = false;
this.loading = false;
created() {

As you can see above, I use the LoadingView and LoadingCard components that ship with Nova. I then pass the loading state of my component as a prop and the loading state transition is handled for me. The result is the loading animation being rendered while my data is prepared.

Registering a Nova Tool

With the tool built, the last stage of the process is to let Nova know about its existence by registering it to the application. This is done by adding the tool class to the registerTools method of the NovaServiceProvider.

protected function registerTools()
new Dashboard,
new ResourceManager,
new NovaTranslation,

Laravel Community

Taking a step away from the technical implementation, I wanted to highlight something that happened during the development of this tool.

During the build, I wanted to implement the blue loading bar at the top of the page when carrying out an ajax-powered search. If you have used Nova before, it’s the same loader that appears when you search through any of your resources.

I was tired and burning the midnight oil trying to get it finished and could not figure it out. I decided to contact David on Twitter for some advice. Ten minutes later, I had a reply with exactly what I needed to know.

When you search the query string is updated and that bar shows up when navigating to new URLs.

— HEMPHILL (@davidhemphill) November 29, 2018

A big thank you to David for helping me through this issue, but also to the broader Laravel community. This is not, and certainly won’t be the last time I have been offered assistance from members of the community when in need.


The developer experience for Nova was fantastic. From not knowing where to start to have my package ported over only took a couple of evenings which is a testament to, not only the documentation but also the planning and execution of Nova itself. As with all things in the Laravel ecosystem, it’s been built with extreme care and attention to detail, making the onboarding experience for developers quick and painless. I, for one, can’t wait to start the next one!

If you want to look at the tool I built, check it out on Nova Packages and as always, if you have any questions, you can find me on Twitter.

Joe Dixon photo

Founder and CTO of ubisend. Proud Father to two tiny heroes, Husband, developer, occasional globetrotter.


Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project.

Visit No Compromises
Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo


The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo


Providing innovation and stability to ensure your web application succeeds.

Shift logo


Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

LoadForge logo


Easy, affordable load testing and stress tests for websites, APIs and databases.

Paragraph logo


Manage your Laravel app as if it was a CMS – edit any text on any page or in any email without touching Blade or language files.

Lucky Media logo

Lucky Media

Bespoke software solutions built for your business. We ♥ Laravel

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
Bacancy - Staff Augmentation logo

Bacancy - Staff Augmentation

Leave your web app development hustles to the leading IT Staff Augmentation Service Providers. Choose from an extensive pool of 1050+ developers and give yourself the sigh of success you deserve with Bacancy. Get In Touch Today!

Bacancy - Staff Augmentation logo

Save hours of manually writing Code Documentation, Comments & DocBlocks, Test suites and Refactoring.
Rector logo


Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies


The latest

View all →
Laracon EU Videos are now out image

Laracon EU Videos are now out

Read article
Use Google's Gemini AI in Laravel image

Use Google's Gemini AI in Laravel

Read article
PhpStorm is getting a brand new terminal image

PhpStorm is getting a brand new terminal

Read article
Six Essential Plugins for Visual Studio Code image

Six Essential Plugins for Visual Studio Code

Read article
Modularize Your Laravel Application With the Modular Package image

Modularize Your Laravel Application With the Modular Package

Read article
Handle Money Transactions in Eloquent with Laravel Wallet image

Handle Money Transactions in Eloquent with Laravel Wallet

Read article