Skip to content

Developing Plugins

You can extend Web.Casa by developing custom plugins. A plugin is a Go package that implements the Plugin interface and is compiled into the Web.Casa binary.

  • Go (version matching Web.Casa’s go.mod)
  • Familiarity with the Gin web framework (used for routing)
  • React (for frontend components)
  • Understanding of the Plugin System architecture

Create a directory under plugins/ (at the project root) with your plugin name:

plugins/myplugin/
myplugin.go # Plugin struct and lifecycle methods
handler.go # HTTP handlers
service.go # Business logic
model.go # Database models

Your plugin struct must implement these lifecycle methods:

type MyPlugin struct {
ctx *plugin.Context
db *gorm.DB
}
func (p *MyPlugin) Metadata() plugin.Metadata {
return plugin.Metadata{
Name: "myplugin",
Version: "1.0.0",
Description: "My custom plugin",
Dependencies: []string{"docker"}, // optional
}
}
func (p *MyPlugin) Init(ctx *plugin.Context) error {
p.ctx = ctx
p.db = ctx.DB
// Auto-migrate database tables
// Register event subscriptions
return nil
}
func (p *MyPlugin) Start() error {
// Start background processes
return nil
}
func (p *MyPlugin) Stop() error {
// Clean shutdown
return nil
}

Routes are registered using the Gin router group provided through the CoreAPI. Routes are mounted under /api/plugins/<plugin-name>/:

func (p *MyPlugin) RegisterRoutes(group *gin.RouterGroup) {
group.GET("/items", p.handleListItems)
group.POST("/items", p.handleCreateItem)
group.GET("/items/:id", p.handleGetItem)
group.PUT("/items/:id", p.handleUpdateItem)
group.DELETE("/items/:id", p.handleDeleteItem)
}

Authentication and authorization middleware are automatically applied to plugin routes.

Notify other plugins when something happens:

p.ctx.EventBus.Publish("myplugin.item.created", map[string]interface{}{
"id": item.ID,
"name": item.Name,
})

React to events from other plugins or the core system:

p.ctx.EventBus.Subscribe("container.started", func(e plugin.Event) {
// Handle container start event
})

Common events to subscribe to:

EventSourcePayload
container.startedDocker pluginContainer ID, name
container.stoppedDocker pluginContainer ID, name
host.createdReverse ProxyHost ID, domain
backup.completedBackup pluginBackup ID, size
project.deployedDeploy pluginProject ID, status

Use the ConfigStore to persist plugin settings without direct database access:

// Write a setting
p.ctx.ConfigStore.Set("myplugin", "api_url", "https://example.com")
// Read a setting
value := p.ctx.ConfigStore.Get("myplugin", "api_url")

Settings stored in the ConfigStore are automatically exposed in the Web.Casa settings UI for user configuration.

The plugin Context provides access to shared system services:

ServiceAccess MethodPurpose
Databasectx.DBGORM database connection
Event Busctx.EventBusPublish and subscribe to events
Config Storectx.ConfigStoreScoped key-value settings
Loggerctx.LoggerStructured logging

After developing your plugin, register it in the plugin loader so Web.Casa discovers it at startup:

// In the plugin registration file
pluginManager.Register(&myplugin.MyPlugin{})
  • Write unit tests for your service logic
  • Test HTTP handlers using Go’s httptest package
  • Test event subscriptions by publishing mock events
  • Use existing built-in plugins as reference implementations

Tip: See the Architecture Guide for detailed code structure conventions, naming patterns, and best practices.