Say hello to the Inertia Head component
Published on Tuesday June 1st, 2021With the newest release of Inertia.js comes a new component called "Inertia head". This new component allows you to update the <title>
and <meta>
tags inside the <head>
tag of your HTML. Before this component, trying to change the <title>
of your page, although not impossible, wasn't very easy. Not only can you do this with ease within your page component, but you can also take advantage of any props
passed to your page.
Imagine being able to set your Open Graph tags dynamically or updating the page's title when your user is reading an article, or even changing the favicon; all of this is possible.
To demonstrate this new feature, let's start using my favourite Laravel starter kit Laravel Breeze.
Start by creating a new Laravel app.
laravel new inertia-head-demo
Once this is run, cd into your new project and run
composer require laravel/breeze --dev
followed by
PHP artisan breeze:install vue
Once this has run, you should see your devDependencies
of your package.json
have been updated and look like this.
"devDependencies": { "@inertiajs/inertia": "^0.8.4", "@inertiajs/inertia-vue3": "^0.3.5", "@inertiajs/progress": "^0.2.4", "@tailwindcss/forms": "^0.2.1", "@vue/compiler-sfc": "^3.0.5", "autoprefixer": "^10.2.4", "axios": "^0.21", "laravel-mix": "^6.0.6", "lodash": "^4.17.19", "postcss": "^8.2.13", "postcss-import": "^14.0.1", "tailwindcss": "^2.1.2", "vue": "^3.0.5", "vue-loader": "^16.1.2"}
To take advantage of this <inertia-head>
we need to bump the version of @inertiajs/inertia
, @inertiajs/inertia-vue3
. While we are at it we can also updated @inertiajs/progress
to the latest version, but this isn't required.
"devDependencies": { "@inertiajs/inertia": "^0.9.1", "@inertiajs/inertia-vue3": "^0.4.2", "@inertiajs/progress": "^0.2.5", // optional ...}
Next, let's install our JavaScript dependencies and build our assets and watch for changes.
npm install && npm run watch
Next, we want to edit our app layouts and add <inertia-head>
tags. What we set here will be the "defaults" that we can override at the page level.
In Breeze, there are two layout components, Guest.vue
located at resources/js/Layouts/Guest.vue
and Authenticated.vue
located at resources/js/Layouts/Authenticated. vue
The Guest.vue
layout gets used by all the auth views, and Authenticated.vue
gets used once the user has authenticated and is viewing their dashboard. For this example, we will focus on the auth screens and the Guest.vue
layout; add the following to Guest.vue
layout anywhere in the <template>
tags.
<inertia-head title="Inertia Head Demo" />
I am using Laravel Valet locally, so if I go and visit http://inertia-head-demo.test/login
I should expect to see the title for that page to be "Inertia Head Demo", but visiting /login
to check, the title will show "Laravel" or whatever your is in your .env
setting for APP_NAME
. The reason for that is there should only ever be one <title>
tag on the page, and if there are more than one, the first one that appears on the page will take priority. If you check the app.blade.php
file, you'll see this on line 8
<title>{{ config('app.name', 'Laravel') }}</title>
If you delete the above line and refresh the page, we should see the title we set in our layout.
Good stuff, right? Okay, let's take that next step. Open Login.vue
and add a <inertia-head>
tag to overwrite the default we set in the Guest.vue
<inertia-head title="Inertia Head Demo - Login" />
Now when you visit /login
, you will see Inertia Head Demo - Login
in your browser tab as the title.
Open Graph meta tags
Facebook and Twitter both allow you to customize what the preview for a URL looks like. You can read about Facebook's OG tags here and Twitter cards here.
Let's start by updating the default <inertia-head>
component we added to Guest.vue
add the following.
<inertia-head> <title>Inertia Head Demo</title> <meta type="description" content="Inertia Head Demo." /> <meta name="twitter:title" content="Inertia Head Demo" /> <meta name="twitter:site" content="@ninjaparade" /> <meta name="twitter:creator" content="@ninjaparade" /> <meta name="twitter:description" content="Inertia Head Demo." /> <meta name="twitter:card" content="summary_large_image" /> <meta property="og:url" content="http://inertia-head-demo.test" /> <meta property="og:title" content="Inertia Head Demo" /> <meta property="og:description" content="Inertia Head Demo" /> <meta property="og:type" content="website" /> <meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" /></inertia-head>
Now visit /login
, and you should see this.
<head> <title inertia="">Inertia Head Demo </title> <meta type="description" content="Inertia Head Demo." inertia="" /> <meta property="og:url" content="http://inertia-head-demo.test" inertia="" /> <meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="" /> <meta name="twitter:title" content="Inertia Head Demo." inertia="" /> <meta name="twitter:site" content="@ninjaparade" inertia="" /> <meta name="twitter:creator" content="@ninjaparade" inertia="" /> <meta name="twitter:description" content="Inertia Head Demo." inertia="" /> <meta name="twitter:card" content="summary_large_image" inertia="" /> <meta property="og:title" content="Inertia Head Demo." inertia="" /> <meta property="og:description" content="Inertia Head Demo." inertia="" /> <meta property="og:type" content="website" inertia="" /></head>
You can see the OG Meta tags, followed by the title. The defaults are used here, and since we set the title in the <inertia-head>
on our Login.vue
page, we see Inertia removing the default title and using the one from our page component.
Now let's try to set the OG tags in our Login.vue
component. I'm going to add this.
<inertia-head> <title>Inertia Head Demo - Login</title> <meta type="description" content="Inertia Head Demo - Login page." /> <meta name="twitter:title" content="Inertia Head Demo - Login page." /> <meta name="twitter:site" content="@ninjaparade" /> <meta name="twitter:creator" content="@ninjaparade" /> <meta name="twitter:description" content="Inertia Head Demo - Login page." /> <meta name="twitter:card" content="summary_large_image" /> <meta property="og:url" content="http://inertia-head-demo.test/login" /> <meta property="og:title" content="Inertia Head Demo - Login page." /> <meta property="og:description" content="Inertia Head Demo - Login page." /> <meta property="og:type" content="website" /> <meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" /></inertia-head>
Now refresh and visit /login
... WHAT IS HAPPENING!?
<head> ... <meta type="description" content="Inertia Head Demo." inertia="" /> <meta property="og:url" content="http://inertia-head-demo.test" inertia="" /> <meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="" /> <meta name="twitter:title" content="Inertia Head Demo." inertia="" /> <meta name="twitter:site" content="@ninjaparade" inertia="" /> <meta name="twitter:creator" content="@ninjaparade" inertia="" /> <meta name="twitter:description" content="Inertia Head Demo." inertia="" /> <meta name="twitter:card" content="summary_large_image" inertia="" /> <meta type="description" content="Inertia Head Demo - Login page." inertia="" /> <meta name="twitter:title" content="Inertia Head Demo - Login page." inertia="" /> <meta name="twitter:site" content="@ninjaparade" inertia="" /> <meta name="twitter:creator" content="@ninjaparade" inertia="" /> <meta name="twitter:description" content="Inertia Head Demo - Login page." inertia="" /> <meta name="twitter:card" content="summary_large_image" inertia="" /> <meta property="og:url" content="http://inertia-head-demo.test" inertia="" /> <meta property="og:title" content="Inertia Head Demo - Login page." inertia="" /> <meta property="og:description" content="Inertia Head Demo - Login page." inertia="" /> <meta property="og:type" content="website" inertia="" /> <meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="" /> <title inertia="">Inertia Head Demo - Login</title></head>
Our <head>
tag now duplicates our meta tags and empty inertia
attributes; why is this happening? The <inertia-head>
component will always ensure only one <title>
tag. When it comes to the <meta>
tags <inertia-head>
is simply going to take the defaults and the <meta>
tags from the Login.vue
component and stack them which is why you see them duplicated. Thankfully fixing this is pretty straightforward. We can tell <inertia-head>
how to handle duplicates by adding a head-key
property. This will make sure the tag is only rendered once.
So change the Guest.vue
Inertia head to this.
<inertia-head> <title>Inertia Head Demo</title> <meta head-key="description" type="description" content="Inertia Head Demo." /> <meta head-key="twitter:title" name="twitter:title" content="Inertia Head Demo." /> <meta head-key="twitter:site" name="twitter:site" content="@ninjaparade" /> <meta head-key="twitter:creator" name="twitter:creator" content="@ninjaparade" /> <meta head-key="twitter:description" name="twitter:description" content="Inertia Head Demo." /> <meta head-key="twitter:card" name="twitter:card" content="summary_large_image" /> <meta head-key="og:url" property="og:url" content="http://inertia-head-demo.test" /> <meta head-key="og:title" property="og:title" content="Inertia Head Demo." /> <meta head-key="og:description" property="og:description" content="Inertia Head Demo." /> <meta head-key="og:type" property="og:type" content="website" /> <meta head-key="og:image" property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" /></inertia-head>
And change the <inertia-head>
component in Login.vue
to
<inertia-head> <title>Inertia Head Demo - Login</title> <meta head-key="description" type="description" content="Inertia Head Demo - Login page." /> <meta head-key="twitter:title" name="twitter:title" content="Inertia Head Demo - Login page." /> <meta head-key="twitter:site" name="twitter:site" content="@ninjaparade" /> <meta head-key="twitter:creator" name="twitter:creator" content="@ninjaparade" /> <meta head-key="twitter:description" name="twitter:description" content="Inertia Head Demo - Login page." /> <meta head-key="twitter:card" name="twitter:card" content="summary_large_image" /> <meta head-key="og:url" property="og:url" content="http://inertia-head-demo.test/login" /> <meta head-key="og:title" property="og:title" content="Inertia Head Demo - Login page." /> <meta head-key="og:description" property="og:description" content="Inertia Head Demo - Login page." /> <meta head-key="og:type" property="og:type" content="website" /> <meta head-key="og:image" property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" /></inertia-head>
let your assets recompile and refresh and you should see this.
<head> ... <title inertia="">Inertia Head Demo - Login</title> <meta type="description" content="Inertia Head Demo - Login page." inertia="description" /> <meta property="og:url" content="http://inertia-head-demo.test" inertia="og:url" /> <meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="og:image" /> <meta name="twitter:title" content="Inertia Head Demo - Login page." inertia="twitter:title" /> <meta name="twitter:site" content="@ninjaparade" inertia="twitter:site" /> <meta name="twitter:creator" content="@ninjaparade" inertia="twitter:creator" /> <meta name="twitter:description" content="Inertia Head Demo - Login page." inertia="twitter:description" /> <meta name="twitter:card" content="summary_large_image" inertia="twitter:card" /> <meta property="og:title" content="Inertia Head Demo - Login page." inertia="og:title" /> <meta property="og:description" content="Inertia Head Demo - Login page." inertia="og:description" /> <meta property="og:type" content="website" inertia="og:type" /></head>
That's it! There is more to discuss about <inertia-head>
and where it really shines when paired with an upcoming feature to provide server-side rendering for Inertia. SSR for Inertia is ready to be used and is currently powering the Inertia.js website, but documentation on how to get this working on Laravel Forge and Heroku are currently available to Inerita sponsors.
Thanks for reading and feel free to reach out on Twitter if you got any questions.