README
¶
Admin Shell Example
This example is an opinionated go-admin shell for projects that use the goliatone stack.
It is intentionally small, but complete enough to:
- boot the server,
- show a useful root page at
/, - protect
/adminbehind auth, - render a real login UI at
/admin/login, - and provide a
Coredependency container you can reuse in new projects.
Goal
Create a reusable app-shell baseline that wires:
go-configfor config loading,go-router/Fiber for HTTP server + routing,go-authfor login/session auth,go-admin/quickstartfor admin bootstrap and UI routes.
What We Built
examples/admin-shell/cmd/admin/main.goexamples/admin-shell/internal/config/config.goexamples/admin-shell/internal/core/core.goexamples/admin-shell/internal/core/auth.goexamples/admin-shell/internal/http/routes.goexamples/admin-shell/config/app.yamlexamples/admin-shell/taskfile
Step-By-Step Setup Process
1. Scaffold the Example Structure
We started by creating a focused structure for an app-shell:
examples/admin-shell/
cmd/admin/main.go
config/app.yaml
internal/config/config.go
internal/core/core.go
internal/core/auth.go
internal/http/routes.go
taskfile
2. Add Configuration Loading (go-config)
In internal/config/config.go we added:
AppConfigwithServer,Admin,Auth, andFeatures.Defaults()for baseline values.Load(ctx)that merges:- struct defaults,
- optional config file,
- environment overrides.
Environment override convention:
- prefix:
APP_ - delimiter:
__ - examples:
APP_SERVER__ADDRESS=":9090"APP_ADMIN__BASE_PATH="/control"APP_AUTH__SIGNING_KEY="change-me"
3. Build a Lightweight DI Container (Core)
In internal/core/core.go we introduced type Core struct to carry app dependencies:
- config and logger,
- server/router/fiber app,
- admin instance,
- auth components,
- feature gate,
- demo identity/token metadata.
core.New(...) is the composition root and is where wiring happens.
4. Wire go-admin with Quickstart
In core.New(...):
- create
admin.Configviaquickstart.NewAdminConfig(...), - construct admin via
quickstart.NewAdmin(...), - provide a feature gate from configured defaults.
5. Wire go-auth
In internal/core/auth.go:
- define demo identity provider (
username/email/password), - create
auth.Auther, - create
auth.RouteAuthenticator, - attach auth + authorizer to admin via
quickstart.WithGoAuth(...).
Important detail:
GetTokenLookup() is configured as:
header:Authorization,cookie:<contextKey>
This is required so browser login sessions (cookie) and API bearer tokens both work.
6. Add View Engine + Static Assets
To render login/admin pages, we wired:
quickstart.NewViewEngine(...)using embedded client templates,quickstart.NewFiberServer(...)to use that view engine,quickstart.NewStaticAssets(...)to serve/admin/assets/....
7. Register Auth + Admin UI Routes
This is the key wiring for protected UI:
quickstart.RegisterAuthUIRoutes(...)quickstart.RegisterAdminUIRoutes(...)with auth wrapper
Result:
- unauthenticated
GET /admin->302redirect to/admin/login, GET /admin/loginrenders login page,- successful login sets auth cookie and redirects to
/admin.
8. Register Shell Utility Routes
In internal/http/routes.go we kept lightweight shell routes:
GET /status/links/debug-friendly page,GET /healthz,GET /readyz.
The root page includes quick links to /admin and /admin/login.
9. Add Developer Task Commands
examples/admin-shell/taskfile includes shell-focused commands:
dev:servedev:serve:quietdev:serve:proddev:testdev:fmtdev:vetdev:checkdev:curl:homedev:curl:healthdev:curl:readydev:curl:admin
Run Guide
1. Start the app
./examples/admin-shell/taskfile dev:serve
or:
go run ./examples/admin-shell/cmd/admin
2. Open endpoints
From current examples/admin-shell/config/app.yaml, default address is :8383:
http://localhost:8383/http://localhost:8383/healthzhttp://localhost:8383/readyzhttp://localhost:8383/adminhttp://localhost:8383/admin/login
3. Login credentials
Default demo credentials:
superadmin/superadmin.pwdadmin/admin.pwdjane.smith/jane.smith.pwdtranslator/translator.pwdjohn.doe/john.doe.pwdviewer/viewer.pwd
The login page also renders this credential list as a local-dev helper snippet.
Verification Checklist
After startup, verify these exact behaviors:
GET /adminreturns redirect (302) to/admin/login.GET /admin/loginreturns200and HTML login page.POST /admin/loginwith demo credentials sets auth cookie and redirects to/admin.GET /adminwith that cookie returns200.
Example cURL:
# expect 302 + Location: /admin/login
curl -i http://localhost:8383/admin
# login and store cookie
curl -i -c /tmp/admin-shell.cookies -X POST \
-d 'identifier=admin&password=admin.pwd' \
http://localhost:8383/admin/login
# authenticated admin page
curl -i -b /tmp/admin-shell.cookies http://localhost:8383/admin
“Cannot GET /admin” Fix Summary
We hit this during setup and fixed it by adding missing UI/auth wiring:
- add view engine,
- add static assets,
- register auth UI routes,
- register admin UI routes with auth wrapper,
- support cookie lookup in token config.
Without those, only API/admin backend routes existed and /admin could resolve to 404/“Cannot GET”.
Configuration Notes
Default config file:
examples/admin-shell/config/app.yaml
Override config file:
APP_CONFIG_PATH=/absolute/path/to/app.yaml
Common env overrides:
APP_SERVER__ADDRESS=":9090"APP_SERVER__PRINT_ROUTES=falseAPP_ADMIN__BASE_PATH="/control"APP_AUTH__SIGNING_KEY="replace-me"APP_FEATURES__SEARCH=false
Next Extensions
Natural next changes if you clone this shell into another project:
- replace demo identity provider with real user store,
- plug real role/resource mappings into go-auth claims,
- add project modules under admin registration,
- add persistence and migrations,
- add project-specific home diagnostics to
/.