How to Convert a Node.js Theme into a Laravel + Vue.js + Inertia Theme

As web development continues to evolve, developers often find themselves needing to migrate applications between different stacks to meet modern project requirements. One common scenario is converting a Node.js theme (typically based on EJS, Pug, or Handlebars) into a full-stack Laravel application using Vue.js and Inertia.js.

This comprehensive guide will walk you through how to take an existing Node.js theme and convert it into a clean, component-based Laravel + Vue + Inertia.js application. We’ll cover everything from preparing your Laravel project to restructuring your front-end components for modern, maintainable code.


📌 Why Convert From Node.js to Laravel + Vue + Inertia?

Here are a few reasons you might want to switch:

  • Separation of concerns: Laravel offers a robust backend while Vue handles a reactive, modern frontend.
  • Inertia.js: Bridges Laravel and Vue beautifully, enabling single-page app (SPA) experiences without the complexity of building an API.
  • Better developer tools: Laravel provides great tooling out of the box like Eloquent ORM, Blade components, Laravel Mix/Vite, and more.
  • Maintainability: Vue components offer a more modular structure than traditional server-rendered templates.

🛠 Step 1: Understand Your Node.js Theme Structure

Before converting, audit your existing Node.js project.

Your directory might look like:

/views
  ├─ layout.ejs
  ├─ home.ejs
  ├─ partials/
    ├─ header.ejs
    ├─ footer.ejs
/public
  ├─ css/
  ├─ js/
  ├─ images/

Take note of:

  • Page layouts and structure
  • How routes are defined
  • Dynamic data being injected (e.g., <%= user.name %>)
  • Front-end assets (Bootstrap, jQuery, etc.)

⚙️ Step 2: Set Up Laravel with Vue and Inertia

Start by installing a fresh Laravel project.

composer create-project laravel/laravel laravel-inertia-app
cd laravel-inertia-app

Install Laravel Breeze with Vue + Inertia:

composer require laravel/breeze --dev
php artisan breeze:install vue
npm install && npm run dev
php artisan migrate

You now have:

  • Laravel backend
  • Vue.js frontend
  • Inertia.js integration for SPA-like behavior

🧩 Step 3: Set Up the Directory Structure

In Laravel:

  • Vue components go in: resources/js/Components
  • Pages go in: resources/js/Pages
  • Layouts can go in: resources/js/Layouts

Create basic folders if needed:

mkdir -p resources/js/Components resources/js/Pages resources/js/Layouts

📥 Step 4: Convert Your HTML Templates into Vue Components

Let’s say your home.ejs contains:

<%- include('partials/header') %>
<h1>Welcome <%= user.name %></h1>
<%- include('partials/footer') %>

You can convert this to a Vue + Inertia page:

resources/js/Layouts/Layout.vue

<template>
  <div>
    <Header />
    <main><slot /></main>
    <Footer />
  </div>
</template>

<script setup>
import Header from '../Components/Header.vue'
import Footer from '../Components/Footer.vue'
</script>

resources/js/Pages/Home.vue

<template>
  <Layout>
    <h1>Welcome {{ user.name }}</h1>
  </Layout>
</template>

<script setup>
import Layout from '../Layouts/Layout.vue'
defineProps({ user: Object })
</script>

📁 Step 5: Move CSS, JS, and Images

Move public assets from your Node.js project into the Laravel structure.

  • CSS → resources/css/
  • JavaScript → resources/js/
  • Images → public/images/

Import any CSS in resources/js/app.js:

import '../css/theme.css';

If you’re using Bootstrap or another framework:

npm install bootstrap

Then include it:

import 'bootstrap/dist/css/bootstrap.min.css';

🧠 Step 6: Migrate Dynamic Logic

Convert template logic (like EJS or Pug) into Vue syntax.

EJS example:

<% if (user.isAdmin) { %>
  <p>Admin Panel</p>
<% } %>

Vue equivalent:

<p v-if="user.isAdmin">Admin Panel</p>

EJS loop:

<ul>
  <% items.forEach(function(item) { %>
    <li><%= item.name %></li>
  <% }); %>
</ul>

Vue loop:

<ul>
  <li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>

🌐 Step 7: Create Routes and Controllers in Laravel

Define a route that returns an Inertia page:

routes/web.php

use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Home', [
        'user' => Auth::user()
    ]);
});

Create controllers for more complex logic:

Route::get('/dashboard', [DashboardController::class, 'index']);

In your controller:

public function index()
{
    return Inertia::render('Dashboard', [
        'user' => Auth::user(),
        'data' => SomeModel::all()
    ]);
}

📝 Step 8: Handling Forms and POST Requests

Using Inertia and Vue, forms are simple and reactive.

Example Form:

<template>
  <form @submit.prevent="submit">
    <input v-model="form.name" type="text" />
    <button type="submit">Submit</button>
  </form>
</template>

<script setup>
import { useForm } from '@inertiajs/vue3'

const form = useForm({ name: '' })

const submit = () => {
  form.post('/submit')
}
</script>

Laravel Route:

Route::post('/submit', function () {
    // Handle form logic
});

🔔 Step 9: Flash Messages & Validation

Laravel automatically flashes session messages.

Backend:

return redirect('/')->with('success', 'Form submitted successfully!');

Vue Page:

<p v-if="$page.props.flash.success">{{ $page.props.flash.success }}</p>

To handle validation errors, Inertia will return them and make them available via form.errors.


🧱 Step 10: Modularize Your UI

Split your UI into reusable Vue components like:

  • Navbar.vue
  • Sidebar.vue
  • UserCard.vue

Place them in resources/js/Components and reuse them as needed:

<Navbar />
<UserCard :user="user" />

This makes your Laravel + Vue theme scalable and easy to maintain.


🧪 Bonus Tips

  • Use Laravel Mix or Vite (default from Laravel 9+) for asset bundling.
  • Use Inertia middleware to share global data like authenticated user, flash messages, etc.
  • If migrating from a CMS-based Node.js app, consider using Laravel’s Blade if needed for email templates or fallback rendering.

✅ Final Thoughts

Migrating a theme from Node.js to Laravel + Vue.js + Inertia may seem daunting at first, but once you break it down:

  • You get a clean separation of logic and UI
  • You benefit from Laravel’s robust backend features
  • Vue.js provides a modern, reactive frontend
  • Inertia makes routing and data-sharing seamless

Advantages of Laravel + Vue + Inertia:

  • No need for separate API + SPA codebases
  • Less boilerplate than REST or GraphQL APIs
  • Smooth developer experience

Whether you’re moving to Laravel for better backend capabilities or standardizing on a PHP stack, this conversion is a worthwhile investment.


📣 Want to Learn More?

Let me know if you’d like a downloadable boilerplate or GitHub example repo!



Leave a Reply

Your email address will not be published. Required fields are marked *