The starter kit’s Vite setup works on day one. Then someone adds an alias and deletes a plugin, someone else puts a secret in a VITE_ variable, and production loads JavaScript from a laptop. Here are the three edits that go wrong, and the fix for each.
TL;DR
npm run devwritespublic/hot;npm run buildwritespublic/build. Never deploypublic/hot.@points atresources/js. Add the alias beside the kit’s plugins; don’t replace them.- Every
VITE_variable is public. Secrets stay in Laravel’s.env, read on the server. - Restart
npm run dev(or rebuild) after changing.env.
laravel new with the Vue starter kit already wires Vite, the Vue plugin, and the Laravel plugin. You do not replace vite.config.ts to “add Vue”. This page is the three edits that go wrong after that: imports, environment variables, and the dev server file.
Production builds are the deploy guide. Sail’s HMR host is Sail. The app those assets belong to is Inertia, a SPA, or Nuxt.
Dev and build#
| Command | Writes | Browser loads assets from |
|---|---|---|
npm run dev | public/hot | The Vite dev server (your machine) |
npm run build | public/build | Your Laravel app |
npm run dev writes public/hot and serves assets from the Vite process. Laravel reads that file and points the browser at the dev server. That is what you want on your machine.
npm run build writes public/build and removes the need for public/hot.
Gotcha: public/hot on the server
If public/hot is on the server, every page loads JavaScript from the URL in that file, which is your laptop. Delete it. Do not commit it. The deploy guide is the checklist around that file.
Restart npm run dev after .env changes. Vite reads VITE_* at startup and inlines them at build time. A key you add later is not in the bundle until you build again.
Check before you deploy
git ls-files public/hot && echo "remove public/hot from git" || echo "ok"The @ alias#
The kit aliases @ to resources/js. If a fresh config lost it, put it back beside the plugins. Do not remove laravel(), Vue, Tailwind, or Wayfinder while you add the alias.
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
export default defineConfig({
// plugins: keep the kit's laravel(), vue(), tailwindcss(), and wayfinder()
resolve: {
alias: {
"@": fileURLToPath(new URL("./resources/js", import.meta.url)),
},
},
});Breaks when files move, then Same path everywhere:
import PostForm from "../../pages/posts/Form.vue";import PostForm from "@/pages/posts/Form.vue";A relative ../../pages/posts/Form.vue works until a file moves. The alias is the path the rest of the kit already uses, including Wayfinder imports under @/actions.
What VITE_ exposes#
Only variables whose names start with VITE_ are available as import.meta.env.VITE_.... That is a browser bundle. Anyone who can load the JavaScript can read them.
const key = import.meta.env.VITE_REVERB_APP_KEY;Safe as VITE_ (public) | Never VITE_ (secret) |
|---|---|
| Reverb app key, host and port | Database password |
| The Laravel origin | GitHub client secret |
| App name | Mail password, API secrets |
Heads up: a VITE_ prefix publishes it
A Reverb app key is public by design. A database password, a GitHub client secret, or a mail password is not. Those stay in Laravel’s .env and are read with env() or config() on the server. Prefixing a secret with VITE_ so a Vue page can “just use it” publishes the secret.
The Laravel origin, the Reverb host, and the Reverb port are the usual public values. Set them before npm run build. The Reverb guide is why the key has to be in the bundle at all.
Where this stops#
Vite does not authenticate the API. Cookie setup for a separate dev server on port 5173 is CORS and Sanctum. Same-origin Inertia, opened through the Laravel URL, does not need that CORS file.
Recap#
public/hotis for your machine only; production usespublic/build.- Restore
@beside the kit’s plugins, never instead of them. VITE_variables ship to every visitor; secrets stay server-side.- Restart or rebuild after
.envchanges.
FAQ#
Why does my production Laravel site try to load assets from localhost:5173?
A public/hot file was deployed. Delete it; with it present, Laravel points the browser at the dev server URL inside it.
Why is my new VITE_ variable undefined?
Vite reads VITE_* variables at startup and inlines them at build time. Restart npm run dev, or run npm run build again.
Can I put an API secret in a VITE_ variable?
No. Anything prefixed VITE_ ends up in the JavaScript bundle that every visitor downloads. Keep secrets in Laravel config.
Next steps#
- Deploy a Laravel + Vue app: the build and the
public/hotchecklist. - Laravel Sail with Vue and Vite: HMR inside Docker.
- Typed routes with Wayfinder: the
@/actionsimports. - Laravel docs: Vite



