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: August 2026

Integrating a modern JavaScript framework into a PHP backend often feels like maintaining two separate applications, but the right tooling eliminates that friction. This Vue with Laravel Setup Complete Guide provides the exact configuration steps needed to run Vue 3 alongside Laravel 12 using Vite 6.x in 2026. Whether you are building a single-page application or enhancing server-rendered views, understanding the distinction between Inertia.js and pure API modes is critical for long-term maintainability. For teams evaluating their stack, I also cover how this compares to other approaches in my article on Laravel Livewire for beginners, which helps clarify when to choose client-side reactivity versus server-driven rendering.

How do you configure Vite for Vue with Laravel Setup Complete Guide?

In 2026, Laravel Mix is officially deprecated for new projects. Vite is the default asset bundler, offering significantly faster Hot Module Replacement (HMR) and build times. Configuring it correctly prevents the most common "blank screen" and HMR issues developers face during initial setup.

Installing Core Dependencies

Start with a fresh Laravel 12 installation. Ensure your Node.js version is 22 LTS (Jod) or higher, as Vite 6.x requires modern Node features. Run the following command to install Vue and the necessary Vite plugin:

npm install vue@latest @vitejs/plugin-vue
npm install -D sass

Note that we explicitly install sass as a dev dependency. Many Vue components rely on SCSS preprocessing, and omitting this causes silent build failures or runtime errors when importing style blocks.

Configuring vite.config.js

The vite.config.js file at your project root controls the build pipeline. A common mistake is forgetting to alias the @ symbol or misconfiguring the input paths. Here is a production-ready configuration:

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 setting is vital. Without it, Vue’s compiler may attempt to resolve image URLs as JavaScript modules rather than letting Vite handle them as static assets. This single line saves hours of debugging broken images in production builds.

Vue SFC.vue FilesVite + PluginTransform & BundleBlade Template@vite DirectiveBrowserHMR / Prod Assets
Vite processes Vue Single File Components and injects optimized assets into Laravel Blade templates via the @vite directive.

Bootstrapping the Vue Application

Your entry point, typically resources/js/app.js, must create and mount the Vue instance. In 2026, always use the Composition API with createApp:

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

const app = createApp(App);

app.mount('#app');

Ensure your primary Blade layout contains a matching container: <div id="app"></div>. Also verify that @vite(['resources/css/app.css', 'resources/js/app.js']) appears in your <head> tag. Using the old mix() helper will fail silently or throw deprecation warnings in Laravel 12.

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

This architectural decision defines your development velocity and deployment complexity. Both approaches are valid, but they serve different business needs. On legal-tech portals like Court Marriage In Nepal, I have used both patterns depending on whether the priority was SEO-rich content pages or complex authenticated dashboards.

CriteriaInertia.js AdapterStandalone SPA (Sanctum)
RoutingServer-side (Laravel routes)Client-side (Vue Router)
State ManagementProps passed from controllersPinia / Vuex + API calls
AuthenticationSession-based (automatic)Token/Cookie via Sanctum
SEO ComplexityLow (SSR optional)High (requires SSR or prerendering)
API ReusabilityLow (tightly coupled)High (decoupled JSON API)
Best ForInternal tools, B2B dashboardsMobile apps, public marketplaces

When Inertia.js Wins

Inertia allows you to build a modern Vue frontend without building an API. You return Inertia responses directly from Laravel controllers. This eliminates the need for API versioning, serialization resources, and token management. For projects where the web interface is the only consumer, this reduces boilerplate by approximately 40%. If you are exploring admin panels specifically, my Filament admin panel tutorial offers an alternative that requires zero Vue code, but Inertia remains superior when custom UI is non-negotiable.

When Standalone SPA Wins

If you plan to release a mobile app, offer a public API, or have multiple frontend consumers, decouple immediately. Use Laravel Sanctum for cookie-based authentication for the web SPA and token auth for mobile. This forces disciplined API design early. The tradeoff is increased complexity: you must handle loading states, error boundaries, and route guards entirely in Vue. Refer to Laravel API best practices before committing to this path to avoid creating unmaintainable endpoints.

Start ProjectNeed Public/Mobile API?NoYesUse Inertia.jsMonolith DX, Fast DevStandalone SPASanctum + Vue RouterServer Routes OnlyAPI + Client Routing
Decision framework for selecting Inertia.js versus a standalone Vue SPA based on API requirements and team structure.

What are the common Vue with Laravel Setup Complete Guide pitfalls in 2026?

Even experienced developers encounter recurring issues when upgrading to Laravel 12 and Vite 6. These problems rarely appear in documentation but dominate support forums and production debugging sessions.

  • HMR Not Working Over Network: When developing on a remote server or Docker container, Vite defaults to localhost. Add server: { hmr: { host: 'your-domain.test' } } to your Vite config. Without this, changes save but never reflect in the browser.
  • Missing CSRF Token in SPA Requests: For standalone SPAs, ensure /api/csrf-cookie is called before any mutating request. Inertia handles this automatically; manual setups do not. Missing this results in persistent 419 errors.
  • TypeScript Configuration Drift: If using TypeScript, your tsconfig.json must include "types": ["vite/client"]. Otherwise, IDEs cannot resolve import.meta.env or asset imports, leading to false-positive errors.
  • Production Build Fails on CI: Ensure npm ci runs instead of npm install in GitLab CI or GitHub Actions. Also verify that NODE_ENV=production is set during the build step; some plugins behave differently in development mode.
  • Vue DevTools Not Connecting: In production builds, Vue strips devtools hooks. During local development, if DevTools shows "No Vue instance detected," check that you are not accidentally serving cached production assets. Clear public/build/ and restart Vite.

Handling Environment Variables Correctly

Vite exposes environment variables prefixed with VITE_ only. A frequent security issue occurs when developers expose sensitive keys like MIX_PUSHER_APP_KEY (legacy naming) or unprefixed variables. Audit your .env file regularly. Only VITE_APP_URL, VITE_API_ENDPOINT, and similar public values should be accessible in Vue code. Server secrets must remain in PHP-only variables.

How do you deploy Vue with Laravel applications to production?

Deployment strategy depends on your hosting environment. On shared EC2 instances running multiple sister sites like notarykathmandu.com and translationnepal.com, I use Deployer 7 with zero-downtime symlinked releases. The key principle: never run npm install or npm run build on the production server.

The Artifact-Based Deployment Pattern

  1. Build Locally or in CI: Compile assets in a clean environment matching production Node version (22 LTS).
  2. Commit or Upload Artifacts: Either commit public/build/ to version control (acceptable for small teams) or upload as CI artifacts.
  3. Symlink Releases: Deployer swaps the current symlink atomically. PHP-FPM reloads opcache automatically.
  4. Verify Manifest: Check that public/build/manifest.json exists and references hashed filenames. Missing manifest causes 404s on all assets.

This approach eliminates Node.js as a production dependency. Servers need only PHP, Nginx/Apache, and Redis. It also ensures deterministic builds—the exact bytes tested in staging are what users receive.

CI Runnernpm ci && npm run buildArtifact Storepublic/build/Deployer 7Atomic Symlink SwapProductionPHP-FPM Reload⚠ Never Build on Production ServerAvoids Node dependency, ensures deterministic output
Artifact-based deployment keeps Node.js off production servers and guarantees consistent builds across environments.

Cache Busting and CDN Considerations

Vite automatically hashes filenames in production. Your Nginx or Apache configuration must serve these files with long-lived cache headers (Cache-Control: public, max-age=31536000). The HTML document referencing them should have no-cache so browsers always fetch the latest manifest. If using Cloudflare or AWS CloudFront, purge the cache only on manifest.json changes—not individual assets. This reduces origin load significantly for Nepal-based clients with limited bandwidth.

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

Before committing to Vue, validate it against alternatives. The ecosystem has matured, and the "best" choice depends on team skills and project constraints. For Nepali businesses with tight budgets, developer availability matters as much as technical merit.

  • Livewire: Zero JavaScript required. Ideal for CRUD-heavy internal tools where hiring Vue specialists is difficult. Tradeoff: less control over complex interactions. See Livewire tutorial for comparison.
  • React + Inertia: Larger talent pool globally, but steeper learning curve for PHP-native teams. Better library ecosystem for data visualization.
  • Svelte + Laravel: Smaller bundle sizes, simpler syntax. Fewer packages and community resources. Risky for mission-critical commercial projects.
  • HTMX: Minimal JS footprint. Excellent for progressive enhancement. Poor fit for dashboard-style applications requiring persistent client state.

Vue strikes a balance: gentle learning curve for PHP developers transitioning to frontend, strong TypeScript support, and excellent Laravel integration via official packages. For agencies serving diverse clients—from law firms needing document portals to e-commerce platforms—it offers the widest utility per skill unit invested.

Migrating Legacy Mix Projects

If maintaining older Laravel 10/11 projects still on Mix, migrate incrementally. Replace mix() calls with @vite one template at a time. Keep both bundlers running temporarily if necessary, but prioritize completing the switch before upgrading to Laravel 12. Mix support is community-maintained now and receives no security patches. Budget 2–4 hours per medium-sized project for migration testing.

Next Steps for Your Vue with Laravel Setup Complete Guide Implementation

A correct initial setup prevents months of technical debt. Start with Vite 6.x and Vue 3.5+ on Laravel 12, decide deliberately between Inertia and standalone SPA based on actual API needs, and adopt artifact-based deployments from day one. Avoid copying outdated tutorials referencing Mix or Vue 2 Options API patterns. Test HMR thoroughly in your specific development environment before writing feature code. If your project involves complex backend logic alongside the frontend, review modern Laravel architecture best practices to ensure your foundation supports growth. Ready to implement? Reach out via contact me for architecture review or hands-on setup assistance tailored to your infrastructure.

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

Quick Contact Options
Choose how you want to connect me: