Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Vue with Laravel Setup Complete Guide

By Kokil Thapa | Last reviewed: September 2026

You want Vue interactivity without turning Laravel into two disconnected codebases. This Vue with Laravel Setup Complete Guide walks through the current stack: Laravel 13, Vue 3, and Vite 8 on Node.js 26 LTS. The goal is a setup that builds cleanly, hot-reloads reliably, and deploys without Node on production. If you are weighing server-driven UI against client-side Vue, start with my Laravel Livewire tutorial for beginners — then return here when custom Vue components are the right call.

How do you configure Vite for Vue with Laravel in 2026?

Laravel Mix is legacy territory. New projects ship with Vite 8.x and the official laravel-vite-plugin. Vite gives you fast Hot Module Replacement and hashed production assets. Misconfigured paths cause blank screens — the most common first-day failure.

Prerequisites and dependencies

Start from Laravel 13 on PHP 8.3 or higher. Laravel 12 on PHP 8.2 still works if you are mid-upgrade. Use Node.js 26 LTS and npm 12. Run Composer 2.10 for PHP packages.

composer create-project laravel/laravel my-vue-app
cd my-vue-app
npm install vue @vitejs/plugin-vue
npm install -D sass

Install sass when components use <style lang="scss">. Without it, Vite fails on SCSS blocks with errors that look like Vue compiler bugs.

Production-ready vite.config.js

The config below matches what I use on production Laravel applications. It wires Laravel inputs, Vue SFC support, and a @ alias for clean imports.

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import path from 'path';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './resources/js'),
        },
    },
});

The transformAssetUrls block matters. Vue may treat image paths as JS imports without it. Broken product images in production often trace back to this single setting. For deeper Vite tuning, see my Vite config guide for Laravel projects.

Vue + Laravel Vite PipelineVue SFC.vue filesVite 8plugin-vueBlade@vite tagBrowserHMR / prodmanifest.json maps hashed filenames in productionLaravel reads manifest at runtime — no Node on server
Vue with Laravel Setup Complete Guide: Vite transforms Single File Components and Laravel serves them through the @vite directive.

Bootstrapping Vue in app.js

Use Vue 3 with the Composition API. Mount from resources/js/app.js and reference the entry in your layout.

import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');

Your Blade layout needs a mount point and the Vite directive. Never use the old mix() helper on Laravel 12 or 13.

<!DOCTYPE html>
<html lang="en">
<head>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
    <div id="app"></div>
</body>
</html>

Run npm run dev for local HMR. Run npm run build before deploy. The official Laravel Vite documentation covers environment-specific options if you need SSR or multiple entry points.

Should you use Inertia.js or a standalone SPA with Vue and Laravel?

This choice shapes every sprint after setup. Inertia keeps routing on Laravel. A standalone SPA moves routing to Vue Router and forces you to design a real API. On legal-tech portals I have built, dashboards often suit Inertia. Public APIs or mobile clients push you toward Sanctum.

CriteriaInertia.js + VueStandalone SPA + Sanctum
RoutingLaravel routes and controllersVue Router on the client
Data flowProps from controller responsesJSON from /api/* endpoints
AuthenticationSession cookies (automatic)Sanctum SPA cookies or API tokens
SEOEasier with server-rendered shellNeeds SSR, prerender, or hybrid pages
API reuseLow — tied to web controllersHigh — same API for web and mobile
Best fitInternal tools, admin dashboardsMarketplaces, mobile-first products

When Inertia.js wins

Inertia returns Vue page components from ordinary Laravel controllers. You skip API versioning, resource transformers, and token refresh logic. For web-only products, that cuts boilerplate sharply. Custom admin UI that Filament cannot cover is a common Inertia use case. Compare options in my Livewire 3 vs Inertia guide. For zero-custom-JS admin panels, see the Filament admin panel tutorial instead.

When a standalone SPA wins

Choose a decoupled SPA when mobile apps, third-party integrations, or headless consumers need the same backend. Sanctum handles cookie auth for your Vue app and token auth for mobile. You own loading states, error handling, and route guards in Vue. Read Laravel API best practices before you commit — bad endpoints are expensive to fix later. For auth specifics, see Sanctum vs Passport and building a REST API with Sanctum.

Architecture ChoiceNew Laravel + Vue projectNeed shared public API?NoYesInertia.jsLaravel routesVue SPASanctum + RouterFast monolith DXMulti-client API
Vue with Laravel Setup Complete Guide: pick Inertia for web-only monoliths, or Sanctum SPA when mobile and third parties need the same API.

How do you mount Vue components inside existing Blade pages?

Not every project needs a full SPA on day one. Laravel supports islands of Vue inside server-rendered pages. This pattern works well for booking widgets, search filters, and document upload UIs.

Multiple entry points

Add extra inputs in vite.config.js for each mount point. A dashboard page and a public catalog can share one build but load different bundles.

laravel({
    input: [
        'resources/css/app.css',
        'resources/js/app.js',
        'resources/js/booking-widget.js',
    ],
    refresh: true,
}),

In Blade, call @vite(['resources/js/booking-widget.js']) only on pages that need it. Smaller JS payloads help Core Web Vitals on content-heavy sites.

Alpine.js as a lighter alternative

For toggles, dropdowns, and small forms, Alpine.js inside Blade may be enough. It avoids a build step for simple interactivity. Read Alpine.js for interactive Blade templates before defaulting to Vue everywhere. Vue earns its place when state, validation, or component reuse grows beyond a few lines.

How do you set up state management and API calls in Vue?

Small apps can rely on props and composables. Larger SPAs need Pinia for shared state. Vuex 4 still works but Pinia is the default for new Vue 3 projects.

For standalone SPAs, configure axios or fetch with Sanctum credentials. Call /sanctum/csrf-cookie before POST, PUT, or DELETE requests. Inertia skips this step because Laravel handles CSRF on full page requests.

import axios from 'axios';

axios.defaults.withCredentials = true;
axios.defaults.withXSRFToken = true;

await axios.get('/sanctum/csrf-cookie');
await axios.post('/api/bookings', { date: '2026-09-15' });

Pinia stores keep user session and cart data out of prop-drilling hell. See Pinia vs Vuex 4 for migration notes. For component structure, my Vue 3 Composition API deep dive covers patterns that scale on real client projects.

Sanctum SPA Auth FlowVue SPABrowser clientCSRF cookie/sanctum/csrf-cookieLaravel APISession + token419 error without CSRF preflightAlways fetch CSRF cookie before mutating requestsSet SANCTUM_STATEFUL_DOMAINS in .env correctlyMatch APP_URL and frontend origin exactly
Vue with Laravel Setup Complete Guide: Sanctum SPA mode requires a CSRF cookie fetch before API mutations to avoid 419 errors.

What are common Vue with Laravel setup mistakes in 2026?

These issues show up on support forums and in production logs. Most trace back to environment mismatch or legacy Mix habits.

  • HMR stuck on localhost: Remote dev over SSH or Docker needs explicit HMR host config in Vite. Add server: { hmr: { host: 'your-app.test' } } or the browser never receives updates.
  • 419 CSRF on SPA POST: Standalone Vue apps must call /sanctum/csrf-cookie first. Inertia handles CSRF through normal form semantics.
  • Wrong env prefix: Vite exposes only VITE_* variables. Legacy MIX_* names from Mix projects return undefined in Vue code.
  • Production build on the server: Running npm run build on a VPS invites version drift. Build in CI and ship public/build/ as an artifact.
  • Cached prod assets during dev: Stale files in public/build/ make DevTools report no Vue instance. Delete the folder and restart Vite.
  • TypeScript gaps: Add "types": ["vite/client"] to tsconfig.json so import.meta.env resolves in the IDE.

Environment variables and security

Never prefix secrets with VITE_. Those values ship to every browser. Keep API keys, database credentials, and payment secrets in PHP-only .env entries. Public values like VITE_APP_NAME and VITE_API_URL are fine. When debugging API payloads locally, a JSON formatter saves time parsing responses.

Migrating from Laravel Mix

Older Laravel 10 and 11 projects may still use Mix. Replace mix() with @vite one layout at a time. Compare bundlers in Vite vs Webpack for frontend builds. Finish migration before jumping to Laravel 13 — Mix no longer receives first-party support.

How do you deploy Vue with Laravel applications to production?

Production servers should run PHP, not Node. I deploy sister legal-tech sites with Deployer 7 and GitLab CI on shared EC2. Assets build in CI, then PHP-FPM serves hashed files from public/build/.

Artifact-based deployment steps

  1. Build in CI: Use Node.js 26 LTS. Run npm ci, not npm install, for reproducible lockfile installs.
  2. Verify manifest: Confirm public/build/manifest.json exists with hashed filenames before deploy.
  3. Ship artifacts: Upload public/build/ or commit it if your team accepts that trade-off on small projects.
  4. Zero-downtime swap: Deployer symlinks the new release. Reload PHP-FPM to clear opcache.
  5. Smoke test assets: Load one page and confirm JS and CSS return 200, not 404.

Full pipeline details live in my zero-downtime Deployer guide. On booking systems like Adventure Third Pole Trek, Laravel plus Livewire handles most UI — but the same deploy pattern applies when Vue bundles ship alongside Blade.

Production Deploy FlowGitLab CInpm ci & buildArtifactspublic/build/Deployer 7Symlink swapLivePHP-FPMDo not install Node on productionCache hashed assets: max-age=31536000HTML responses: no-cache for manifest lookup
Vue with Laravel Setup Complete Guide deployment: build assets in CI, ship public/build, and swap releases without Node on the server.

CDN and cache headers

Vite hashes filenames in production. Serve JS and CSS with long cache lifetimes. Keep HTML uncached so browsers pick up new manifest entries. Purge CDN cache on manifest changes only — not every asset file. That pattern cuts bandwidth for Nepal users on slower connections.

How does Vue with Laravel compare to other 2026 frontend options?

Vue is not always the answer. Pick based on team skills, SEO needs, and whether you need a public API.

  • Livewire: No separate frontend build. Best for CRUD dashboards when Vue hiring is hard. See the Livewire tutorial for a full walkthrough.
  • Filament: Admin panels without writing Vue. Ideal when standard CRUD covers 90% of back-office work.
  • React + Inertia: Larger global talent pool. Steeper curve for PHP-first teams.
  • HTMX: Minimal JS for progressive enhancement. Poor fit for persistent client state.

Vue hits a sweet spot for PHP developers learning modern frontend. The Vue 3 documentation is clear, and Laravel packages for Inertia and Sanctum are mature. For agency work spanning law portals and e-commerce, Vue skills transfer across project types. Review modern Laravel architecture best practices so your backend structure supports whichever frontend you pick.

Need a team to implement this stack? Our web development services in Nepal cover Laravel, Vue, deployment, and ongoing maintenance. You can also reach out directly via contact me for architecture review.

Key Takeaways

  • Install Vue 3 with @vitejs/plugin-vue on Laravel 13, Node.js 26 LTS, and Vite 8 — not Mix.
  • Choose Inertia for web-only monoliths; choose Sanctum SPA when mobile or third parties need the same API.
  • Call /sanctum/csrf-cookie before mutating requests in standalone SPAs to prevent 419 errors.
  • Build assets in CI and deploy public/build/ artifacts — never run npm on production servers.
  • Use VITE_* env vars only for public values; keep secrets in PHP-side .env entries.
  • Start with Vue islands in Blade for small widgets; graduate to full SPA only when state complexity demands it.

People Also Ask

Does Laravel 13 include Vue by default?

No. Laravel ships with Vite and a minimal JavaScript entry point. You install Vue manually with npm install vue @vitejs/plugin-vue and configure the plugin in vite.config.js. Jetstream with Inertia is an optional starter kit if you want scaffolding.

Can you use Vue with Laravel without Inertia?

Yes. Mount Vue on a Blade page with a single #app div, or build a full SPA with Vue Router and Sanctum. Inertia is optional — it just removes the need to build a separate JSON API for web-only apps.

Is Vite required for Vue in Laravel?

For current Laravel versions, yes. Mix is deprecated for new work. Vite is the official bundler and powers HMR during development plus hashed assets in production.

How do you fix Vue HMR not updating in Laravel?

Check that npm run dev is running and @vite points to the correct entry files. For remote or Docker dev, set an explicit HMR host in vite.config.js. Clear stale files in public/build/ if production assets shadow dev mode.

Ship your Vue with Laravel Setup Complete Guide stack

A clean Vue with Laravel Setup Complete Guide setup saves months of debugging later. Configure Vite 8 correctly, pick Inertia or Sanctum deliberately, and deploy assets from CI from day one. Skip tutorials that still reference Mix, Vue 2, or Node 18 — they will waste your afternoon. If you want hands-on help scoping architecture or implementing the full stack, contact us for a review tailored to your project.

Frequently Asked Questions

Laravel 12 requires PHP 8.2 or higher. Vue 3 itself is framework-agnostic and runs in the browser, so it doesn’t impose any PHP version constraints. However, if you’re using Laravel’s Vite plugin (laravel-vite-plugin 1.x), ensure your Node.js environment is at least version 18 to avoid build issues.

After creating a Laravel 12 project with `composer create-project laravel/laravel project-name`, run `npm install vue@next @vitejs/plugin-vue`. Then update vite.config.js to include the Vue plugin: `import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue(), laravel()] });`. Finally, replace welcome.blade.php with a root Vue component and update app.js to mount it.

Use Inertia.js if you want a single-page-application feel with server-side routing and Laravel’s authentication scaffolding. It’s ideal for admin dashboards or apps where you want to keep Blade’s simplicity for layouts but use Vue for interactive components. For simpler projects or when you only need Vue for isolated components (e.g., modals, forms), stick with Laravel’s default Vite setup and mount Vue components directly in Blade templates.

The core setup is free (Laravel, Vue, Vite, Inertia.js). Hosting on a shared server with PHP 8.2 costs Rs 1,500–3,000/month (~USD 11–23). If you hire a local developer, expect Rs 30,000–60,000 (~USD 225–450) for a basic Vue-Laravel integration (e.g., product catalog with filters). For agencies, rates are Rs 800–1,500/hour (~USD 6–11). No licensing fees apply for open-source tools.

This usually happens when Vite’s dev server isn’t running or the compiled assets aren’t loaded. First, ensure you’ve run `npm install` and `npm run dev`. If using production, run `npm run build`. Check your Blade template includes `@vite(['resources/js/app.js'])` in the head. If the error persists, verify your app.js mounts Vue correctly: `import { createApp } from 'vue'; createApp(App).mount('#app');`. Clear browser cache and Laravel’s view cache with `php artisan view:clear`.

You can technically use Vue 2 with Laravel 12, but it’s not recommended. Laravel’s default Vite setup and Inertia.js are optimized for Vue 3. If you must use Vue 2, install it via `npm install vue@2` and manually configure webpack.mix.js (Laravel Mix) instead of Vite. However, Vue 2 reached end-of-life on December 31, 2023, so you’ll miss security updates and new features. Upgrading to Vue 3 is the better long-term choice.

For simple data, pass props from Blade to Vue using `@json` or `v-bind`. Example: ``. For reactive state, use Laravel’s `ziggy` package to expose named routes to Vue, or create an API endpoint and fetch data with `axios` inside Vue’s `onMounted`. For global state, use Pinia (recommended) or Vuex. Pinia is lighter and works seamlessly with Vue 3: `npm install pinia`, then define stores and access them in components.

For traditional server-rendered apps, use Laravel’s built-in auth scaffolding (`php artisan make:auth`) and enhance forms with Vue. For SPA-like experiences, use Laravel Sanctum or Passport for API authentication. Sanctum is simpler for same-domain apps: install with `composer require laravel/sanctum`, then use `axios` in Vue to call protected routes. For Inertia.js apps, Laravel Breeze provides Vue-ready auth scaffolding out of the box: `composer require laravel/breeze --dev`, then `php artisan breeze:install vue`.

Laravel Mix (webpack-based) was Laravel’s default until Laravel 9. It’s stable but slower, especially for large apps. Vite (used by default in Laravel 10+) is faster due to native ES modules and on-demand compilation. Vite requires fewer config files and supports HMR (hot module replacement) out of the box. For new projects, use Vite. If migrating from Mix, update your package.json scripts, replace webpack.mix.js with vite.config.js, and adjust asset paths in Blade templates.

First, build assets locally with `npm run build`. Upload the entire project to your hosting (e.g., via cPanel File Manager or FTP). Ensure the server runs PHP 8.2+ and Node.js isn’t required in production. Configure your domain’s document root to point to the `public` folder. Set up a MySQL database and update `.env` with the credentials. For Vue components to work, ensure your Blade templates include the compiled assets via `@vite(['resources/js/app.js'])`. If using Inertia.js, verify your server supports the required headers (e.g., `X-Inertia`).

The biggest risk is exposing sensitive data in Vue components. Never hardcode API keys or user data in frontend code. Use Laravel’s API resources to control what data is exposed. For CSRF protection, include the CSRF token in your Blade template (``) and configure axios to send it with every request. Sanitize user input in Laravel before passing it to Vue. For authentication, use Sanctum’s cookie-based auth for same-domain apps to avoid token leakage. Always validate and authorize requests on the server, even if Vue handles client-side validation.

Start with Vite’s built-in optimizations: code-splitting, lazy-loading components, and dynamic imports. Use Laravel’s route caching (`php artisan route:cache`) and config caching (`php artisan config:cache`) in production. For Vue, enable tree-shaking by importing only what you need (e.g., `import { ref } from 'vue'` instead of `import * as Vue`). Implement lazy-loading for routes: `const routes = [{ path: '/dashboard', component: () => import('./pages/Dashboard.vue') }]`. Use Laravel’s queue system for heavy tasks. For images, use Vite’s asset handling or a CDN. Monitor performance with Laravel Debugbar or Vue DevTools.

Yes. Install TypeScript with `npm install typescript @types/node --save-dev`, then create a `tsconfig.json` file. Update vite.config.js to include TypeScript support: `import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue()] });`. Rename your `.js` files to `.ts` and update imports. For Vue components, use ``. Laravel’s Vite plugin works seamlessly with TypeScript. For type safety with Laravel’s API responses, define interfaces in your Vue components or use tools like `laravel-typescript` to generate TypeScript types from your Laravel models.

Place Vue components in `resources/js/components`. For larger apps, group them by feature (e.g., `resources/js/components/auth`, `resources/js/components/products`). Use PascalCase for component filenames (e.g., `ProductCard.vue`). For Inertia.js apps, follow the default structure: `resources/js/Pages` for page components and `resources/js/Components` for shared components. Keep Blade templates in `resources/views` and mount Vue components in them. For global state, use Pinia stores in `resources/js/stores`. Avoid mixing Vue and Blade logic in the same file—keep components self-contained.

Use Vue DevTools (browser extension) for component inspection, state management, and event tracking. For API debugging, use Laravel Telescope (`composer require laravel/telescope --dev`) or Laravel Debugbar. For frontend errors, check the browser’s console and Vite’s dev server output. Use `console.log` or `debugger` statements in Vue components, but remove them before production. For network requests, inspect the "Network" tab in Chrome DevTools. If using Inertia.js, check the `X-Inertia` headers to verify requests are being processed correctly. For build issues, run `npm run dev` with `--debug` flag.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: