Inertia HMR & Vite

Full Hot Module Replacement (HMR) with React Fast Refresh when using Inertia + Vite. Edit inertia/ files and see changes instantly.

How it works

When you run nimbus serve on an Inertia app:

  • Nimbus runs npm run build once (if node_modules exists)
  • Vite dev server starts in the background on port 5173
  • VITE_DEV=1 is set so the layout loads from Vite
  • Air runs the Go app on port 3333
  • Vite logs are hidden to keep the terminal clean

nimbus serve behavior

CommandVite dev serverHMRVite logs
nimbus serveYes (background)YesHidden
nimbus serve -wYes (background)YesHidden

React preamble

Because the HTML is served by Nimbus (port 3333) and not Vite, the @vitejs/plugin-react can't inject its preamble. We add it manually in the layout when viteDev is true:

<script type="module">
  import RefreshRuntime from 'http://localhost:5173/@react-refresh'
  RefreshRuntime.injectIntoGlobalHook(window)
  window.$RefreshReg$ = () => {}
  window.$RefreshSig$ = () => (type) => type
  window.__vite_plugin_react_preamble_installed__ = true
</script>

This must appear before the app script. Without it, you'll see: @vitejs/plugin-react can't detect preamble.

Vite config

Ensure vite.config.js builds to public/build with stable filenames (no hash):

build: {
  outDir: "public/build",
  manifest: true,
  rollupOptions: {
    input: "inertia/app.tsx",
    output: {
      entryFileNames: "assets/[name].js",
      chunkFileNames: "assets/[name].js",
      assetFileNames: "assets/[name].[ext]",
    },
  },
},

Troubleshooting

HMR not working: Ensure you run nimbus serve (not just go run main.go). Check that Vite is on port 5173.

Preamble error: Verify the preamble script block is in the layout and loads before the app script.

Build fails: Run npm install and npm run build before nimbus serve.

See Vite logs: Run npm run dev in a separate terminal.