Complete reference for go-webglue types, functions, and interfaces.
Represents a logical component of your application.
type Module struct {
Name string // Module identifier (used in URLs and JS)
Resources *embed.FS // Embedded client-side files
Events []*Event // Events this module can emit
Api any // Struct with exported methods to expose
}Example:
//go:embed client/*
var clientResources embed.FS
module := &webglue.Module{
Name: "users",
Resources: &clientResources,
Events: []*webglue.Event{userCreatedEvent},
Api: &UsersApi{},
}Configuration for creating the HTTP handler.
type Options struct {
Modules []*Module // Your application modules
IndexHtml string // Custom HTML template (optional)
}Default IndexHtml: If not provided, uses webglue.DefaultIndexHtml
Custom HTML Requirements:
- Must include
{WEBGLUE}placeholder - go-webglue replaces it with stylesheet links and import map
Example:
options := webglue.Options{
Modules: []*webglue.Module{myModule},
IndexHtml: `
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
{WEBGLUE}
<script type="module">
import {start} from "webglue";
$(document).ready(start);
</script>
</head>
<body></body>
</html>
`,
}Represents a server-to-client event stream.
type Event struct {
Module string // Auto-populated by framework
Name string // Event name
servers []*sse.Server // Internal
}Creating Events:
updateEvent := webglue.NewEvent("dataUpdated")Emitting Events:
event.Emit(param1, param2, ...) // Variadic parametersCreates the main HTTP handler for your application.
func NewHandler(options Options) (*http.ServeMux, error)Returns:
*http.ServeMux: Handler ready to pass tohttp.ListenAndServeerror: Error if initialization fails
Example:
handler, err := webglue.NewHandler(webglue.Options{
Modules: []*webglue.Module{myModule},
})
if err != nil {
panic(err)
}
http.ListenAndServe(":8080", handler)Creates a new event that can be emitted to clients.
func NewEvent(name string) *EventExample:
tickEvent := webglue.NewEvent("tick")
tickEvent.Emit(time.Now().Unix())Implement this interface on your API struct to inject custom parameters or perform authentication.
type CallChecker interface {
CheckCall(request *http.Request, functionName string) ([]any, error)
}Parameters:
request: The HTTP requestfunctionName: The Go method name being called (e.g., "GetUser")
Returns:
[]any: Parameters to inject into the function callerror: If non-nil, the API call fails with this error
Example:
type MyApi struct {
db *Database
}
func (api *MyApi) CheckCall(req *http.Request, funcName string) ([]any, error) {
// Extract and validate auth token
token := req.Header.Get("Authorization")
user, err := api.db.ValidateToken(token)
if err != nil {
return nil, errors.New("unauthorized")
}
// Inject user into all API calls
return []any{user}, nil
}
// Now all methods can receive User
func (api *MyApi) GetProfile(user *User) (*Profile, error) {
return api.db.GetProfile(user.ID)
}Important: The CheckCall method itself cannot be called via API.
Your API methods are automatically exposed with these rules:
- Go:
PascalCase(e.g.,GetUser) - JavaScript:
camelCase(e.g.,api.module.getUser)
Parameters can be:
-
Injected Automatically (not from JavaScript):
context.Context- fromrequest.Context()*http.Request- the HTTP request- Any type returned by
CallChecker
-
From JavaScript (JSON unmarshaled):
- Primitives:
int,float64,string,bool - Structs with JSON tags
- Slices and maps
- Nested structures
- Primitives:
Example:
type UserInput struct {
Name string `json:"name"`
Email string `json:"email"`
}
func (api *MyApi) CreateUser(
ctx context.Context, // Injected: request context
currentUser *User, // Injected: from CallChecker
input UserInput, // From JS: unmarshaled from JSON body
) (string, error) {
// Implementation
}// JavaScript call
let userId = await api.mymodule.createUser({
name: "John",
email: "john@example.com"
});Methods can return:
-
Single Value:
func (api *Api) GetCount() int { return 42 }
let count = await api.module.getCount(); // 42
-
Value and Error:
func (api *Api) GetUser(id int) (*User, error) { ... }
try { let user = await api.module.getUser(42); } catch (err) { console.error(err.message); }
-
Multiple Values:
func (api *Api) DivMod(a, b int) (int, int, error) { return a/b, a%b, nil }
let [quotient, remainder] = await api.module.divMod(10, 3);
-
Multiple Values (no error):
func (api *Api) GetMinMax(nums []int) (int, int) { ... }
let [min, max] = await api.module.getMinMax([1, 5, 3]);
Error Handling:
- Any return value of type
errorthat is non-nil stops processing - Error is returned to JavaScript as rejected Promise
- Other return values are ignored if error is present
import { api, asy, error, goto, tags, start } from "webglue";Dynamic proxy object containing all discovered API methods.
Structure:
api.moduleName.methodName(...args)Returns: Promise that resolves to the result or rejects with error
Example:
// Call Go method: func (api *MyApi) GetUser(id int) (*User, error)
let user = await api.mymodule.getUser(42);Object containing tag factory functions.
Available Tags:
DIV,SPAN,H1,H2,H3BUTTON,AHREF,LABEL,PARIMG,ICON,SETOFFFORM,INPUT,TEXT,PASSWORD,NUMBERCHECKBOX,RADIO,SELECT,OPTION,TEXTAREATABLE,TR,TD,THFIELDSET,IFRAME
Usage:
let { DIV, BUTTON, TEXT } = tags;
DIV("css-class", [
TEXT().val("Hello"),
BUTTON().text("Click me")
])Arguments (processed in order):
string: Added as CSS classobject: Passed to jQuery.prop()array: Elements appended as childrenfunction: Called with element, return value processed recursively
Function Callbacks:
DIV(el => {
el.addClass("dynamic");
return "Content"; // Processed
})Initializes the webglue application. Called automatically if using default HTML.
import { start } from "webglue";
$(document).ready(start);Process:
- Discovers API endpoints
- Sets up event stream
- Initializes routing
- Renders initial page
Navigate to a different page.
goto("/users?id=42") // Add to history
goto("/home", true) // Replace current history entryParameters:
url: Path with optional query stringreplace: If true, replaces current history entry
Wrapper for async functions that handles errors.
BUTTON().click(() => {
asy(async () => {
let result = await api.mymodule.doSomething();
console.log(result);
});
});Behavior:
- Catches errors and calls
error(e)orpage.error(e) - Prevents unhandled promise rejections
Default error handler.
error(new Error("Something went wrong"));Behavior:
- Calls
page.error(e)if defined - Otherwise shows
alert(e)
Each page is a JavaScript module exporting a default object.
Location: client/{pagename}.page.js
Required Exports:
export default {
title: "Page Title", // Browser title
render: async (url, params) => { // Returns array of jQuery elements
return [
DIV().text("Content")
];
},
// Optional:
error: (e) => { ... }, // Custom error handler
check: async (url, params) => { // Pre-render check
// Return URL string to redirect, or falsy to continue
}
}Example:
// client/users.page.js
import { api, tags } from "webglue";
let { DIV, H1 } = tags;
export default {
title: "Users",
async render(url, params) {
let users = await api.mymodule.listUsers();
return [
H1().text("Users"),
DIV(users.map(user =>
DIV().text(user.name)
))
];
}
}Events are auto-registered based on discovery:
// For event named "updated" in module "users"
$(element).onUsersUpdated((el, ...params) => {
// Handle event
});Naming Convention:
on+ModuleName(capitalized) +EventName(capitalized)- Example:
onUsersDataChanged,onCoreReady
webglue.tick
Fires every second on all elements:
DIV().onWebglueTick(handler) // or
DIV().on("webglue.tick", handler)Set headers to be sent with all API requests:
// Set in localStorage (persists across sessions)
localStorage.setItem("webglue.headers.Authorization", "Bearer token123");
// Set in sessionStorage (cleared on browser close)
sessionStorage.setItem("webglue.headers.X-Custom", "value");Prefix: webglue.headers.
Example Use Case: Authentication tokens
// After login
localStorage.setItem("webglue.headers.Authorization", `Bearer ${token}`);
// All subsequent API calls include: Authorization: Bearer token123
// Logout
localStorage.removeItem("webglue.headers.Authorization");Enable file-system serving for a module:
MODULENAME_DEV=/path/to/client go run main.goModule Name: Uppercase version of module name
Example: Module "myApp" → MYAPP_DEV=/path/to/files
Benefits:
- No rebuild needed for JS/CSS changes
- No minification (easier debugging)
- Instant feedback
webglue.ContentTypeHeader = "Content-Type"
webglue.ContentTypeJson = "application/json"
webglue.ContentLengthHeader = "Content-Length"
webglue.WebgluePlaceholder = "{WEBGLUE}"
webglue.DefaultIndexHtml = "..." // Default HTML template
webglue.EventStreamName = "webglue"func (api *Api) GetUser(id int) (*User, error) {
if id < 0 {
return nil, errors.New("invalid user ID")
}
// ...
}try {
await api.module.getUser(-1);
} catch (err) {
console.error(err.message); // "invalid user ID"
}| Go Type | JavaScript Type | Notes |
|---|---|---|
int, int64, float64 |
number |
|
string |
string |
|
bool |
boolean |
|
struct |
object |
Uses JSON tags |
[]T |
Array |
|
map[string]T |
object |
|
time.Time |
string |
ISO 8601 format |
nil |
null |
|
error |
Exception | Becomes rejected Promise |
- Frontend Guide - Build UIs with webglue
- Events Guide - Real-time communication
- Examples - Code samples