Admin Panel (CRUD)

The admin plugin is a resource-based CRUD panel modeled on Laravel Nova / Filament. You describe your models as Resources โ€” the fields to show and how โ€” and the panel auto-generates list, create, edit, and delete screens with a modern Tailwind UI. It operates on your existing tables and declares no migrations of its own.

Gate it. The panel exposes full CRUD over your data. Always pass an auth guard via Config.Middleware โ€” without it the panel is public.

Setup

import "github.com/CodeSyncr/nimbus/plugins/admin"

panel := admin.New(db, admin.Config{
    BrandName:  "Acme Admin",
    RoutePrefix: "/admin",
    Middleware: []router.Middleware{auth.RequireAuth(guard)}, // gate the panel
})

panel.AddResource(admin.Resource{
    Model:  &models.Post{},
    Fields: []admin.Field{
        admin.Text("Title").AsSortable(),
        admin.Textarea("Body"),
        admin.Boolean("Published"),
        admin.Number("Views").AsReadonly(),
    },
})

app.Use(panel)

Open /admin for the dashboard. Each resource gets /admin/<slug> (list), /admin/<slug>/create, and edit/delete routes. The slug, singular, and plural labels default from the model type name.

Zero-config field inference

With no Fields, the panel infers them from the struct: booleans โ†’ checkboxes, email/password names โ†’ the right input, body/description/content โ†’ textareas, numeric kinds โ†’ number inputs, time.Time โ†’ date pickers. The embedded database.Model bookkeeping fields (ID, timestamps) are skipped from forms automatically.

Field types & modifiers

admin.Text("Name")
admin.Textarea("Bio")
admin.Number("Age")
admin.Boolean("Active")
admin.Email("Email")
admin.Password("Password")     // write-only; never echoed; blank = keep existing
admin.Date("PublishedAt")
admin.Select("Status",
    admin.Option{Value: "draft", Label: "Draft"},
    admin.Option{Value: "live",  Label: "Live"})

// Chainable modifiers:
admin.Text("Slug").WithLabel("URL slug").AsSortable()
admin.Number("Views").AsReadonly().HideFromForm()
admin.Text("Secret").HideFromIndex()

How it works

The panel is reflection-driven: it reads and writes your struct fields by name and persists through the ORM, so any database.Model-based type works without per-model glue. Password fields left blank on edit preserve the stored value, list pages paginate (PerPage, default 15), and CSRF tokens are injected into every form when Shield is enabled.