Skip to main content

Schema Design

Hugr apps organize their API using schemas which map to GraphQL modules (nested types).

Default Schema

Functions and tables registered under the "default" schema appear at the app's top-level module — no extra nesting.

mux.HandleFunc("default", "add", handler, ...)
mux.Table("default", &ItemsTable{})
# Functions at: function → app_name → add
{ function { my_app { add(a: 1, b: 2) } } }

# Tables at: app_name → items
{ my_app { items { id name } } }

You can customize the default schema name via AppInfo.DefaultSchema:

func (a *MyApp) Info() app.AppInfo {
return app.AppInfo{
Name: "my_app",
DefaultSchema: "main", // "main" schema = top-level (instead of "default")
// ...
}
}

Named Schemas (Nested Modules)

Any non-default schema creates a nested module:

mux.HandleFunc("admin", "user_count", handler, ...)
mux.HandleTableFunc("admin", "audit", handler, ...)
# Functions: function → app_name → schema_name → function_name
{ function { my_app { admin { user_count } } } }

# Table functions: app_name → schema_name → table_function_name
{ my_app { admin { admin_audit(args: { limit: 10 }) { id action } } } }

Naming Conventions

App Name → GraphQL Module

The app name becomes the top-level GraphQL module:

App NameModule Path
my_app{ my_app { ... } }
analytics{ analytics { ... } }

DS Name → Sub-Module

Data source names use dot notation: appName.dsName:

DS RegistrationGraphQL Path
my_app.store{ my_app { store { ... } } }
my_app.logs{ my_app { logs { ... } } }

Table Functions in Named Schemas

Table functions in named schemas get a prefixed name to avoid collisions:

SchemaNameGraphQL Field
defaultsearchsearch
adminauditadmin_audit
reportsdailyreports_daily

Reserved Names

These names cannot be used as app names:

  • function — conflicts with Function root type
  • mutation_function — conflicts with MutationFunction root type
  • core — reserved for system functions
  • _system — reserved for internal use
  • Names starting with _ — reserved

Example: Multi-Schema App

func (a *MyApp) Catalog(ctx context.Context) (catalog.Catalog, error) {
mux := app.New()

// Default schema — top-level
mux.HandleFunc("default", "version", versionHandler, app.Return(app.String))
mux.Table("default", &UsersTable{})

// Admin schema — nested module
mux.HandleFunc("admin", "stats", statsHandler, app.Return(app.Int64))
mux.HandleTableFunc("admin", "logs", logsHandler, ...)

// Reports schema — another nested module
mux.HandleTableFunc("reports", "daily", dailyHandler, ...)

return mux, nil
}

GraphQL schema:

# Functions
{ function { my_app { version } } }
{ function { my_app { admin { stats } } } }

# Tables and table functions
{ my_app { users { id name } } }
{ my_app { admin { admin_logs(args: {...}) { ... } } } }
{ my_app { reports { reports_daily(args: {...}) { ... } } } }