Go-Vite is a powerful CLI tool for generating production-ready desktop applications using Go (backend), React + Vite (frontend), and native webview. It creates a complete, self-contained application architecture in seconds.
- π One Command Setup - Generate a complete project structure instantly
- π¦ Embedded Architecture - Single binary contains frontend, backend, and webview
- β‘ Lightning Fast - Vite for blazing-fast frontend development
- π¨ Modern UI - Tailwind CSS pre-configured with custom theme
- π§ Production Ready - Includes build system, error handling, and logging
- π Extensible - Module system for easy feature addition
- π¦ Module Management - Install, uninstall, and manage local/remote modules
- π₯οΈ Cross-Platform - Build native desktop apps for Windows, macOS, and Linux
- π― Type Safe - TypeScript support out of the box
- π Complete Backend - RESTful API with Gin framework
- π Hot Reload - Development mode with automatic reloading
- Prerequisites
- Installation
- Quick Start
- CLI Commands
- Project Structure
- Development Workflow
- Building for Production
- Configuration
- Module System
- API Development
- Frontend Development
- Deployment
- Troubleshooting
- Best Practices
- Contributing
- License
Before using Go-Vite, ensure you have the following installed:
- Go 1.24 or later (Download)
- Node.js 18.x or later (Download)
- npm or yarn (comes with Node.js)
- Git (for version control)
# Ubuntu/Debian
sudo apt-get install webkit2gtk-4.0-dev
# Fedora
sudo dnf install webkit2gtk3-devel
# Arch
sudo pacman -S webkit2gtk# Xcode Command Line Tools
xcode-select --install- MinGW-w64 or MSYS2 for CGO support
- Windows SDK
go install github.com/guiperry/go-vite@latestgit clone https://github.com/guiperry/go-vite.git
cd go-vite
go build -o go-vite .
sudo mv go-vite /usr/local/bin/go-vite version# Basic usage
go-vite init my-app
# With custom options
go-vite init my-app \
--module github.com/myuser/my-app \
--description "My awesome desktop application" \
--author "Your Name" \
--port 5173 \
--backend-port 8080cd my-appmake depsmake binary./dist/my-appπ That's it! Your desktop application is now running.
Initialize a new Go-Vite project.
Usage:
go-vite init [project-name] [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--module |
-m |
[project-name] |
Go module name |
--description |
-d |
"A Go-Vite desktop application" |
Project description |
--author |
-a |
"" |
Author name |
--port |
-p |
5173 |
Frontend development port |
--backend-port |
-b |
8080 |
Backend API port |
Examples:
# Minimal
go-vite init todo-app
# Full configuration
go-vite init todo-app \
--module github.com/john/todo-app \
--description "A simple todo list application" \
--author "John Doe" \
--port 3000 \
--backend-port 9000Display version information.
go-vite versionInstall a module from a remote repository. Automatically detects whether the current project is a Go or Node.js project and uses the appropriate package manager.
Usage:
go-vite install [module]Examples:
# Install a Go module
go-vite install github.com/gin-gonic/gin
# Install a Node.js package
go-vite install axios
# Install with version constraint (Go)
go-vite install github.com/gin-gonic/gin@v1.9.1Uninstall a module from the current project. Automatically detects the project type and uses the appropriate package manager.
Usage:
go-vite uninstall [module]Examples:
# Uninstall a Go module
go-vite uninstall github.com/gin-gonic/gin
# Uninstall a Node.js package
go-vite uninstall axiosInstall a module from a local directory. Copies the module files to the project's modules directory and registers it for use.
Usage:
go-vite install-local [path]Examples:
# Install from a local directory
go-vite install-local ./my-custom-module
# Install from an absolute path
go-vite install-local /home/user/projects/my-moduleRequirements:
- The source directory must contain either
go.mod(for Go modules) orpackage.json(for Node.js modules) - The module will be copied to
backend/internal/modules/[module-name]
Import and register a local module without copying files. Similar to install-local but checks for existing modules first.
Usage:
go-vite import-module [path]Examples:
# Import a local module
go-vite import-module ./my-module
# Import from an absolute path
go-vite import-module /path/to/moduleNote: If a module with the same name already exists, the command will fail. Use install-local to overwrite existing modules.
my-app/
βββ main.go # Desktop app entry point
βββ go.mod # Root Go module
βββ Makefile # Build automation
βββ README.md # Project documentation
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore rules
βββ .gitattributes # Git attributes
β
βββ backend/ # Go backend service
β βββ go.mod # Backend Go module
β βββ cmd/
β β βββ server/
β β βββ main.go # Backend server entry
β βββ config/
β β βββ config.go # Configuration management
β βββ internal/
β β βββ api/
β β β βββ routes.go # API route definitions
β β β βββ handlers/
β β β β βββ handlers.go # Request handlers
β β β βββ middleware/
β β β βββ cors.go # CORS middleware
β β β βββ logger.go # Logging middleware
β β βββ models/
β β β βββ pipeline.go # Pipeline data model
β β β βββ project.go # Project data model
β β β βββ user.go # User data model
β β βββ modules/
β β β βββ modules.go # Module manager
β β β βββ builtin.go # Built-in modules
β β βββ storage/
β β β βββ database.go # Database layer
β β βββ utils/
β β βββ logger.go # Utility functions
β βββ tests/
β βββ ... # Test files
β
βββ frontend/ # React + Vite frontend
β βββ src/
β β βββ main.tsx # React entry point
β β βββ App.tsx # Main App component
β β βββ index.css # Global styles
β β βββ components/ # Reusable components
β β βββ pages/ # Page components
β β βββ hooks/ # Custom React hooks
β β βββ services/ # API services
β β βββ utils/ # Utility functions
β βββ public/ # Static assets
β βββ index.html # HTML template
β βββ package.json # Node dependencies
β βββ vite.config.js # Vite configuration
β βββ tailwind.config.js # Tailwind CSS config
β βββ postcss.config.js # PostCSS config
β βββ .eslintrc.cjs # ESLint rules
β βββ .prettierrc # Prettier config
β
βββ bin/ # Backend binary (temp)
βββ dist/ # Final application binary
βββ my-app # Single executable
Run frontend and backend separately for hot-reload during development:
Terminal 1 - Frontend:
cd frontend
npm run devTerminal 2 - Backend:
cd backend
go run ./cmd/serverTerminal 3 - Build Desktop App:
make binary
./dist/my-app| Command | Description |
|---|---|
make all |
Clean, install deps, and build everything |
make deps |
Install all dependencies (Go + Node.js) |
make deps-go |
Install Go dependencies only |
make deps-node |
Install Node.js dependencies only |
make frontend |
Build React frontend |
make backend |
Build Go backend |
make binary |
Build unified desktop application |
make clean |
Remove build artifacts |
make test |
Run all tests |
make run |
Build and run the application |
# Install dependencies
make deps
# Build everything
make all
# Run the application
make run
# Clean and rebuild
make clean && make binary# Build for your current platform
make binary# Linux
GOOS=linux GOARCH=amd64 make binary
# Windows
GOOS=windows GOARCH=amd64 make binary
# macOS (Intel)
GOOS=darwin GOARCH=amd64 make binary
# macOS (Apple Silicon)
GOOS=darwin GOARCH=arm64 make binaryFor smaller binary sizes:
# Build with optimizations
go build -ldflags="-s -w" -o dist/my-app .
# Further compress with UPX (optional)
upx --best --lzma dist/my-appCreate a .env file in the project root:
# Frontend
VITE_API_URL=http://localhost:8080
VITE_APP_NAME=My Application
VITE_APP_VERSION=1.0.0
# Backend
PORT=8080
LOG_LEVEL=info
# Database (if needed)
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
# API Keys
API_KEY=your_api_key_hereEdit backend/config/config.go:
type Config struct {
FrontendPort int
BackendPort int
LogLevel string
DatabaseURL string
APIKey string
}Edit frontend/vite.config.js:
export default defineConfig({
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
},
},
},
})The generated project includes an extensible module system for organizing business logic. Go-Vite also provides CLI commands for managing both remote and local modules.
Go-Vite provides powerful module management capabilities:
# Install from remote repositories
go-vite install github.com/gin-gonic/gin
go-vite install axios
# Uninstall modules
go-vite uninstall github.com/gin-gonic/gin
go-vite uninstall axios# Install from local directory (copies files)
go-vite install-local ./my-custom-module
# Import without copying (references existing location)
go-vite import-module ./my-existing-moduleLocal modules are automatically:
- Detected as Go or Node.js modules
- Copied to
backend/internal/modules/[module-name] - Registered in the module system
- Available for use in your application
1. Create module file: backend/internal/modules/mymodule.go
package modules
type MyModule struct {
config map[string]interface{}
}
func NewMyModule() *MyModule {
return &MyModule{
config: make(map[string]interface{}),
}
}
func (m *MyModule) Name() string {
return "mymodule"
}
func (m *MyModule) Execute(input map[string]interface{}) (map[string]interface{}, error) {
// Your business logic here
result := map[string]interface{}{
"status": "success",
"data": input,
}
return result, nil
}
func (m *MyModule) Validate(config map[string]interface{}) error {
// Validation logic
return nil
}2. Register the module: backend/internal/modules/builtin.go
func LoadBuiltinModules(manager *Manager) {
manager.Register("example", &ExampleModule{})
manager.Register("mymodule", NewMyModule())
}3. Use in handlers: backend/internal/api/handlers/handlers.go
func ExecuteModule(c *gin.Context) {
moduleManager := c.MustGet("modules").(*modules.Manager)
module, exists := moduleManager.Get("mymodule")
if !exists {
c.JSON(404, gin.H{"error": "Module not found"})
return
}
input := map[string]interface{}{
"data": "test",
}
result, err := module.Execute(input)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, result)
}1. Define route: backend/internal/api/routes.go
func SetupRoutes(router *gin.Engine) {
v1 := router.Group("/api/v1")
{
v1.GET("/users", handlers.ListUsers)
v1.POST("/users", handlers.CreateUser)
v1.GET("/users/:id", handlers.GetUser)
}
}2. Create handler: backend/internal/api/handlers/handlers.go
func ListUsers(c *gin.Context) {
users := []map[string]interface{}{
{"id": 1, "name": "John"},
{"id": 2, "name": "Jane"},
}
c.JSON(200, gin.H{"users": users})
}
func CreateUser(c *gin.Context) {
var user map[string]interface{}
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(201, gin.H{"message": "User created", "user": user})
}# Health check
curl http://localhost:8080/health
# List items
curl http://localhost:8080/api/v1/items
# Create item
curl -X POST http://localhost:8080/api/v1/items \
-H "Content-Type: application/json" \
-d '{"name":"Test Item"}'1. Create component: frontend/src/components/Button.tsx
import React from 'react';
interface ButtonProps {
children: React.ReactNode;
onClick?: () => void;
variant?: 'primary' | 'secondary';
}
export const Button: React.FC<ButtonProps> = ({
children,
onClick,
variant = 'primary'
}) => {
const baseClasses = 'px-6 py-3 rounded-lg font-semibold transition-all';
const variantClasses = variant === 'primary'
? 'bg-gradient-to-r from-brand-600 to-blue-600 hover:from-brand-500'
: 'bg-slate-700 hover:bg-slate-600';
return (
<button
onClick={onClick}
className={`${baseClasses} ${variantClasses}`}
>
{children}
</button>
);
};2. Use component: frontend/src/App.tsx
import { Button } from './components/Button';
function App() {
return (
<div>
<Button onClick={() => console.log('Clicked!')}>
Click Me
</Button>
</div>
);
}1. Create service: frontend/src/services/api.ts
const API_BASE = import.meta.env.VITE_API_URL || '/api/v1';
export const api = {
async get(endpoint: string) {
const response = await fetch(`${API_BASE}${endpoint}`);
return response.json();
},
async post(endpoint: string, data: any) {
const response = await fetch(`${API_BASE}${endpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return response.json();
},
};2. Use in component:
import { useEffect, useState } from 'react';
import { api } from './services/api';
function ItemsList() {
const [items, setItems] = useState([]);
useEffect(() => {
api.get('/items').then(data => setItems(data.items));
}, []);
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}The project comes with Tailwind CSS pre-configured with a custom brand color palette:
// Use brand colors
<div className="bg-brand-500 text-white">
Brand colored background
</div>
// Gradient text
<h1 className="bg-gradient-to-r from-brand-400 to-blue-400 bg-clip-text text-transparent">
Gradient Text
</h1>
// Custom animations
<div className="animate-fade-in">
Fades in on load
</div>1. Build for target platform:
# macOS
GOOS=darwin GOARCH=amd64 make binary
# Windows
GOOS=windows GOARCH=amd64 make binary
# Linux
GOOS=linux GOARCH=amd64 make binary2. Package the binary:
macOS:
# Create .app bundle
mkdir -p MyApp.app/Contents/MacOS
cp dist/my-app MyApp.app/Contents/MacOS/
# Add Info.plist and iconWindows:
# Use tools like NSIS or Inno Setup
# Or simply distribute the .exeLinux:
# Create AppImage, Snap, or Flatpak
# Or distribute as binary with .desktop fileIf you want to deploy as a web app instead:
# Build frontend only
cd frontend && npm run build
# Deploy dist/ folder to:
# - Netlify
# - Vercel
# - GitHub Pages
# - AWS S3Issue: Blank window or "Failed to load" error
Solution:
# Linux: Install webkit2gtk
sudo apt-get install webkit2gtk-4.0-dev
# macOS: Install Xcode Command Line Tools
xcode-select --install
# Windows: Ensure WebView2 Runtime is installedIssue: CGO_ENABLED=1 required but not set
Solution:
# Install build tools
# Ubuntu/Debian
sudo apt-get install build-essential
# macOS
xcode-select --install
# Windows
# Install MinGW-w64 or MSYS2Issue: bind: address already in use
Solution:
# Find and kill process using port
lsof -ti:8080 | xargs kill -9
# Or change port in .env
echo "PORT=9000" >> .envIssue: API calls returning 404 or connection refused
Solution:
- Check
vite.config.jsproxy settings - Ensure backend is running on correct port
- Verify CORS middleware is enabled
- Check
.envfile has correctVITE_API_URL
Issue: cannot find package during Go build
Solution:
# Clean and reinstall
rm -rf go.sum
go clean -modcache
go mod download
go mod tidyEnable verbose logging:
# Backend
LOG_LEVEL=debug go run ./cmd/server
# Frontend
DEBUG=vite:* npm run dev- Keep business logic in modules - Don't put logic in handlers
- Use consistent naming - Follow Go and React conventions
- Write tests - Aim for >80% coverage
- Document APIs - Use OpenAPI/Swagger for backend
- Type everything - Use TypeScript strictly
# Go
go fmt ./...
go vet ./...
golangci-lint run
# Frontend
npm run lint
npm run format- Never commit secrets - Use
.envfiles - Validate all inputs - Backend and frontend
- Use HTTPS in production
- Implement rate limiting
- Keep dependencies updated
# Update Go dependencies
go get -u ./...
go mod tidy
# Update Node dependencies
npm update
npm audit fix- Optimize images - Use WebP format
- Lazy load components - React.lazy() and Suspense
- Bundle splitting - Configure Vite code splitting
- Database indexing - Add indexes for common queries
- Enable compression - gzip middleware in production
We welcome contributions! Here's how to get started:
# Fork and clone
git clone https://github.com/guiperry/go-vite.git
cd go-vite
# Create branch
git checkout -b feature/amazing-feature
# Make changes and test
go build .
./go-vite init test-app
# Commit and push
git commit -m "Add amazing feature"
git push origin feature/amazing-feature- Update README.md with details of changes
- Add tests for new functionality
- Ensure all tests pass
- Update version numbers following SemVer
- Submit PR with clear description
When reporting issues, include:
- Go version:
go version - Node version:
node --version - Operating system
- Error messages and logs
- Steps to reproduce
Check out example projects:
- Support for additional frontend frameworks (Vue, Svelte)
- Built-in database migrations
- Authentication scaffolding
- Docker deployment templates
- CI/CD pipeline templates
- Plugin system for custom generators
- GUI configuration tool
- Auto-update mechanism for apps
This project is licensed under the MIT License - see the LICENSE file for details.
- Webview - For the native webview library
- Gin - For the excellent web framework
- Vite - For the blazing-fast build tool
- Cobra - For CLI framework
- All contributors and users of this project
- GitHub Issues: Report bugs or request features
- Discussions: Community forum
- Twitter: @govitecli
- Discord: Join our server
Website β’ Documentation β’ Blog
Made with β€οΈ by the Go-Vite team