/

Custom Nova 4 Error Pages

Have you been asked to make a custom error page for Laravel Nova 4 and had a hard time and want to cry?

Me too, but not anymore.

As of 2023, the way of doing this is creating custom assets and registering them. https://github.com/laravel/nova-issues/discussions/5809

Here are the steps:

  1. Make a custom asset.
  2. In the asset, register your custom component.
  3. Create the custom component.
  4. Build the asset.

First, make a custom asset. https://nova.laravel.com/docs/customization/assets.html

Make sure you use your company or organization name.

php artisan nova:asset your-company/nova-error-pages

This will ask you to update composer, install npm dependencies, and compile dependencies. You should say yes to everything.

When you are done this step, you should have a new asset in ./nova-components and your composer.json should be updated.

Okay. Now you have a custom asset. It’s its own little thing that lives in ./nova-components/NovaErrorPages/. It has its own composer.json and package.json. You are doing great.

The asset should look like this.

composer.json
dist
node_modules
nova.mix.js
package-lock.json
package.json
postcss.config.js
resources
src
webpack.mix.js

Now, find ./nova-components/NovaErrorPages/resources/js/asset.js. This is where you’ll register your new component.

You need to make asset.js look exactly like this:

import NovaErrorPages from "./components/NovaErrorPages"

// We override the existing Nova Error Pages.
// https://github.com/laravel/nova-issues/discussions/5809
Nova.booting((app) => {
  app.component("CustomError403", {
    extends: NovaErrorPages,
    props: {
      status: {
        type: String,
        default: "403",
      },
    },
  })
  app.component("CustomError404", {
    extends: NovaErrorPages,
    props: {
      status: {
        type: String,
        default: "404",
      },
    },
  })
  app.component("CustomAppError", {
    extends: NovaErrorPages,
    props: {
      status: {
        type: String,
        default: "500",
      },
    },
  })
})

What we did was register our new component (we haven’t made that yet) in Nova. It replaces the existing CustomError404 and friends. You can find them in ./vendor/laravel/nova/resources/js/views/CustomError404.vue.

Ok, next we need to actually make the component, right?

Create a file at ./nova-components/NovaErrorPages/resources/js/components/NovaErrorPages.vue.

Copy in this code.

<template>
  <!-- We have copied this from the existing Nova Error Page Views, and modified it. -->
  <div class="flex justify-center h-screen">
    <div
      class="z-50 flex items-center justify-center p-6"
      :dusk="`${status}-error-page`"
    >
      <span class="shrink-0 md:w-[20rem]" v-html="logo"></span>
      <div
        class="flex flex-col md:flex-row justify-center items-center space-y-4 md:space-y-0 md:space-x-20"
        role="alert"
      >
        <div class="md:w-[20rem] md:shrink-0 space-y-2 md:space-y-4">
          <Head title="Page Not Found" />
          <h1 class="text-[5rem] md:text-[4rem] font-normal leading-none">
            {{ status }}
          </h1>
          <p class="text-lg leading-normal">
            <span v-if="status === '403'">{{ __("Access denied") }}</span>
            <span v-else-if="status === '404'">{{ __("Page not found") }}</span>
            <span v-else="status === '500'">{{ __("Unexpected error") }}</span>
          </p>

          <Link
            :href="$url('/')"
            class="inline-flex items-center focus:outline-none focus:ring rounded border-2 border-primary-300 dark:border-gray-500 hover:border-primary-500 active:border-primary-400 dark:hover:border-gray-400 dark:active:border-gray-300 bg-white dark:bg-transparent text-primary-500 dark:text-gray-400 px-3 py-2 h-9 font-bold tracking-wide uppercase"
            tabindex="0"
            replace
          >
            {{ __("Go Home") }}
          </Link>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  computed: {
    logo() {
      return window.Nova.config("logo")
    },
  },
}
</script>

That will give you a template that uses your company’s logo if defined. __("Page not found") is a translation I added to Nova’s translations. Let’s do that now.

Add this to ./resources/lang/vendor/nova/en.json

"Page not found": "Page not found",
"Access denied": "Access denied",
"Unexpected error": "Unexpected error"

Okay. Great. Pretty much done.

Finally, build your component. From your project root, run npm run build-nova-error-pages-prod.

That should be it. Cause a 404 and see if it worked.

If you are having trouble, reach out!