lago

package module
v0.6.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 41 Imported by: 0

README

Lago Web Framework

Go Reference

Lago is a modular, plugin-based web application framework for Go. It features dynamic registry-based layouts, hot-reloadable plugin features, transactional views, and database schema migrations managed per plugin.

For a detailed bootstrapping guide, check out the Lago Quickstart Guide.

Quickstart

Database Setup (PostgreSQL)

To use PostgreSQL with Lago:

  1. Install PostgreSQL:

    • Linux (Ubuntu/Debian): Run sudo apt update && sudo apt install postgresql postgresql-contrib
    • macOS: Run brew install postgresql
    • Windows: Download and run the installer from the PostgreSQL Official Downloads Page.
  2. Start the PostgreSQL Service:

    • Linux: Run sudo systemctl start postgresql
    • macOS: Run brew services start postgresql
  3. Create a Database User and Database: Access the PostgreSQL prompt:

    • Linux/macOS: Run:
      sudo -u postgres psql
      
    • Windows: Launch SQL Shell (psql) from the Start Menu, or open Command Prompt/PowerShell and run:
      psql -U postgres
      
      (If psql is not in your system PATH, run it from the installation directory, e.g., "C:\Program Files\PostgreSQL\<version>\bin\psql.exe" -U postgres) Run the following SQL commands to create a user and database:
    CREATE USER lago_user WITH PASSWORD 'secure_password';
    CREATE DATABASE lago_db OWNER lago_user;
    \q
    

Create a empty go project named lago_test

mkdir lago_test
cd lago_test
go mod init lago_test
go get github.com/lariv-in/lago@latest

Create an empty main.go, and an empty config.toml file

touch main.go
touch config.toml

In config.toml, put the following to connect with the postgres server configured above:

Debug = true
DBType = "Postgres"
Address = ":42069"

[PostgresConfig]
  DSN = "host=localhost user=lago_user password=secure_password dbname=lago_db port=5432 sslmode=disable TimeZone=Asia/Kolkata"

[plugins.p_pwa]
  # If set, /serviceworker.js will serve this file. If empty, p_pwa serves a minimal default.
  serviceWorkerPath = ""

  # If set, /offline will render this view key. If empty, p_pwa serves a minimal offline HTML page.
  offlineViewName = ""

  staticDir = "./pwa_static/"

  PWA_APP_NAME = "Lago Test"
  PWA_APP_DESCRIPTION = "Test app for lago"
  PWA_APP_THEME_COLOR = "#0A0302"
  PWA_APP_BACKGROUND_COLOR = "#ffffff"
  PWA_APP_DISPLAY = "standalone"
  PWA_APP_SCOPE = "/"
  PWA_APP_ORIENTATION = "any"
  PWA_APP_START_URL = "/"
  PWA_APP_STATUS_BAR_COLOR = "default"
  PWA_APP_DIR = "ltr"
  PWA_APP_LANG = "en-US"

[plugins.p_users]
adminEmail = "superadmin@test.com"
adminPassword = "SuperadminPassword1234"

To initialize a Lago application by registering active plugins, loading configuration values from a TOML file, and executing the CLI entrypoint, put the following in main.go

package main

import (
	"log"

	"github.com/lariv-in/lago"
	"github.com/lariv-in/lago/plugins/p_dashboard"
	"github.com/lariv-in/lago/plugins/p_users"
	"github.com/lariv-in/lago/registry"
)

func main() {
	// 1. Register the list of active plugins to load into the application kernel.
	plugins := []registry.Pair[string, lago.Plugin]{
		p_dashboard.GetPlugin(),
		p_users.GetPlugin(),
	}
	// Load database settings, server addresses, and plugin parameters from config.toml.
	config, err := lago.LoadConfigFromFile("config.toml", plugins)
	if err != nil {
     	log.Fatalf("failed loading configuration file: %v", err)
	}

	// 3. Build global registries and run the Cobra CLI bootstrapper.
	if err := lago.Start(config, plugins); err != nil {
		log.Fatalf("failed executing application entry: %v", err)
	}
}

To run,

go mod tidy
go run main.go generate
go run main.go

You can now login using the following credentials:

Email: superadmin@test.com Password: SuperadminPassword1234

Features

  • Plugin Registries: Package database models, pages, API routes, and configs inside modular plugin boundaries.
  • Transactional View Layers: Compose request pipelines with built-in or custom middleware layers to handle detail loading, form updates, and deletions.
  • Goose Migrations: Keep SQL database migrations decoupled and isolated inside plugin subdirectory systems.

Next Steps & Documentation

For detailed package documentation and guides, check out:

  • Lago Quickstart Guide: Detailed guide on bootstrapping and building modular plugins.
  • Lago Documentation Package: Explains the application directory structure, standard plugin files (app.go, config.go, pages.go, migrations.go, routes.go, models.go, views.go, commands.go), and architectural concepts (layers.go, components.go, querypatchers.go).

Documentation

Overview

Package lago is the application kernel: configuration loading, HTTP server wiring, and aggregated plugin registries (pages, views, routes, models, migrations, etc.).

Core Plugin Registrations

The kernel registers a default "core" plugin during boot via CorePlugin(). Below is a detailed list of features, pages, views, and routes contributed by the core plugin:

Core Global Layers (Global HTTP Middleware)

Registered under the following keys:

  • "core.AttachRequestLayer" -> views.AttachRequestLayer Attaches raw query parameter map ($get), request object ($request), and start timestamp ($timestamp) to the request context.
  • "core.DbLayer" -> DBLayer Attaches the active GORM database connection pool instance ($db) to the request context.
  • "core.LoggingLayer" -> LoggingLayer (Debug mode only) Logs HTTP request methods, paths, durations, and response codes.
  • "core.CacheDisableLayer" -> CacheDisableLayer (Debug mode only) Injects HTTP headers (Cache-Control, Pragma, Expires) to disable browser caching under local development.
  • "core.HtmxBoostLayer" -> HtmxBoostLayer Configures response headers for HTMX requests.
  • "core.EnvironmentLayer" -> EnvironmentLayer Sets up standard environment config context.

Core Views

Registered under:

  • "core.HomeView" -> views.View Resolves and displays the "core.HomePage" page component.

Core Pages

Registered under:

  • "core.HomePage" -> components.ShellBase The default home page visual layout scaffolding.

Core Routes

Registered under:

  • "core.HomeRoute" -> lago.Route Maps the root path ("/") to render standard text content or the home page view.

Bundled Plugins

The framework includes a collection of bundled plugins supporting standard app capabilities:

Index

Constants

View Source
const (
	// DBTypeSqlite specifies GORM SQLite database configurations.
	DBTypeSqlite = DBType("Sqlite")
	// DBTypePostgres specifies GORM PostgreSQL database configurations.
	DBTypePostgres = DBType("Postgres")
)
View Source
const (
	// PluginTypeApp indicates standalone, self-contained plugins containing primary application business logic and models.
	PluginTypeApp = iota
	// PluginTypeAddon indicates plugins that will not get listed on the dashboard's app grid.
	PluginTypeAddon
	// PluginTypeService indicates plugins booting long-running processes (e.g. background queue workers, SSE connections).
	PluginTypeService
)

Variables

Deprecated: This registry is a Work in Progress (WIP) and should NOT be used.

RegistryCommand represents the global immutable registry mapping custom plugin sub-commands to their CommandFactory builders.

RegistryConfig represents the global immutable registry mapping config identifiers to their Config instances.

RegistryDBInit represents the global immutable registry tracking database initialization hooks.

RegistryGenerator represents the global immutable registry tracking database seed generators.

RegistryLayer represents the global immutable registry tracking global middleware layers of type views.GlobalLayer. Global layers act as multiplexer-level middlewares wrapped around request paths prior to route matching.

Use Cases:

  • Registering global HTTP request filters (e.g. CORS headers, request loggers, CSRF validation, compression).

Example Definition:

type CorsLayer struct{}

func (l CorsLayer) Next(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		next.ServeHTTP(w, r)
	})
}

Example Registration:

// In your lago.Plugin setup:
lago.Plugin{
	Layers: lago.PluginStages(func() PluginFeatures[views.GlobalLayer] {
		return PluginFeatures[views.GlobalLayer]{
			Entries: []registry.Pair[string, views.GlobalLayer]{
				registry.NewPair("cors_layer", CorsLayer{}),
			},
		}
	}),
}

Example Patch:

// Register a patch to replace or modify global layers from another plugin:
lago.Plugin{
	Layers: lago.PluginStages(func() PluginFeatures[views.GlobalLayer] {
		return PluginFeatures[views.GlobalLayer]{
			Patches: []registry.Pair[string, func(views.GlobalLayer) views.GlobalLayer]{
				registry.NewPair("cors_layer", func(existing views.GlobalLayer) views.GlobalLayer {
					// Wrap or extend CorsLayer:
					return existing
				}),
			},
		}
	}),
}

Example Retrieval:

layer, ok := RegistryLayer.Get("cors_layer")

RegistryMigrations represents the global immutable registry tracking database migrations filesystems of type UsefulFilesystem. The database engine scans filesystems registered here to automatically execute pending SQL schemas during startup.

Use Cases:

  • Bundling plugin database table creations, constraints, or seeds.

Example Registration:

//go:embed migrations/*.sql
var MigrationFS embed.FS

// In your lago.Plugin setup:
lago.Plugin{
	Migrations: lago.PluginStages(func() PluginFeatures[UsefulFilesystem] {
		return PluginFeatures[UsefulFilesystem]{
			Entries: []registry.Pair[string, UsefulFilesystem]{
				registry.NewPair("my_plugin_migrations", MigrationFS),
			},
		}
	}),
}

Example Patch:

// Register a patch to modify migration filesystems from another plugin:
lago.Plugin{
	Migrations: lago.PluginStages(func() PluginFeatures[UsefulFilesystem] {
		return PluginFeatures[UsefulFilesystem]{
			Patches: []registry.Pair[string, func(UsefulFilesystem) UsefulFilesystem]{
				registry.NewPair("my_plugin_migrations", func(existing UsefulFilesystem) UsefulFilesystem {
					// Decorate or intercept filesystem:
					return existing
				}),
			},
		}
	}),
}

Example Retrieval:

fs, ok := RegistryMigrations.Get("my_plugin_migrations")

RegistryModel represents the global immutable registry tracking application database models of type [any]. Models registered here are mapped to database structures for schema introspection or auto-migrations.

Use Cases:

  • Bundling plugin GORM structures (e.g. User, Product) to allow table creation, relationship tracking, or admin panel listing.

Example Definition:

type Product struct {
	gorm.Model
	Name string
}

Example Registration:

// In your lago.Plugin setup:
lago.Plugin{
	Models: lago.PluginStages(func() PluginFeatures[any] {
		return PluginFeatures[any]{
			Entries: []registry.Pair[string, any]{
				registry.NewPair("product_model", Product{}),
			},
		}
	}),
}

Example Patch:

// Register a patch to extend or modify registered models from another plugin:
lago.Plugin{
	Models: lago.PluginStages(func() PluginFeatures[any] {
		return PluginFeatures[any]{
			Patches: []registry.Pair[string, func(any) any]{
				registry.NewPair("product_model", func(existing any) any {
					// Modify or wraps metadata:
					return existing
				}),
			},
		}
	}),
}

Example Retrieval:

modelVal, ok := RegistryModel.Get("product_model")

RegistryPage represents the global immutable registry tracking page templates of type components.PageInterface. Pages registered here are resolved by view controllers to compile dynamic user interfaces.

Use Cases:

  • Bundling plugin views structures (e.g. login pages, settings layout templates).

Example Definition:

type HelloPage struct {
	components.Page
}

func (p HelloPage) Build(ctx context.Context) gomponents.Node {
	return html.Div(html.H1(gomponents.Text("Hello World")))
}

Example Registration:

// In your lago.Plugin setup:
lago.Plugin{
	Pages: lago.PluginStages(func() PluginFeatures[components.PageInterface] {
		return PluginFeatures[components.PageInterface]{
			Entries: []registry.Pair[string, components.PageInterface]{
				registry.NewPair("hello_page", HelloPage{}),
			},
		}
	}),
}

Example Patch:

// Register a patch to decorate or modify pages from another plugin:
lago.Plugin{
	Pages: lago.PluginStages(func() PluginFeatures[components.PageInterface] {
		return PluginFeatures[components.PageInterface]{
			Patches: []registry.Pair[string, func(components.PageInterface) components.PageInterface]{
				registry.NewPair("hello_page", func(existing components.PageInterface) components.PageInterface {
					// Modify layout or add wrapper children:
					return existing
				}),
			},
		}
	}),
}

Example Retrieval:

page, ok := RegistryPage.Get("hello_page")

RegistryPlugin represents the global immutable registry tracking installed plugins metadata.

RegistryRoute represents the global immutable registry tracking route mappings.

RegistryView represents the global immutable registry tracking view page controllers of type *views.View.

Functions

func BuildAllRegistries

func BuildAllRegistries(allPlugins []registry.Pair[string, Plugin])

BuildAllRegistries executes mapping and populates all application registries using the slice of active plugins. It sets up migrations, views, configs, DB hooks, routers, models, layers, and page templates.

Use Cases:

  • Initializing registries at startup before starting the server.

Example:

lago.BuildAllRegistries(allActivePlugins)

func CorePlugin

func CorePlugin(db *gorm.DB, config LagoConfig) registry.Pair[string, Plugin]

CorePlugin creates the framework core plugin configuration. It registers standard global middleware layers (e.g. database attachments, logging, caching controls, environment mappings) and hooks up default routing and landing page views.

func FillRegistry

func FillRegistry[T any](features [][]func() PluginFeatures[T], targetRegistry *registry.ImmutableRegistry[T])

FillRegistry merges feature bundles from plugins, then populates and assigns an immutable registry after executing PluginFeatures.Build for each element block. Patches must be pure and idempotent.

func GetDbConn

func GetDbConn(config LagoConfig) (*gorm.DB, error)

GetDbConn opens and configures a GORM connection using the provided database configurations. It overrides default delete callbacks to enforce hard deletes (disabling soft deletes).

func GetPageView

func GetPageView(pageName string) *views.View

GetPageView initializes and returns a standard view controller wrapper views.View that resolves and renders page layouts from the global RegistryPage.

Use Cases:

  • Defining basic HTML routes or static pages that require page registry lookups without custom middleware layers.

Example:

var DashboardHomeView = lago.GetPageView("dashboard.home")

func GetRouter

func GetRouter(config LagoConfig) *http.ServeMux

GetRouter initializes and returns the ServeMux router populated with all registered routes. It maps path endings to specific ServeMux rules and registers pprof handlers under debug environments.

func GooseVersionTableName

func GooseVersionTableName(registryKey string) string

GooseVersionTableName derives a database-safe schema version tracker table name for a plugin migration registry key. It maps plugin keys deterministically to clean snake_case table names (prefixed with "goose_migrations__") ensuring separate tables per plugin so that numeric migration versions can overlap across plugins.

Database Migrations Structure

In Lago, database schema migrations are managed per plugin. To add migrations to a plugin:

1. Create a `migrations` folder inside your plugin directory structure. 2. Add SQL migration files inside the `migrations` directory following Goose's syntax structure:

-- 00001_create_users_table.sql
-- +goose Up
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE
);

-- +goose Down
DROP TABLE users;

3. Embed the migration files and register the filesystem on your Plugin configuration under the Migrations field:

//go:embed migrations/*.sql
var migrationFS embed.FS

// In your lago.Plugin setup:
lago.Plugin{
    Migrations: lago.PluginStages(func() lago.PluginFeatures[lago.UsefulFilesystem] {
        return lago.PluginFeatures[lago.UsefulFilesystem]{
            Entries: []registry.Pair[string, lago.UsefulFilesystem]{
                registry.NewPair("my_plugin", migrationFS),
            },
        }
    }),
}

func InitDB

func InitDB(db *gorm.DB, config LagoConfig) error

InitDB executes pending schema migrations and invokes registered database initialization hooks sequentially.

func MapSlice

func MapSlice[T any, R any](slice []T, mapper func(T) R) []R

MapSlice maps elements in a slice from type T to type R using a converter function.

func PluginStages

func PluginStages[T any](stage func() PluginFeatures[T]) []func() PluginFeatures[T]

PluginStages wraps a single feature callback as a one-element slice for Plugin fields.

func RedirectView

func RedirectView(urlGetter getters.Getter[string]) *views.View

RedirectView returns a specialized *views.View instance configured to perform client redirects to the URL resolved by urlGetter.

Use Cases:

  • Mapping base routes or landing URLs to dashboard landing folders (e.g. mapping "/" to "/dashboard/").

Example:

var HomeRoute = Route{
	Path:    "/",
	Handler: lago.RedirectView(getters.Static("/dashboard/")),
}

func RoutePath

func RoutePath(name string, args map[string]getters.Getter[any]) getters.Getter[string]

RoutePath yields a Getter that resolves and interpolates path variables in a registered named route.

Example:

pathGetter := RoutePath("user.profile", map[string]getters.Getter[any]{
	"id": getters.Static(42),
})
url, err := pathGetter(ctx) // Resolves to "/users/u/42/profile"

func RunGenerators

func RunGenerators(config LagoConfig)

RunGenerators executes all registered seed generators. It runs deletion (Remove) in reverse order of GeneratorOrder to satisfy foreign key constraints, and creation (Create) in forward order of GeneratorOrder so dependent entities are populated correctly.

func Start

func Start(config LagoConfig, plugins []registry.Pair[string, Plugin]) error

Start initializes and executes the Cobra CLI application, acting as the main entrypoint for any Lago application.

CLI Command Scopes:

  • Root Command: Starts the HTTP web server via StartServer.
  • generate: Runs database seed generators via RunGenerators.
  • tui: Launches the Bubble Tea terminal user interface.
  • Plugin Commands: Resolves and registers custom commands dynamically loaded from RegistryCommand.

Registries and configurations must be populated before invoking this function (e.g. using LoadConfigFromFile).

Use Cases:

  • Initializing the CLI bootstrapper in the main execution block of a Go application.

Example:

func main() {
	config := lago.LagoConfig{
		DBType:  lago.DBTypePostgres,
		Address: ":8080",
	}
	plugins := []registry.Pair[string, lago.Plugin]{
		p_dashboard.GetPlugin(),
	}
	if err := lago.Start(config, plugins); err != nil {
		log.Fatal(err)
	}
}

func StartServer

func StartServer(config LagoConfig) error

StartServer compiles global middleware layers, configures CORS/CrossOrigin protection, and listens for HTTP requests. It supports binding to standard TCP socket addresses (config.Address) or Unix Domain Sockets (config.UDS).

Use Cases:

  • Initializing the primary web server listener block during application startup.

Example:

if err := lago.StartServer(config); err != nil {
	log.Fatal(err)
}

Types

type AdminPanel deprecated

type AdminPanel[T any] struct {
	SearchField string
	ListFields  []string
	Preload     []string
}

Deprecated: This struct is a Work in Progress (WIP) and should NOT be used.

func (AdminPanel[T]) Create

func (a AdminPanel[T]) Create(db *gorm.DB, values map[string]*string) error

func (AdminPanel[T]) EditableFields

func (a AdminPanel[T]) EditableFields() []string

func (AdminPanel[T]) ExportCSV

func (a AdminPanel[T]) ExportCSV(db *gorm.DB, path string) (int, error)

func (AdminPanel[T]) GetListFields

func (a AdminPanel[T]) GetListFields() []string

func (AdminPanel[T]) ImportCSV

func (a AdminPanel[T]) ImportCSV(db *gorm.DB, path string) (int, error)

func (AdminPanel[T]) IsAdminPanel

func (a AdminPanel[T]) IsAdminPanel() bool

func (AdminPanel[T]) List

func (a AdminPanel[T]) List(db *gorm.DB, page, pageSize int) ([]map[string]any, error)

func (AdminPanel[T]) ModelName

func (a AdminPanel[T]) ModelName() string

func (AdminPanel[T]) Save

func (a AdminPanel[T]) Save(db *gorm.DB, id string, values map[string]*string) error

type AdminPanelInterface deprecated

type AdminPanelInterface interface {
	IsAdminPanel() bool
	ModelName() string
	GetListFields() []string
	EditableFields() []string
	List(db *gorm.DB, page, pageSize int) ([]map[string]any, error)
	Save(db *gorm.DB, id string, values map[string]*string) error
	Create(db *gorm.DB, values map[string]*string) error
	ImportCSV(db *gorm.DB, path string) (int, error)
	ExportCSV(db *gorm.DB, path string) (int, error)
}

Deprecated: This interface is a Work in Progress (WIP) and should NOT be used.

type CacheDisableLayer

type CacheDisableLayer struct{}

func (CacheDisableLayer) Next

type CommandFactory

type CommandFactory func(LagoConfig) *cobra.Command

CommandFactory represents a generator function that builds Cobra CLI commands mapped to a specific LagoConfig.

Use Cases:

  • Defining custom CLI sub-commands inside application plugins (e.g., system diagnostics, database cleaner tasks).

Example:

var BackupCmdFactory CommandFactory = func(config LagoConfig) *cobra.Command {
	return &cobra.Command{
		Use:   "backup",
		Short: "Executes a database schema backup",
		Run: func(cmd *cobra.Command, args []string) {
			executeBackup(config)
		},
	}
}

// Register the command factory inside your lago.Plugin configuration:
lago.Plugin{
	CommandFactories: lago.PluginStages(func() PluginFeatures[CommandFactory] {
		return PluginFeatures[CommandFactory]{
			Entries: []registry.Pair[string, CommandFactory]{
				registry.NewPair("backup_db", BackupCmdFactory),
			},
		}
	}),
}

// Register a patch to modify an existing command in another plugin:
lago.Plugin{
	CommandFactories: lago.PluginStages(func() PluginFeatures[CommandFactory] {
		return PluginFeatures[CommandFactory]{
			Patches: []registry.Pair[string, func(CommandFactory) CommandFactory]{
				registry.NewPair("backup_db", func(existing CommandFactory) CommandFactory {
					return func(config LagoConfig) *cobra.Command {
						cmd := existing(config)
						cmd.Short = "Patched: " + cmd.Short
						return cmd
					}
				}),
			},
		}
	}),
}

// Retrieve a registered command factory:
factory, ok := RegistryCommand.Get("backup_db")

type Config

type Config interface {
	// PostConfig executes sanity checks and assigns default values after TOML values are loaded.
	PostConfig()
}

Config defines the interface implemented by plugin config structs to receive and validate parsed settings from TOML files. PostConfig is executed automatically after settings are mapped, enabling validation or setting default values.

Use Cases:

  • Defining configuration tables for plugins (e.g. storage paths, API client secrets).

Example Definition:

type DashboardConfig struct {
	AppName string
}

func (c *DashboardConfig) PostConfig() {
	if c.AppName == "" {
		c.AppName = "My Dashboard App"
	}
}

Example Registration:

var DashboardConfigPtr = &DashboardConfig{}

// Register the config instance inside your lago.Plugin configuration:
lago.Plugin{
	Configs: lago.PluginStages(func() PluginFeatures[Config] {
		return PluginFeatures[Config]{
			Entries: []registry.Pair[string, Config]{
				registry.NewPair("dashboard", DashboardConfigPtr),
			},
		}
	}),
}

Example Patch:

// Register a patch to modify config settings from another plugin:
lago.Plugin{
	Configs: lago.PluginStages(func() PluginFeatures[Config] {
		return PluginFeatures[Config]{
			Patches: []registry.Pair[string, func(Config) Config]{
				registry.NewPair("dashboard", func(existing Config) Config {
					cfg := existing.(*DashboardConfig)
					cfg.AppName = "Modified App Name"
					return cfg
				}),
			},
		}
	}),
}

Example Retrieval:

cfgVal, ok := RegistryConfig.Get("dashboard")

type DBInitHook

type DBInitHook func(*gorm.DB) *gorm.DB

DBInitHook represents a hook function executed after core database setup is complete (migrations, default callbacks). Hooks are executed in registration order and receive the active *gorm.DB instance, returning a decorated/modified *gorm.DB client.

Use Cases:

  • Configuring connection pool properties (e.g., setting maximum connections).
  • Triggering initial auto-migrations for non-plugin core tables.
  • Running database logging configurations or starting background cron workers with database handles.

Example Definition:

var ConnPoolHook DBInitHook = func(db *gorm.DB) *gorm.DB {
	sqlDB, err := db.DB()
	if err == nil {
		sqlDB.SetMaxOpenConns(20)
	}
	return db
}

Example Registration:

// In your lago.Plugin setup:
lago.Plugin{
	DBInitHooks: lago.PluginStages(func() PluginFeatures[DBInitHook] {
		return PluginFeatures[DBInitHook]{
			Entries: []registry.Pair[string, DBInitHook]{
				registry.NewPair("conn_pool", ConnPoolHook),
			},
		}
	}),
}

Example Patch:

// Register a patch to chain or decorate existing DBInitHooks from another plugin:
lago.Plugin{
	DBInitHooks: lago.PluginStages(func() PluginFeatures[DBInitHook] {
		return PluginFeatures[DBInitHook]{
			Patches: []registry.Pair[string, func(DBInitHook) DBInitHook]{
				registry.NewPair("conn_pool", func(existing DBInitHook) DBInitHook {
					return func(db *gorm.DB) *gorm.DB {
						db = existing(db)
						// Chain extra configurations:
						return db.Debug()
					}
				}),
			},
		}
	}),
}

Example Retrieval:

hook, ok := RegistryDBInit.Get("conn_pool")

type DBLayer

type DBLayer struct {
	DB *gorm.DB
}

func (DBLayer) Next

func (m DBLayer) Next(next http.Handler) http.Handler

type DBType

type DBType string

DBType represents the configuration database engine driver selector.

type DynamicPage

type DynamicPage struct {
	// Page embeds common component properties like Key and Roles.
	components.Page
	// Name represents the registered string identifier of the target page component to fetch (e.g. "admin.Dashboard").
	Name string
}

DynamicPage lazily resolves page elements by string identifiers from RegistryPage at build/render time. This decouples components registrations, avoiding import-time dependency loops between modular plugins.

Use Cases:

  • Lazy-loading sub-pages or sections dynamically from registries without establishing direct static dependencies.

Example:

&lago.DynamicPage{
    Name: "admin.Dashboard",
}

func (DynamicPage) Build

func (d DynamicPage) Build(ctx context.Context) gomponents.Node

Build compiles the dynamic component by rendering the lazy resolved page.

func (DynamicPage) GetChildren

func (d DynamicPage) GetChildren() []components.PageInterface

GetChildren resolves the lazy target page from the registry and returns it in a slice.

func (DynamicPage) GetKey

func (d DynamicPage) GetKey() string

GetKey returns the unique key identifier for this DynamicPage component.

func (DynamicPage) GetRoles

func (d DynamicPage) GetRoles() []string

GetRoles returns the authorized roles required to view this DynamicPage.

type DynamicView

type DynamicView struct {
	// Key represents the registered identifier of the view controller in RegistryView (e.g., "core.HomeView").
	Key string
}

DynamicView represents an HTTP handler that lazily resolves and executes a target view from RegistryView at request-time. This resolves import-cycle constraints between routing endpoints and view logic blocks.

Use Cases:

  • Delegating routing mappings to plugins without statically importing the views controllers.

Example Definition:

var HomeHandler = lago.NewDynamicView("core.HomeView")

func NewDynamicView

func NewDynamicView(key string) DynamicView

NewDynamicView constructs a new DynamicView handler targeting the specified view key.

func (DynamicView) ServeHTTP

func (v DynamicView) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP satisfies the standard http.Handler interface, executing the resolved view handler.

type EnvironmentLayer

type EnvironmentLayer struct{}

func (EnvironmentLayer) Next

type Generator

type Generator struct {
	// Create populates database tables with mock data records.
	Create func(*gorm.DB) error
	// Remove cleans up database tables to undo mock population.
	Remove func(*gorm.DB) error
}

Generator defines creation and deletion functions executed during database seeding/data generating commands.

Use Cases:

  • Seeding development or test databases with mock tables data (e.g. creating dummy administrator accounts, catalog samples).

Example Definition:

var ProductGen = Generator{
	Create: func(db *gorm.DB) error {
		return db.Create(&Product{Name: "Mock Item"}).Error
	},
	Remove: func(db *gorm.DB) error {
		return db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&Product{}).Error
	},
}

Example Registration:

// In your lago.Plugin setup:
lago.Plugin{
	Generators: lago.PluginStages(func() PluginFeatures[Generator] {
		return PluginFeatures[Generator]{
			Entries: []registry.Pair[string, Generator]{
				registry.NewPair("products_seeder", ProductGen),
			},
		}
	}),
}

Example Patch:

// Register a patch to chain or modify database seeders from another plugin:
lago.Plugin{
	Generators: lago.PluginStages(func() PluginFeatures[Generator] {
		return PluginFeatures[Generator]{
			Patches: []registry.Pair[string, func(Generator) Generator]{
				registry.NewPair("products_seeder", func(existing Generator) Generator {
					return Generator{
						Create: func(db *gorm.DB) error {
							if err := existing.Create(db); err != nil {
								return err
							}
							// Add extra seeder child data:
							return db.Create(&Tag{Name: "Hot"}).Error
						},
						Remove: existing.Remove,
					}
				}),
			},
		}
	}),
}

Example Retrieval:

gen, ok := RegistryGenerator.Get("products_seeder")

type HtmxBoostLayer

type HtmxBoostLayer struct{}

func (HtmxBoostLayer) Next

func (HtmxBoostLayer) Next(next http.Handler) http.Handler

type LagoConfig

type LagoConfig struct {
	// Debug enables verbose debug level outputs and diagnostics.
	Debug bool
	// DBType specifies the database driver engine type (e.g. Postgres, Sqlite).
	DBType DBType
	// SqliteConfig represents driver parameters for SQLite DB files.
	SqliteConfig *sqlite.Config
	// PostgresConfig represents connection parameters for PostgreSQL connections.
	PostgresConfig *postgres.Config
	// Address represents the TCP bind address (e.g. ":8080").
	Address string
	// UDS represents the Unix Domain Socket path to bind to (overrides Address if specified).
	UDS string
	// GeneratorOrder specifies the sequence of db seeder names to run during seed execution.
	GeneratorOrder []string
	// TrustedOrigins lists the allowed CORS request origin hosts.
	TrustedOrigins []string
	// Plugins maps raw TOML configuration sections to specific plugin config structures.
	Plugins map[string]toml.Primitive
}

LagoConfig represents the top-level configuration structure mapped from TOML files. It carries connection details, database setups, UDS paths, CORS trusted origins, and plugin parameters.

func LoadConfigFromFile

func LoadConfigFromFile(path string, plugins []registry.Pair[string, Plugin]) (LagoConfig, error)

LoadConfigFromFile decodes a TOML configuration file, registers application plugins, initializes database connections, decodes specific plugin configurations, and runs database migrations and hooks.

Use Cases:

  • Parsing configurations from files at startup before running the Cobra TUI or web server.

Example:

config, err := lago.LoadConfigFromFile("config.toml", plugins)
if err != nil {
	log.Fatal(err)
}

type LoggingLayer

type LoggingLayer struct{}

func (LoggingLayer) Next

func (LoggingLayer) Next(next http.Handler) http.Handler

type PageURL

type PageURL struct {
	// URL embeds standard url.URL structures.
	url.URL
}

PageURL represents a GORM-compatible database-persisted URL wrapper. It embeds standard Go url.URL allowing callers to directly access standard URL fields and methods (e.g. url.URL.String).

Use Cases:

  • Storing web resources urls (e.g. avatar images, callback webhooks, external client logins) in database models.

Example:

type ClientApp struct {
	gorm.Model
	Homepage lago.PageURL
}

func (PageURL) MarshalText

func (p PageURL) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler to serialize URL objects to byte strings.

func (*PageURL) Scan

func (p *PageURL) Scan(value any) error

Scan implements the SQL Scanner interface to populate URL properties from database columns.

func (*PageURL) SetFromURL

func (p *PageURL) SetFromURL(u *url.URL)

SetFromURL overrides the embedded URL properties using fields from the provided *url.URL object. Providing nil clears the url properties to zero.

func (*PageURL) URLPtr

func (p *PageURL) URLPtr() *url.URL

URLPtr returns a pointer to a copy of the embedded URL (or nil if empty / invalid for use as *url.URL). URLPtr yields a standard url.URL pointer to a copy of the embedded URL structure. Returns nil if the URL Host string is empty or invalid.

func (*PageURL) UnmarshalText

func (p *PageURL) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler to parse TOML configurations and form bindings.

func (PageURL) Value

func (p PageURL) Value() (driver.Value, error)

Value implements the database driver Valuer interface to save URL properties as database text strings.

type Plugin

type Plugin struct {
	// Type specifies the plugin classification.
	Type PluginType
	// Icon represents a CSS class or emoji string for UI representation.
	Icon string
	// URL represents the primary entry URL path pointing to the plugin landing page.
	URL *url.URL
	// VerboseName represents the user-friendly human readable label for the plugin.
	VerboseName string
	// Roles lists the authorized security roles allowed to interact with the plugin.
	Roles []string
	// Migrations defines embedded database schema update folders.
	Migrations []func() PluginFeatures[UsefulFilesystem]
	// Views defines views controllers to map request pipelines.
	Views []func() PluginFeatures[*views.View]
	// Routes maps endpoint strings to standard HTTP handlers.
	Routes []func() PluginFeatures[Route]
	// Pages registers HTML component page layout trees.
	Pages []func() PluginFeatures[components.PageInterface]
	// Models registers GORM schema models.
	Models []func() PluginFeatures[any]
	// Layers registers global request/response multiplexer middlewares.
	Layers []func() PluginFeatures[views.GlobalLayer]
	// Generators registers database mock seed handlers.
	Generators []func() PluginFeatures[Generator]
	// DBInitHooks registers GORM initialization hook decorators.
	DBInitHooks []func() PluginFeatures[DBInitHook]
	// Configs registers custom setting configurations structs.
	Configs []func() PluginFeatures[Config]
	// CommandFactories registers custom CLI commands generators.
	CommandFactories []func() PluginFeatures[CommandFactory]
}

Plugin defines a collection of application features, CLI commands, database initializers, routing endpoints, configurations, and metadata components.

Use Cases:

  • Defining modular code boundaries to group related database tables, templates, middlewares, and views.

Example Definition:

var DashboardPlugin = lago.Plugin{
	Type:        lago.PluginTypeApp,
	VerboseName: "Dashboard",
	Pages: lago.PluginStages(func() lago.PluginFeatures[components.PageInterface] {
		return lago.PluginFeatures[components.PageInterface]{
			Entries: []registry.Pair[string, components.PageInterface]{
				registry.NewPair("dashboard.home", DashboardHome{}),
			},
		}
	}),
}

type PluginFeatures

type PluginFeatures[T any] struct {
	// Entries represents the slice of new registry contributions to register.
	Entries []registry.Pair[string, T]
	// Patches represents the slice of modification rules targeting previously registered components with matching keys.
	Patches []registry.Pair[string, func(T) T]
}

PluginFeatures collects registry Entries and optional Patches for a specific feature type T. Patches are applied to registered entries with matching keys during registry builds.

func (*PluginFeatures[T]) Build

func (f *PluginFeatures[T]) Build() []registry.Pair[string, T]

Build returns registry pairs with patches applied in registration order. Patches must be pure and idempotent: they must not mutate their argument T in place, and applying the same patch again to its own output must yield an equivalent result. Registry assembly may invoke Build more than once while merging plugins.

func (PluginFeatures[T]) Merge

func (f PluginFeatures[T]) Merge(others ...PluginFeatures[T]) PluginFeatures[T]

Merge concatenates Entries and Patches. Order is preserved so patch application order stays deterministic.

type PluginType

type PluginType int

PluginType represents the classification of a Lago plugin.

type RedirectLayer

type RedirectLayer struct {
	// URLGetter represents the dynamic URL target getter resolving to the redirection link.
	URLGetter getters.Getter[string]
}

RedirectLayer represents a view middleware layer that intercepts requests and performs a client redirect.

func (RedirectLayer) Next

func (m RedirectLayer) Next(_ views.View, next http.Handler) http.Handler

Next wraps the down-chain HTTP handler with redirection interceptors.

type ResponseLoggerLayer

type ResponseLoggerLayer struct{}

func (ResponseLoggerLayer) Next

type ResponseWriterWrapper

type ResponseWriterWrapper struct {
	// contains filtered or unexported fields
}

ResponseWriterWrapper struct is used to log the response

func NewResponseWriterWrapper

func NewResponseWriterWrapper(w http.ResponseWriter) ResponseWriterWrapper

NewResponseWriterWrapper static function creates a wrapper for the http.ResponseWriter

func (ResponseWriterWrapper) Header

func (rww ResponseWriterWrapper) Header() http.Header

Header function overwrites the http.ResponseWriter Header() function

func (ResponseWriterWrapper) String

func (rww ResponseWriterWrapper) String() string

func (ResponseWriterWrapper) Write

func (rww ResponseWriterWrapper) Write(buf []byte) (int, error)

func (ResponseWriterWrapper) WriteHeader

func (rww ResponseWriterWrapper) WriteHeader(statusCode int)

WriteHeader function overwrites the http.ResponseWriter WriteHeader() function

type Route

type Route struct {
	// Path represents the ServeMux-compatible URL path pattern (e.g., "/users/u/{id}/").
	Path string
	// Handler represents the HTTP handler mapped to this route path.
	Handler http.Handler
}

Route represents a multiplexer-compatible HTTP routing entry.

Wildcard Path Guidelines

1. Wildcards (like `{id}`) must occupy a full path segment. Use `/users/u/{id}/` instead of `/users{id}/`. 2. Base paths should end with a trailing slash `/` before segment appends. 3. Sibling paths with fixed literals and wildcards under the same prefix should be disambiguated by adding an explicit sub-segment (e.g. `/users/roles/...` vs `/users/u/{id}/...`).

Use Cases:

  • Mapping standard HTTP endpoints to custom controllers or view handlers.

Example Definition:

var ProfileRoute = Route{
	Path: "/users/u/{id}/profile",
	Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		w.Write([]byte("Profile for user: " + id))
	}),
}

Example Registration:

// In your lago.Plugin setup:
lago.Plugin{
	Routes: lago.PluginStages(func() PluginFeatures[Route] {
		return PluginFeatures[Route]{
			Entries: []registry.Pair[string, Route]{
				registry.NewPair("user.profile", ProfileRoute),
			},
		}
	}),
}

Example Patch:

// Register a patch to prefix or redirect routes from another plugin:
lago.Plugin{
	Routes: lago.PluginStages(func() PluginFeatures[Route] {
		return PluginFeatures[Route]{
			Patches: []registry.Pair[string, func(Route) Route]{
				registry.NewPair("user.profile", func(existing Route) Route {
					return Route{
						Path:    "/internal" + existing.Path,
						Handler: existing.Handler,
					}
				}),
			},
		}
	}),
}

Example Retrieval:

route, ok := RegistryRoute.Get("user.profile")

type UsefulFilesystem

type UsefulFilesystem interface {
	fs.FS
	fs.ReadDirFS
	fs.ReadFileFS
}

UsefulFilesystem represents a comprehensive filesystem interface combining basic reads, directory lists, and file retrieval capabilities. It embeds standard Go fs.FS, fs.ReadDirFS, and fs.ReadFileFS interfaces.

Use Cases:

  • Bundling embedded resource directories (e.g. database migration files, template directory pools) in plugin packages.

Example:

func LoadSqlMigrations(filesystem lago.UsefulFilesystem) {
	entries, err := filesystem.ReadDir("migrations")
	// ... parse and run migrations ...
}

Directories

Path Synopsis
Package components provides a set of reusable UI components and input controls built on top of gomponents for structured, server-side rendered HTML generation.
Package components provides a set of reusable UI components and input controls built on top of gomponents for structured, server-side rendered HTML generation.
Package docs contains explanations and code examples for plugin-specific files in Lago.
Package docs contains explanations and code examples for plugin-specific files in Lago.
app
Package app contains explanations and code examples for the plugin app.go file in Lago.
Package app contains explanations and code examples for the plugin app.go file in Lago.
commands
Package commands contains explanations and code examples for plugin-specific CLI commands in Lago.
Package commands contains explanations and code examples for plugin-specific CLI commands in Lago.
components
Package components contains explanations and code examples for UI page components in Lago.
Package components contains explanations and code examples for UI page components in Lago.
config
Package config contains explanations and code examples for plugin configurations in Lago.
Package config contains explanations and code examples for plugin configurations in Lago.
layers
Package layers contains explanations and code examples for middleware request-handling layers in Lago.
Package layers contains explanations and code examples for middleware request-handling layers in Lago.
migrations
Package migrations contains explanations and code examples for database migrations in Lago.
Package migrations contains explanations and code examples for database migrations in Lago.
models
Package models contains explanations and code examples for database models in Lago.
Package models contains explanations and code examples for database models in Lago.
pages
Package pages contains explanations and code examples for pages in Lago.
Package pages contains explanations and code examples for pages in Lago.
querypatchers
Package querypatchers contains explanations and code examples for database query patchers in Lago.
Package querypatchers contains explanations and code examples for database query patchers in Lago.
quickstart
Package quickstart guides you through building a minimal Lago plugin that renders "Hello, World!".
Package quickstart guides you through building a minimal Lago plugin that renders "Hello, World!".
routes
Package routes contains explanations and code examples for HTTP routing in Lago.
Package routes contains explanations and code examples for HTTP routing in Lago.
views
Package views contains explanations and code examples for view controllers in Lago.
Package views contains explanations and code examples for view controllers in Lago.
Package fields provides custom datatype fields and structures for GORM database models persisting.
Package fields provides custom datatype fields and structures for GORM database models persisting.
Package getters defines the core Getter type and a suite of utility functions for fetching, transforming, and composing dynamic values.
Package getters defines the core Getter type and a suite of utility functions for fetching, transforming, and composing dynamic values.
lago module
plugins
p_dashboard
Package p_dashboard implements the central launchpad, top bar navigation buttons, and theme toggling for the Lago application portal.
Package p_dashboard implements the central launchpad, top bar navigation buttons, and theme toggling for the Lago application portal.
p_export
Package p_export implements Excel spreadsheet (XLSX) creation and table export features for GORM models.
Package p_export implements Excel spreadsheet (XLSX) creation and table export features for GORM models.
p_filesystem
Package p_filesystem implements a virtual node (VNode) database filesystem for the Lago framework.
Package p_filesystem implements a virtual node (VNode) database filesystem for the Lago framework.
p_google_genai
Package p_google_genai implements Google Gemini GenAI client wrappers and dynamic schema generators.
Package p_google_genai implements Google Gemini GenAI client wrappers and dynamic schema generators.
p_livereloading
Package p_livereloading implements automated browser refresh / live reloading capabilities during local development.
Package p_livereloading implements automated browser refresh / live reloading capabilities during local development.
p_llm_assistant
Package p_llm_assistant implements an interactive LLM chat assistant powered by Gemini.
Package p_llm_assistant implements an interactive LLM chat assistant powered by Gemini.
p_otp
Package p_otp implements one-time password (OTP) delivery and verification features for password recovery and multi-factor auth.
Package p_otp implements one-time password (OTP) delivery and verification features for password recovery and multi-factor auth.
p_pwa
Package p_pwa implements Progressive Web App (PWA) manifest compilation, service worker mapping, offline fallback pages, and Android asset links hosting.
Package p_pwa implements Progressive Web App (PWA) manifest compilation, service worker mapping, offline fallback pages, and Android asset links hosting.
p_users
Package p_users implements the user administration and authentication system for the Lago framework.
Package p_users implements the user administration and authentication system for the Lago framework.
forms module
p_assignments module
p_contacts module
p_courses module
p_forms module
p_lacerate module
p_programs module
p_seer_intel module
p_seer_reddit module
p_semesters module
p_sqlagent module
p_students module
p_teachers module
Package registry provides a mechanism to store and modify objects.
Package registry provides a mechanism to store and modify objects.
Package syncmap provides a generic, thread-safe map implementation.
Package syncmap provides a generic, thread-safe map implementation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL