Signal dependent tabs to re-fetch when plan ladders change. operator_plan_ladders handlers set HX-Trigger: planLadderMutation on create/update/delete and tier operations so Org Types' plan dropdowns refresh. operator.html adds explanatory comments and hx-trigger attrs so Org Types, Grants, and Products panes listen for productMutation, planLadderMutation, and entitlementMutation
Embedded Assets
This package provides embedded static files, templates, and configuration using Go's embed directive.
Overview
All assets are embedded at compile time, producing a single binary with no external file dependencies.
package embeds
//go:embed static
var Static embed.FS
//go:embed templates
var Templates embed.FS
//go:embed mc-config.yaml
var Config embed.FS
Directory Structure
internal/embeds/
├── embeds.go # Embed directives
├── mc-config.yaml # Default configuration template
├── static/ # Static assets (CSS, JS, images)
│ ├── bootstrap.css
│ ├── bootstrap.bundle.js
│ ├── htmx.min.js
│ └── favicon*.png
└── templates/ # HTML templates
├── index.html # Main page template
└── partials/ # HTMX partial templates
├── fedwiki_sites.html
├── fedwiki_create_form.html
├── fedwiki_create_success.html
├── fedwiki_delete_confirm.html
└── fedwiki_delete_success.html
Static Assets
Serving Static Files
staticFS, _ := fs.Sub(embeds.Static, "static")
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))
Included Libraries
bootstrap.css(5.3.x) - CSS frameworkbootstrap.bundle.js(5.3.x) - Bootstrap JS (includes Popper)htmx.min.js(2.0.4) - HTMX for dynamic content
Favicons
Standard favicon set for various platforms:
favicon.ico- Traditional faviconfavicon-16x16.png,favicon-32x32.png- Standard sizesapple-touch-icon.png- iOS home screenandroid-chrome-*.png- Android home screensite.webmanifest- PWA manifest
Templates
Main Page Template (index.html)
The full HTML page that serves as the application shell:
<!DOCTYPE html>
<html>
<head>
<!-- Meta, CSS, HTMX -->
</head>
<body>
<!-- Navigation -->
<!-- Content sections with HTMX triggers -->
<div hx-get="/partials/fedwiki/sites"
hx-trigger="load, refreshSites from:body">
<!-- Loading spinner -->
</div>
<!-- Modals -->
<div class="modal" id="createSiteModal">...</div>
<!-- Scripts -->
</body>
</html>
Partial Templates (partials/)
HTML fragments returned by HTMX handlers. These are not full pages.
Naming Convention
{feature}_{action}.html
Examples:
fedwiki_sites.html- Sites list displayfedwiki_create_form.html- Site creation formfedwiki_create_success.html- Creation success messagefedwiki_delete_confirm.html- Delete confirmation dialogfedwiki_delete_success.html- Deletion success message
Template Data Pattern
Each partial has a corresponding Go struct for its data:
// In fedwiki_partials.go
type SitesData struct {
Sites []SiteViewModel
CurrentCount int64
Quota int64
IsMember bool
CanCreate bool
Error string
}
HTMX Patterns in Templates
Loading Content on Page Load
<div hx-get="/partials/fedwiki/sites"
hx-trigger="load, refreshSites from:body"
hx-swap="innerHTML">
<!-- Initial loading spinner -->
<div class="spinner-border"></div>
</div>
Form Submission
<form hx-post="/partials/fedwiki/sites"
hx-swap="innerHTML"
hx-target="#createSiteModalBody">
<!-- Form fields -->
<button type="submit">
<span class="spinner-border d-none" id="spinner"></span>
Create Site
</button>
</form>
Loading Button into Modal
<button data-bs-toggle="modal"
data-bs-target="#createSiteModal"
hx-get="/partials/fedwiki/create-form"
hx-target="#createSiteModalBody">
Create Site
</button>
Conditional Button State
<button {{ if .CanCreate }}
hx-get="/partials/fedwiki/create-form"
{{ else }}
disabled title="Site limit reached"
{{ end }}>
Create Site
</button>
Spinner Pattern
Spinners are hidden by default and shown during HTMX requests:
<!-- CSS to show spinner during request -->
<style>.htmx-request #createSpinner { display: inline-block !important; }</style>
<!-- Spinner hidden by default -->
<span class="spinner-border d-none" id="createSpinner"></span>
The htmx-request class is automatically added to elements during requests.
Configuration Template
mc-config.yaml provides a default configuration template that can be extracted:
// Extract default config
configData, _ := embeds.Config.ReadFile("mc-config.yaml")
This is used by the init command to create a starter configuration file.
Usage
Accessing Templates
import "git.coopcloud.tech/wiki-cafe/member-console/internal/embeds"
// For full page templates
tmpl, err := template.ParseFS(embeds.Templates, "templates/index.html")
// For partial templates
partialFS, _ := fs.Sub(embeds.Templates, "templates/partials")
tmpl, err := template.ParseFS(partialFS, "*.html")
Accessing Static Files
// Serve static files
staticFS, _ := fs.Sub(embeds.Static, "static")
http.Handle("/static/", http.FileServer(http.FS(staticFS)))