Working with Laravel Jetstream VueJS 3 & InertiaJS with SSR Support
Tags: laravel, vue, webdev, tutorial
Published: 2022-07-15 13:58:28

You feel like you're describing a brand-new car with some fairly impressive characteristics when you read this article's headline, don't you? Working with such tools will undoubtedly give you the impression that you are driving a brand-new, stylish car.

In this Article, I'm going to help you get started with Laravel's JetStream InertiaJS stack with SSR support. JetStream will provide your next Laravel project with a well secured authentication system and InertiaJS with VueJS3 will give it a modern and elegant taste. I'll assume you have some familiarity with Laravel, but it's okay if you don't. Just follow along, and I'm sure you'll find this tutorial helpful.

| TOC  |
| ------------ |
|   [What is JetStream](#chapter-1)   |
|   [What is InertiaJS](#chapter-2)   |
|   [Why should I use Inertia with SSR support](#chapter-3)   |
|   [1- Install new Laravel App](#chapter-4)   |
|   [2- Install JetStream with SSR support](#chapter-5)   |
|   [3- Start your Laravel server](#chapter-6)   |
|   [4- Laravel & Inertia Routing](#chapter-7)   |
|   [5- InertiaJS Forms](#chapter-8)   |

I would like to start this by taking few seconds to give you a quick background about JetStream and InertiaJS.

## What is JetStream: <a name="chapter-1"></a>

>Jetstream provides the implementation for your application's login, registration, email verification, two-factor authentication, session management, API via Laravel Sanctum, and optional team management features. Jetstream is designed using Tailwind CSS and offers your choice of Livewire or Inertia scaffolding. [Source](https://www.digitalocean.com/community/tech_talks/getting-started-with-laravel-jetstream#:~:text=Jetstream%20provides%20the%20implementation%20for,of%20Livewire%20or%20Inertia%20scaffolding.)

It's the more complete version of [Laravel Breeze](https://laravel.com/docs/9.x/starter-kits#laravel-breeze) authentication system. JetStream allow you to start your next application without wasting anytime creating a secure authentication mechanism for you app.

## What is InertiaJS:<a name="chapter-2"></a>

>Inertia allows you to create fully client-side rendered, single-page apps, without much of the complexity that comes with modern SPAs. It does this by leveraging existing server-side frameworks. [DOCS](https://inertiajs.com/)

InertiaJS works side by side with Laravel and VueJS. You can think of it as a friendly neighbor who is always trying to help you to do anything. Inertia also allow you to use Laravel router instead of Vue router.

## Why should I use Inertia with SSR support:<a name="chapter-3"></a>

>Server-side rendering allows you to pre-render an initial page visit on the server, and to send the rendered HTML to the browser. This allows visitors to see and interact with your pages before they have fully loaded, and also provides other benefits such as decreasing the time it takes for search engines to index your site. [DOCS](https://inertiajs.com/server-side-rendering)

Search engine optimization (SEO) might be challenging when using VueJS since single page apps are known to confuse search engines. There are other solutions available to that problem, however InertiaJS came to the rescue by adding SSR (Server Side Rendering) functionality.

Time to get started 🚀

### 1- Install new Laravel App:<a name="chapter-4"></a>

You're free to choose the best [installation method](https://laravel.com/docs/9.x/installation), I will use for this tutorial Laravel Installer.

```cmd
laravel new {project name}
```

Don't forget to replace {project name} with any name you want to give your project.

### 2- Install JetStream with SSR support:<a name="chapter-5"></a>

When you install JetStream and Vue Inertia stack, it will install InertiaJS with VueJS 3 and TailwindCSS by default. The installation will configure everything for you, you really won't have to do a thing.

- Start with JetStream composer package

```
composer require laravel/jetstream
```

- Install InertiaJS stack with SSR support

```
php artisan jetstream:install inertia --ssr
```

### 3- Start your Laravel server:<a name="chapter-6"></a>

Since Laravel recently runs on Vite, we need to run 2 terminal commands.

```
npm run dev
```

And in another terminal window we need to run the below:

```
php artisan serve
```

And Voilà! You have a Laravel project with a fully secured authentication system, InertiaJS components styled with TailwindCSS and all of that ready to be customized to fit your project.

### 4- Laravel & Inertia Routing:<a name="chapter-7"></a>

Let's create a Product model and allow our users to create a new product and get redirected to the newly created product page.

- Create a new database and connect to use using your `.env` file in the main project directory. In my case I created a new mySQL database called tutorial and made the below changes in `.env` file.

```javascript
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tutorial
DB_USERNAME=root
DB_PASSWORD=
```

- Open up your terminal and hit the below command to create a Product model with migration:

```
php artisan make:model Product -mc
```

- Head to your products table in `database/migration` and make the below changes to add user_id, name and slug for each product.

```php
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
    }
```

- Now go to your newly created `app/models/Product` file and make those columns fillable and write the product relation to users. Since every product will belong to a user, then we're going to use [belongsTo relationship](https://laravel.com/docs/9.x/eloquent-relationships#one-to-many-inverse).

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'name',
        'slug',
    ];


    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

```

- Let's add the User relationship which will be that every user has many products. We will just add the relationship to the User model without changing anything else.

```php
    public function products()
    {
        return $this->hadMany(Product::class);
    }
```

- Migration time.

```
php artisan migrate:fresh
```

- Time to work our routes, we need one route to show the product and another to post the create product request. In this tutorial, we will use `routes/web.php` as our playground. 

First thing, let's work our route to show the product.

```php
//Route to show the product
Route::get('{slug}', function () {
       return Inertia::render('ProductShow')>name('products.show');
});
```

Notice that we don't use `return view()` anymore, the `return Inertia::render` allows you to render InertiaJS components.

Now we need the other route for posting the request. 

```php

use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

//Route to submit a new product and redirect to show it
Route::post('products/create', function (Request $request) {
    $validated = $request->validate([
        'name' => 'required',
        'slug' => 'required',
    ]);

    $user_id = $validated['user_id'] = auth()->user()->id;
    $product_slug = $validated['slug'];

    Product::create($validated);

    return redirect()->route('products.show', [$user_id, $product_slug]);
})->name('products.create');
```

### 5- InertiaJS Forms:<a name="chapter-8"></a>

- Notice that we already have welcome route set by default in `web.php`, we will use this welcome page to add to it our form.

- Head to `resources/js/Pages/Welcome.vue` and replace it with the below code. We will use Inertia's [`useForm` helper](https://inertiajs.com/forms).

```javascript
<script setup>
import { Head, Link } from "@inertiajs/inertia-vue3";
import { useForm } from "@inertiajs/inertia-vue3";

defineProps({
    canLogin: Boolean,
    canRegister: Boolean,
});

const form = useForm("createProduct", {
    name: null,
    slug: null,
});

const submit = () => {
    form.post(route("products.create"), {
        onSuccess: () => form.reset(),
    });
};
</script>

<template>
    <Head title="Welcome" />

    <div
        class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0"
    >
        <div
            v-if="canLogin"
            class="hidden fixed top-0 right-0 px-6 py-4 sm:block"
        >
            <Link
                v-if="$page.props.user"
                :href="route('dashboard')"
                class="text-sm text-gray-700 underline"
            >
                Dashboard
            </Link>

            <template v-else>
                <Link
                    :href="route('login')"
                    class="text-sm text-gray-700 underline"
                >
                    Log in
                </Link>

                <Link
                    v-if="canRegister"
                    :href="route('register')"
                    class="ml-4 text-sm text-gray-700 underline"
                >
                    Register
                </Link>
            </template>
        </div>

        <div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
            <form @submit.prevent="submit">
                <input type="text" id="name" name="name" v-model="form.name" />
                <input type="text" id="slug" name="slug" v-model="form.slug" />
                <button type="submit">Submit</button>
            </form>
        </div>
    </div>
</template>
```

Have a look at the above code and see how simple the syntax is for the form integration with Inertia's useForm helper. We make a constant called form and make it equal to `useForm` then we give a name to our form and define the data. then we make const for our submission and give it the Laravel route name and that's it!

- Now create another file in the same directory and name it `Product.vue` and paste the below code.

```javascript
<script setup>
import { Head } from "@inertiajs/inertia-vue3";
</script>

<template>
    <Head title="Product" />

    <div
        class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0"
    >
        <h1 class="text-6xl font-bold text-black">Hi, I'm product</h1>
    </div>
</template>

```

--------

Now you're ready to test your project 😎

register a new user and head to the homepage, fill the form and click on submit. You will find yourself magically redirected to the product.show route without page reloads or any kind of delay.

I hope that this quick tutorial was useful. Despite my current hectic schedule, I continue to do my best to give back to the community. Please post any questions you may have in the comments section, and I will get back to you as soon as I can 👋