Quickstart
This walkthrough takes you from an empty directory to a working admin panel with a generated resource — in about five minutes, using SQLite so nothing else needs to be installed.
1. Install the CLI
go install github.com/imfiqhan/steward/cmd/steward@latestThe steward binary only generates code — projects it creates are plain
Go programs that run themselves.
2. Create a project
steward new myadmin --module example.com/myadmin --db sqlite
cd myadmin
go mod tidyThis scaffolds a small, readable tree:
myadmin/
├── main.go # steward.CLI wiring: serve, worker, migrate, …
├── app/app.go # builds the Admin (DB, config, resource registry)
├── resources/ # one file per resource + registry.go
├── migrations/ # your app's migrations, in Go
└── README.md3. Migrate and run
go run . migrate up # creates framework + app tables, seeds defaults
go run . serve # http://localhost:8080/adminSign in with admin / admin.
Warning
The seeded account is for first login only. Change its password
immediately — or create your own account with
go run . admin:create-user and delete the seeded one.
4. Generate a resource
steward make:resource Task --fields "title:string,notes:text,priority:enum(low,normal,high),done:bool,due_at:datetime:nullable"
go run . migrate up
go run . servemake:resource writes the model, a migration, and a pre-populated resource
file (grid columns, form fields with inferred validation rules, detail
view), and registers it in resources/registry.go. The field spec drives
sensible defaults — enum becomes a select with a badge column, bool
becomes a switch, *_id:fk(...) becomes a searchable BelongsTo.
Already have a schema? Generate from the live database instead:
steward make:resource Product --from-db --dsn "file:app.db" --table productsOr from an existing Go struct:
steward make:resource Invoice --from-struct ./models5. Make it yours
Open resources/task.go and shape the resource — everything is typed:
tasks := steward.Register[models.Task](app).Title("Tasks").Icon("check")
tasks.Grid(func(g *steward.Grid[models.Task]) {
g.Column("Title").Sortable().Limit(60)
g.Column("Priority").Badge(map[any]string{
"high": "red", "normal": "secondary", "low": "green",
})
g.Column("Done").Switch() // inline toggle, saved through validation
g.QuickSearch("Title", "Notes")
})
tasks.Form(func(f *steward.Form[models.Task]) {
f.Text("Title").Rules("required|max:255")
f.Select("Priority").Options(steward.Options{
"low": "Low", "normal": "Normal", "high": "High",
})
f.Datetime("DueAt")
f.Saving(func(c *steward.Context, m *models.Task) error {
// runs before persist, with the typed model
return nil
})
})Restart go run . serve and refresh.
Where to go next
- Grid — columns, filters, actions, tree grids, CSV export
- Form — all field kinds, rules, hooks, hasMany rows
- RBAC — roles, permissions, policies, menu visibility
- Runtime commands —
serve,worker,migrate, and deploying panel and background jobs as separate processes