aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hergès <william@herges.fr>2025-10-03 18:40:45 +0200
committerWilliam Hergès <william@herges.fr>2025-10-03 18:40:45 +0200
commit0de89e6bc6a467b2cc4261ae65464f40119cc0ff (patch)
tree47ca3e894444950152b3ba0cf587f713d5aa7eaa
parent270f592fc65cd5553ccf7c0dc81431c3efdf67ab (diff)
feat(frontend): use htmx to dynamically navigate between pages
-rw-r--r--backend/data.go13
-rw-r--r--backend/home.go2
-rw-r--r--backend/logs.go3
-rw-r--r--backend/router.go18
-rw-r--r--backend/templates/base.html12
-rw-r--r--backend/templates/components.html (renamed from backend/templates/logs_display.html)0
-rw-r--r--backend/templates/home.html2
-rw-r--r--backend/templates/home_log.html6
-rw-r--r--backend/templates/log.html2
-rw-r--r--backend/templates/simple.html6
-rw-r--r--frontend/index.ts26
-rw-r--r--index.ts6
-rw-r--r--package.json4
13 files changed, 75 insertions, 25 deletions
diff --git a/backend/data.go b/backend/data.go
index 8922aca..cc61941 100644
--- a/backend/data.go
+++ b/backend/data.go
@@ -31,7 +31,7 @@ type data struct {
}
func (d *data) handleGeneric(w http.ResponseWriter, r *http.Request, name string, custom dataUsable) {
- cfg := r.Context().Value("config").(*Config)
+ cfg := r.Context().Value(configKey).(*Config)
if d.Domain == "" {
d.Domain = cfg.Domain
}
@@ -75,15 +75,20 @@ func (d *data) handleGeneric(w http.ResponseWriter, r *http.Request, name string
},
"next": func(i int) int { return i + 1 },
"before": func(i int) int { return i - 1 },
- }).ParseFS(templates, "templates/logs_display.html", fmt.Sprintf("templates/%s.html", name), "templates/base.html")
+ }).ParseFS(templates, "templates/components.html", fmt.Sprintf("templates/%s.html", name), "templates/base.html")
if err != nil {
panic(err)
}
+ exec := "base.html"
+ if r.Context().Value(isUpdateKey).(bool) {
+ exec = "body"
+ w.Header().Set("Updated-Title", d.Title())
+ }
if custom == nil {
- err = t.ExecuteTemplate(w, "base.html", d)
+ err = t.ExecuteTemplate(w, exec, d)
} else {
custom.SetData(d)
- err = t.ExecuteTemplate(w, "base.html", custom)
+ err = t.ExecuteTemplate(w, exec, custom)
}
if err != nil {
panic(err)
diff --git a/backend/home.go b/backend/home.go
index fd01318..b2a6dfa 100644
--- a/backend/home.go
+++ b/backend/home.go
@@ -66,7 +66,7 @@ func handleGenericRoot(w http.ResponseWriter, r *http.Request, name string) {
if c, ok := rootContent[name]; ok {
d.Content = c
} else {
- cfg := r.Context().Value("config").(*Config)
+ cfg := r.Context().Value(configKey).(*Config)
path := filepath.Join(cfg.RootFolder, name+".md")
b, err := os.ReadFile(path)
if err != nil {
diff --git a/backend/logs.go b/backend/logs.go
index 2901559..c663ffb 100644
--- a/backend/logs.go
+++ b/backend/logs.go
@@ -124,11 +124,12 @@ func handleLogList(w http.ResponseWriter, r *http.Request) {
if d == nil {
return
}
+ d.title = "logs"
d.handleGeneric(w, r, "home_log", d)
}
func handleLog(w http.ResponseWriter, r *http.Request) {
- cfg := r.Context().Value("config").(*Config)
+ cfg := r.Context().Value(configKey).(*Config)
slug := chi.URLParam(r, "slug")
path := filepath.Join(cfg.LogFolder, slug)
d, ok := logs[path]
diff --git a/backend/router.go b/backend/router.go
index 33c685d..22c77a4 100644
--- a/backend/router.go
+++ b/backend/router.go
@@ -15,7 +15,11 @@ import (
"github.com/go-chi/httplog/v3"
)
-const Version = "0.1.0"
+const (
+ Version = "0.1.0"
+ configKey = "config"
+ isUpdateKey = "is_update"
+)
//go:embed templates
var templates embed.FS
@@ -62,7 +66,17 @@ func NewRouter(debug bool, cfg *Config) *chi.Mux {
}))
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ctx := context.WithValue(r.Context(), "config", cfg)
+ ctx := context.WithValue(r.Context(), configKey, cfg)
+ next.ServeHTTP(w, r.WithContext(ctx))
+ })
+ })
+ r.Use(func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ val := false
+ if r.Header.Get("HX-Request") == "true" {
+ val = true
+ }
+ ctx := context.WithValue(r.Context(), isUpdateKey, val)
next.ServeHTTP(w, r.WithContext(ctx))
})
})
diff --git a/backend/templates/base.html b/backend/templates/base.html
index 68d3f8d..fec24ef 100644
--- a/backend/templates/base.html
+++ b/backend/templates/base.html
@@ -28,14 +28,14 @@
<header>
<img src="{{ static .Logo.Header }}" alt="Logo">
<nav>
- {{ range .Links }}<a href="{{ .URL }}">{{ .Name }}</a>{{end}}
+ {{ range .Links }}
+ <a href="{{ .URL }}">
+ {{ .Name }}
+ </a>
+ {{end}}
</nav>
</header>
-{{ if .Article }}
-<main>{{ template "body" . }}</main>
-{{ else }}
-<article>{{ template "body" . }}</article>
-{{ end }}
+{{ template "body" . }}
<footer>
<p>&copy; 2025 - Anhgelus Morthuuzh</p>
<p>«&thinsp;{{ .Quote }}&thinsp;»</p>
diff --git a/backend/templates/logs_display.html b/backend/templates/components.html
index adafacf..adafacf 100644
--- a/backend/templates/logs_display.html
+++ b/backend/templates/components.html
diff --git a/backend/templates/home.html b/backend/templates/home.html
index 1a6b158..de9d2af 100644
--- a/backend/templates/home.html
+++ b/backend/templates/home.html
@@ -1,4 +1,5 @@
{{define "body"}}
+<main id="content">
<div class="introduction">
<h1>logs</h1>
<p>
@@ -6,4 +7,5 @@
</p>
</div>
{{ template "logs_display" . }}
+</main>
{{end}}
diff --git a/backend/templates/home_log.html b/backend/templates/home_log.html
index 2301ffd..c57272c 100644
--- a/backend/templates/home_log.html
+++ b/backend/templates/home_log.html
@@ -1 +1,5 @@
-{{define "body"}}{{ template "logs_display" . }}{{end}}
+{{define "body"}}
+<main id="content">
+{{ template "logs_display" . }}
+</main>
+{{end}}
diff --git a/backend/templates/log.html b/backend/templates/log.html
index 57948d4..789bdae 100644
--- a/backend/templates/log.html
+++ b/backend/templates/log.html
@@ -1,5 +1,5 @@
{{define "body"}}
-<article>
+<article id="content">
<h1>{{ .LogTitle }}</h1>
<p>
{{ .Description }}
diff --git a/backend/templates/simple.html b/backend/templates/simple.html
index dd00397..7b4f6d3 100644
--- a/backend/templates/simple.html
+++ b/backend/templates/simple.html
@@ -1 +1,5 @@
-{{ define "body" }}{{ .Content }}{{ end }}
+{{ define "body" }}
+<main id="content">
+{{ .Content }}
+</main>
+{{ end }}
diff --git a/frontend/index.ts b/frontend/index.ts
new file mode 100644
index 0000000..cd3c455
--- /dev/null
+++ b/frontend/index.ts
@@ -0,0 +1,26 @@
+import htmx from "htmx.org";
+
+function setupAnchors() {
+ document.querySelectorAll("a").forEach(e => {
+ if (!e.href.startsWith(window.location.origin)) {
+ e.target = "_blank";
+ return
+ }
+ if (e.hasAttribute("hx-trigger")) return;
+ e.setAttribute("hx-get", e.href)
+ e.setAttribute("hx-trigger", "click")
+ e.setAttribute("hx-target", "#content")
+ e.setAttribute("hx-swap", "outerHTML show:top")
+ htmx.process(e)
+ });
+}
+
+// updating history and window title
+document.addEventListener("htmx:afterSettle", e => {
+ const title = e.detail.xhr.getResponseHeader("Updated-Title")
+ if (title?.length != 0) document.title = title
+ window.history.pushState({}, "", e.detail.pathInfo.finalRequestPath)
+ setupAnchors()
+})
+
+setupAnchors()
diff --git a/index.ts b/index.ts
deleted file mode 100644
index 72679ce..0000000
--- a/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import 'htmx.org';
-
-document.querySelectorAll("a").forEach(e => {
- if (e.href.startsWith(window.location.origin)) return;
- e.target = "_blank";
-});
diff --git a/package.json b/package.json
index 543b5bf..0c88ca7 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
{
"name": "small-web",
- "module": "index.ts",
+ "module": "frontend/index.ts",
"type": "module",
"private": true,
"scripts": {
"build:sass": "sass --no-source-map --style=compressed frontend/scss/main.scss dist/styles.css",
"watch:sass": "sass --watch frontend/scss/main.scss dist/styles.css",
- "build:js": "bun build ./index.ts --outdir ./dist --minify",
+ "build:js": "bun build frontend/index.ts --outdir ./dist --minify",
"build": "bun run build:sass && bun run build:js"
},
"devDependencies": {