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])
->prefix('nova-vendor/nova-translation')
->group(__DIR__.'/../routes/api.php');

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) => {
router.addRoutes([
{
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.

<template>
<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
</loading-card>
</loading-view>
</template>
 
<script>
export default {
data() {
return {
initialLoading: true,
loading: false,
languages: {}
}
},
 
methods: {
listLanguages() {
Nova.request().get('/nova-vendor/nova-translation/languages')
.then((response) => {
this.languages = response.data;
this.initialLoading = false;
this.loading = false;
})
}
},
 
created() {
this.listLanguages()
},
}
</script>

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()
{
Nova::tools([
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.

Conclusion

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.

Cube

Laravel Newsletter

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

Laravel Forge logo

Laravel Forge

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

Laravel Forge
Tinkerwell logo

Tinkerwell

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

Tinkerwell
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

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

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

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

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
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate logo

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate

Build your SaaS application in hours. Out-of-the-box multi-tenancy and seamless Stripe integration. Supports subscriptions and one-time purchases, allowing you to focus on building and creating without repetitive setup tasks.

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate
Rector logo

Rector

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

Rector
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
Asymmetric Property Visibility in PHP 8.4 image

Asymmetric Property Visibility in PHP 8.4

Read article
Access Laravel Pulse Data as a JSON API image

Access Laravel Pulse Data as a JSON API

Read article
Laravel Forge adds Statamic Integration image

Laravel Forge adds Statamic Integration

Read article
Transform Data into Type-safe DTOs with this PHP Package image

Transform Data into Type-safe DTOs with this PHP Package

Read article
PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell image

PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell

Read article
Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3 image

Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3

Read article