Documentation Index Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
Use this file to discover all available pages before exploring further.
Development mode is designed to give you the best developer experience with instant feedback and minimal configuration. When you run your Mizu app in development, it acts as a reverse proxy to your frontend dev server.
How Development Mode Works
In development, Mizu proxies requests to your frontend dev server (usually Vite, webpack-dev-server, or similar):
Browser Request
↓
Mizu Server (http://localhost:3000)
↓
Is it /api/* ?
↙ ↘
Yes No
↓ ↓
Go API Proxy to Dev Server
Handler (http://localhost:5173)
The flow:
Browser requests http://localhost:3000/
Mizu checks if the path starts with /api (or other ignore paths)
If yes → Handle with Go API routes
If no → Proxy to the frontend dev server
Frontend dev server responds with the latest code
Enabling Development Mode
Automatic Detection
The simplest way is to use auto-detection:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeAuto , // Auto-detect mode
Root : "./dist" , // Production build folder
DevServer : "http://localhost:5173" , // Dev server URL
}))
Set the environment variable to enable development:
# Development (default)
MIZU_ENV = development go run cmd/server/main.go
# Or don't set it at all - defaults to dev
go run cmd/server/main.go
Explicit Development Mode
You can explicitly set development mode:
app . Use ( frontend . Dev ( "http://localhost:5173" ))
Or with options:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeDev ,
DevServer : "http://localhost:5173" ,
}))
Hot Module Replacement (HMR)
HMR is what makes modern frontend development so fast. When you save a file, the changes appear instantly in your browser without a full page reload.
How HMR Works
You edit a React component
Vite detects the file change
Vite sends an update via WebSocket
The browser receives the update
Only the changed component re-renders
Your app state is preserved
Mizu’s role:
Proxies the WebSocket connection between browser and Vite
Preserves all HMR functionality
No configuration needed!
What Gets Proxied
Mizu proxies both HTTP and WebSocket connections:
HTTP Requests:
GET / → Proxied to dev server
GET /assets/main.js → Proxied to dev server
GET /src/App.tsx → Proxied to dev server (during HMR)
WebSocket Connections:
ws://localhost:3000/ → Proxied to ws://localhost:5173/
Used for HMR updates
Vite’s HMR protocol passes through unchanged
Dev Server Configuration
Default Ports
Different dev servers use different default ports:
Framework Tool Default Port React Vite 5173 Vue Vite 5173 Svelte Vite 5173 Angular Angular CLI 4200 Next.js Next.js 3000 (conflicts!)
Important: If your frontend dev server runs on port 3000, change either the Mizu port or the frontend port to avoid conflicts.
Configuring Dev Server URL
Match your frontend dev server port:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeAuto ,
DevServer : "http://localhost:4200" , // Angular dev server
}))
Custom Dev Server Timeout
If your dev server is slow to respond:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeDev ,
DevServer : "http://localhost:5173" ,
DevServerTimeout : 60 * time . Second , // Default: 30s
}))
Disabling WebSocket Proxying
If you don’t need HMR (unusual):
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeDev ,
DevServer : "http://localhost:5173" ,
ProxyWebSocket : false , // Disable WebSocket proxy
}))
Ignore Paths
By default, these paths bypass the proxy and go to your Go handlers:
/api - API routes
/health - Health check
/metrics - Metrics endpoint
app . Get ( "/api/users" , handleUsers ) // Handled by Go
app . Get ( "/health" , handleHealth ) // Handled by Go
app . Get ( "/" , ... ) // Proxied to dev server
app . Get ( "/about" , ... ) // Proxied to dev server
Custom Ignore Paths
Add your own paths:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeDev ,
DevServer : "http://localhost:5173" ,
IgnorePaths : [] string { "/api" , "/auth" , "/webhooks" },
}))
Now /auth and /webhooks are handled by Go, not proxied.
Disable Ignore Paths
If you want to proxy everything except explicit routes:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeDev ,
DevServer : "http://localhost:5173" ,
IgnorePaths : [] string {}, // No automatic ignores
}))
// Define API routes BEFORE the frontend middleware
app . Get ( "/api/users" , handleUsers )
// Frontend middleware comes after
app . Use ( frontend . Dev ( "http://localhost:5173" ))
Remember: middleware order matters! Routes defined before the frontend middleware take precedence.
CORS in Development
Mizu automatically adds CORS headers in development mode:
Access-Control-Allow-Origin: *
This allows your frontend dev server to make requests to the Mizu API without CORS issues.
In production , these permissive CORS headers are NOT added. Use the CORS middleware for production CORS configuration.
Error Handling
When the dev server is not running or unreachable, Mizu shows a helpful error page:
┌─────────────────────────────────────────┐
│ 🚨 Unable to connect to dev server │
│ │
│ http://localhost:5173 │
│ │
│ Make sure your frontend dev server │
│ is running: │
│ │
│ For Vite: npm run dev │
│ For Next.js: npm run dev │
│ │
│ [Auto-retrying in 2s...] │
└─────────────────────────────────────────┘
The page automatically retries every 2 seconds, so once you start your dev server, the page loads.
Complete Development Setup
Here’s a complete example:
app/server/app.go
package server
import (
" github.com/go-mizu/mizu "
" github.com/go-mizu/mizu/frontend "
)
func New ( cfg * Config ) * mizu . App {
app := mizu . New ()
// Add API routes BEFORE frontend middleware
app . Get ( "/api/users" , handleUsers )
app . Post ( "/api/users" , createUser )
// Frontend middleware (auto-detects mode)
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeAuto ,
Root : "./dist" ,
DevServer : "http://localhost:" + cfg . DevPort ,
IgnorePaths : [] string { "/api" },
}))
return app
}
app/server/config.go
package server
import " os "
type Config struct {
Port string
DevPort string
Env string
}
func LoadConfig () * Config {
return & Config {
Port : getEnv ( "PORT" , "3000" ),
DevPort : getEnv ( "DEV_PORT" , "5173" ),
Env : getEnv ( "MIZU_ENV" , "development" ),
}
}
func getEnv ( key , fallback string ) string {
if value := os . Getenv ( key ); value != "" {
return value
}
return fallback
}
Running Development
# Terminal 1: Start frontend dev server
cd frontend
npm run dev
# Terminal 2: Start Mizu server
go run cmd/server/main.go
Or use the Makefile:
make dev # Runs both servers in parallel
Development Workflow
A typical development session:
Start both servers
Open browser
Make frontend changes
Edit React/Vue/Svelte components
Changes appear instantly (HMR)
No refresh needed!
Make backend changes
Edit Go files
Stop server (Ctrl+C)
Restart server
Or use air for auto-reload
Test API integration
Call APIs from frontend
Check browser Network tab
Check server logs
Debugging Tips
Check Dev Server is Running
# Should respond with HTML
curl http://localhost:5173
Check Mizu is Proxying
# Should show the same HTML as above
curl http://localhost:3000
Enable Debug Logging
Add the logger middleware to see all requests:
import " github.com/go-mizu/mizu/middlewares/logger "
app . Use ( logger . New ())
app . Use ( frontend . Dev ( "http://localhost:5173" ))
You’ll see logs like:
GET / → 200 (12.3ms) [proxied]
GET /api/users → 200 (2.1ms) [handler]
GET /assets/main.js → 200 (5.2ms) [proxied]
HMR Not Working
Check WebSocket is connected
Open browser DevTools
Go to Network tab → WS (WebSockets)
Should see a connection to ws://localhost:3000
Check Vite config allows external connections
// vite.config.ts
export default {
server: {
hmr: {
clientPort: 3000 , // Mizu's port
}
}
}
Check CORS headers
Network tab should show Access-Control-Allow-Origin: *
Next Steps
Production Mode Learn how production mode optimizes performance
Configuration Explore all configuration options
Troubleshooting Fix common development issues
API Integration Best practices for calling backend APIs