gui/docs/ref/wails-v3/contributing/extending-wails.mdx

247 lines
5.7 KiB
Text
Raw Permalink Normal View History

---
title: Extending Wails
description: Practical guide to adding new features and platforms to Wails v3
sidebar:
order: 8
---
> Wails is designed to be **hackable**.
> Every major subsystem lives in Go code you can read, modify, and ship.
> This page shows _where_ to start and _how_ to stay cross-platform when you:
* Add a **Service** (file server, KV store, custom IPC…)
* Create a **new CLI command** (`wails3 <foo>`)
* Extend the **Runtime** (window API, dialogs, events)
* Introduce a **Platform capability** (Wayland, Apple Vision OS…)
* Keep **cross-platform compatibility** without drowning in `//go:build` tags
---
## 1. Adding a Service
Services are background Go components exposed to apps via the `application.Context`.
```
internal/service/
├── template/ # Boilerplate for new services
│ ├── template.go
│ └── README.md
└── service.go # Registration + lifecycle interfaces
```
### 1.1 Define the Service
```go
package chat
type Service struct {
messages []string
}
func New() *Service { return &Service{} }
func (s *Service) Send(msg string) string {
s.messages = append(s.messages, msg)
return "ok"
}
```
### 1.2 Implement `service.Service`
```go
func (s *Service) Init(ctx *application.Context) error { return nil }
func (s *Service) Shutdown() error { return nil }
```
### 1.3 Register Generator
*Add to* `internal/generator/collect/services.go`
```go
services.Register("chat", chat.New)
```
> Now `wails3 generate` emits bindings so JS can call
> `window.backend.chat.Send("hi")`.
### 1.4 Ship an Example
Copy `v3/examples/services/` and adjust.
---
## 2. Writing a New CLI Command
CLI logic lives under `internal/commands/`.
Each command is **one file** that mounts itself in `init()`.
### 2.1 Create the File
`v3/internal/commands/hello.go`
```go
package commands
import (
"github.com/spf13/cobra"
)
func init() {
Add(&cobra.Command{
Use: "hello",
Short: "Prints Hello World",
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Println("Hello Wails!")
return nil
},
})
}
```
`Add()` registers with the root in `cmd/wails3/main.go`.
### 2.2 Re-compile CLI
```
go install ./v3/cmd/wails3
wails3 hello
```
If your command needs **Taskfile** integration, reuse helpers in
`internal/commands/task_wrapper.go`.
---
## 3. Modifying the Runtime
Common reasons:
* New window feature (`SetOpacity`, `Shake`, …)
* Extra dialog (`ColorPicker`)
* System-level API (screen brightness)
### 3.1 Public API
Add to `pkg/application/window.go`:
```go
func (w *WebviewWindow) SetOpacity(o float32) {
w.ctx.Call("window:setOpacity", o)
}
```
### 3.2 Message Processor
Create `messageprocessor_window_opacity.go`:
```go
const MsgSetOpacity = "window:setOpacity"
func init() { register(MsgSetOpacity, handleSetOpacity) }
func handleSetOpacity(ctx *Context, params json.RawMessage) ([]byte, error) {
var req struct {
ID uint64 `json:"id"`
Opacity float32 `json:"o"`
}
json.Unmarshal(params, &req)
return nil, runtime.SetOpacity(req.ID, req.Opacity)
}
```
### 3.3 Platform Implementation
```
internal/runtime/
webview_window_darwin.go
webview_window_linux.go
webview_window_windows.go
```
Add `SetOpacity()` to each, guarded by build tags.
If a platform cant support it, return `ErrCapability`.
### 3.4 Capability Flag
Expose via `internal/capabilities`.
```go
const CapOpacity = "window:opacity"
```
Runtime files `*_darwin.go` etc. should `registerCapability(CapOpacity)` when
successfully initialised.
Apps can query:
```go
if application.HasCapability(application.CapOpacity) { ... }
```
---
## 4. Adding New Platform Capabilities
Example: **Wayland** clipboard on Linux.
1. Fork `internal/runtime/clipboard_linux.go`.
2. Split file:
* `clipboard_linux_x11.go` → `//go:build linux && !wayland`
* `clipboard_linux_wayland.go` → `//go:build linux && wayland`
3. Add CLI flag `--tags wayland` in `internal/commands/dev.go`
(`goEnv.BuildTags += ",wayland"`).
4. Document in **Asset Server** & README.
> Keep default build tags minimal; reserve opt-in tags for niche features.
---
## 5. Cross-Platform Compatibility Checklist
| ✅ Step | Why |
|---------|-----|
| Provide **every** public method in all platform files (even if stub) | Keeps build green on all OS/arch |
| Gate platform specifics behind **capabilities** | Let apps degrade gracefully |
| Use **pure Go** first, CGO only when needed | Simplifies cross-compiles |
| Test with `task matrix:test` | Runs `go test ./...` on linux/mac/windows in Docker |
| Document new build tags in `docs/getting-started/installation.mdx` | Users must know flags |
---
## 6. Debug Builds & Iteration Speed
* `wails3 dev -tags debug` adds extra log hooks (`logger_dev*.go`).
* Use `task reload` to rebuild runtime without restarting the whole app.
* Race detector: `wails3 dev -race` (see `pkg/application/RACE.md`).
---
## 7. Upstream Contributions
1. Open an **issue** to discuss the idea & design.
2. Follow the techniques above to implement.
3. Add:
* Unit tests (`*_test.go`)
* Example (`v3/examples/<feat>/`)
* Docs (this file or API reference)
4. Ensure `go vet`, `golangci-lint`, and CI matrix pass.
---
### Quick Links
| Area | Location |
|------|----------|
| Services framework | `internal/service/` |
| CLI core | `internal/commands/` |
| Runtime per-OS | `internal/runtime/` |
| Capability helpers| `internal/capabilities/` |
| Taskfile DSL | `tasks/Taskfile.yml` |
| Dev matrix tests | `tasks/events/generate.go` |
---
You now have a **roadmap** for bending Wails to your will—add services, sprinkle
CLI magic, hack the runtime, or bring entirely new OS features.
Happy extending!