Admin and User Site Separation
Overview
Gojang follows a strict architectural separation between:
- User Site: Public-facing pages at
/
routes - Admin Panel: Staff-only management interface at
/admin
routes
Directory Structure
gojang/
├── admin/ # Admin panel (isolated)
│ ├── handler.go # Generic CRUD handlers
│ ├── models.go # Model registration
│ ├── registry.go # Reflection-based operations
│ ├── admin_renderer.go # Admin-specific renderer
│ ├── admin_routes.go # Admin route definitions
│ └── views/ # Admin templates
│ ├── admin_base.html
│ ├── admin_main.html
│ ├── model_index.html
│ ├── model_list.partial.html
│ ├── model_form.partial.html
│ └── model_delete.partial.html
│
├── http/
│ ├── handlers/ # User site handlers (isolated)
│ │ ├── auth.go
│ │ ├── pages.go
│ │ ├── posts.go
│ │ └── users.go
│ └── routes/ # User site routes
│ ├── pages.go
│ ├── posts.go
│ └── users.go
└── views/
├── renderers/
│ └── renderer.go # User site renderer
└── templates/ # User site templates
├── base.html
├── home.html
├── posts/
└── users/
Key Principles
1. Separate Renderers
User Site Renderer (renderers.Renderer
):
- Located in
gojang/views/renderers/renderer.go
- Uses
base.html
as layout - Handles user-facing templates only
Admin Renderer (admin.AdminRenderer
):
- Located in
gojang/admin/admin_renderer.go
- Uses
admin_base.html
as layout - Handles admin templates only
2. Separate Route Namespaces
User Routes (mounted at root):
r.Get("/", pageHandler.Home)
r.Get("/posts", postHandler.Index)
r.Get("/dashboard", pageHandler.Dashboard)
Admin Routes (mounted under /admin
with staff-only middleware):
r.Route("/admin", func(r chi.Router) {
r.Use(middleware.RequireStaff)
r.Get("/", adminHandler.Dashboard)
r.Get("/{model}", adminHandler.Index)
r.Post("/{model}", adminHandler.Create)
// ... generic CRUD for all models
})
3. No Cross-References
Don't mix admin templates or path-based checks inside user handlers. Keep user handlers focused on the public experience and admin handled by the generic panel.
4. Generic Admin Panel
The admin panel uses reflection-based CRUD that works for all models. To add a model to admin, register it in admin/models.go
and the admin UI provides CRUD automatically.
Migration from Mixed Architectures
When migrating from a project that mixed admin and user concerns, remove admin-specific code from user handlers, delete admin templates from user renderer, and rely on the generic admin package.
Benefits of Separation
- Simplicity
- Maintainability
- Security
- Easier testing
Verification
- Check user handlers do not reference
admin_*.html
or perform path-based admin detection - Check admin package is isolated (routes, renderer, templates)
- Test both sites independently