commit b68286805b2cbdd8161d657f743219af9df2bbf9
parent 57f4ab3b1b5c83ac7bc33724f378651afb96fad4
Author: brookjeynes <me@brookjeynes.dev>
Date: Sun, 7 Jun 2026 17:53:52 +1000
refactor: use canonical entity paths
Signed-off-by: brookjeynes <me@brookjeynes.dev>
Diffstat:
7 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/internal/server/album.go b/internal/server/album.go
@@ -7,6 +7,7 @@ import (
"lyrics/internal/db"
"lyrics/internal/domain"
"lyrics/internal/server/htmx"
+ "lyrics/internal/server/routes"
albumview "lyrics/internal/server/ui/views/album"
"net/http"
"strconv"
@@ -39,7 +40,7 @@ func (ss *ServerState) Album(w http.ResponseWriter, r *http.Request) {
}
if domain.Slug(albumTitle) != slug {
- htmx.HxRedirect(w, http.StatusMovedPermanently, fmt.Sprintf("/album/%d/%s", id, domain.Slug(albumTitle)))
+ htmx.HxRedirect(w, http.StatusMovedPermanently, routes.AlbumPath(domain.AlbumID(id), albumTitle))
return
}
diff --git a/internal/server/artist.go b/internal/server/artist.go
@@ -7,6 +7,7 @@ import (
"lyrics/internal/db"
"lyrics/internal/domain"
"lyrics/internal/server/htmx"
+ "lyrics/internal/server/routes"
artistview "lyrics/internal/server/ui/views/artist"
"net/http"
"strconv"
@@ -39,7 +40,7 @@ func (ss *ServerState) Artist(w http.ResponseWriter, r *http.Request) {
}
if domain.Slug(artistName) != slug {
- htmx.HxRedirect(w, http.StatusMovedPermanently, fmt.Sprintf("/artist/%d/%s", id, domain.Slug(artistName)))
+ htmx.HxRedirect(w, http.StatusMovedPermanently, routes.ArtistPath(domain.ArtistID(id), artistName))
return
}
diff --git a/internal/server/routes/routes.go b/internal/server/routes/routes.go
@@ -0,0 +1,45 @@
+package routes
+
+import (
+ "fmt"
+ "lyrics/internal/domain"
+)
+
+func Song(song domain.Song) string {
+ title := song.Title
+ if song.LatinTitle != nil {
+ title = *song.LatinTitle
+ }
+
+ return SongPath(song.ID, title)
+}
+
+func SongPath(id domain.SongID, title string) string {
+ return fmt.Sprintf("/song/%d/%s", id, domain.Slug(title))
+}
+
+func Album(album domain.Album) string {
+ title := album.Title
+ if album.LatinName != nil {
+ title = *album.LatinName
+ }
+
+ return AlbumPath(album.ID, title)
+}
+
+func AlbumPath(id domain.AlbumID, title string) string {
+ return fmt.Sprintf("/album/%d/%s", id, domain.Slug(title))
+}
+
+func Artist(artist domain.Artist) string {
+ name := artist.Name
+ if artist.LatinName != nil {
+ name = *artist.LatinName
+ }
+
+ return ArtistPath(artist.ID, name)
+}
+
+func ArtistPath(id domain.ArtistID, name string) string {
+ return fmt.Sprintf("/artist/%d/%s", id, domain.Slug(name))
+}
diff --git a/internal/server/song.go b/internal/server/song.go
@@ -7,6 +7,7 @@ import (
"lyrics/internal/db"
"lyrics/internal/domain"
"lyrics/internal/server/htmx"
+ "lyrics/internal/server/routes"
"lyrics/internal/server/ui/views/song"
"net/http"
"strconv"
@@ -39,7 +40,7 @@ func (ss *ServerState) Song(w http.ResponseWriter, r *http.Request) {
}
if domain.Slug(songTitle) != slug {
- htmx.HxRedirect(w, http.StatusMovedPermanently, fmt.Sprintf("/song/%d/%s", id, domain.Slug(songTitle)))
+ htmx.HxRedirect(w, http.StatusMovedPermanently, routes.SongPath(domain.SongID(id), songTitle))
return
}
diff --git a/internal/server/ui/views/album/album.templ b/internal/server/ui/views/album/album.templ
@@ -1,7 +1,7 @@
package album
import (
- "fmt"
+ "lyrics/internal/server/routes"
"lyrics/internal/server/ui/layouts/base"
"time"
)
@@ -21,7 +21,7 @@ templ Album(params AlbumParams) {
<ul>
for _, artist := range params.Album.Artists {
<li>
- <a href={ fmt.Sprintf("/artist/%d/%s", artist.Artist.ID, artist.Artist.Name) }>
+ <a href={ routes.Artist(artist.Artist) }>
{ artist.Artist.Name }
if artist.Artist.LatinName != nil {
<span>({ *artist.Artist.LatinName })</span>
@@ -35,7 +35,7 @@ templ Album(params AlbumParams) {
<ol>
for _, song := range params.Album.Songs {
<li>
- <a href={ fmt.Sprintf("/song/%d/%s", song.ID, song.Title) }>
+ <a href={ routes.Song(song) }>
{ song.Title }
if song.LatinTitle != nil {
<span>({ *song.LatinTitle })</span>
diff --git a/internal/server/ui/views/artist/artist.templ b/internal/server/ui/views/artist/artist.templ
@@ -1,7 +1,7 @@
package artist
import (
- "fmt"
+ "lyrics/internal/server/routes"
"lyrics/internal/server/ui/layouts/base"
"time"
)
@@ -32,7 +32,7 @@ templ Artist(params ArtistParams) {
<header>
<hgroup>
<h3>
- <a href={ fmt.Sprintf("/album/%d/%s", album.ID, album.Title) }>{ album.Title }</a>
+ <a href={ routes.Album(album) }>{ album.Title }</a>
</h3>
if album.LatinName != nil {
<span>({ *album.LatinName })</span>
@@ -42,7 +42,7 @@ templ Artist(params ArtistParams) {
for _, artist := range album.Artists {
if artist.Artist.ID != params.Artist.ID {
<li>
- <a href={ fmt.Sprintf("/artist/%d/%s", artist.Artist.ID, artist.Artist.Name) }>
+ <a href={ routes.Artist(artist.Artist) }>
{ artist.Artist.Name }
if artist.Artist.LatinName != nil {
<span>({ *artist.Artist.LatinName })</span>
@@ -57,7 +57,7 @@ templ Artist(params ArtistParams) {
<ol>
for _, song := range album.Songs {
<li>
- <a href={ fmt.Sprintf("/song/%d/%s", song.ID, song.Title) }>
+ <a href={ routes.Song(song) }>
{ song.Title }
if song.LatinTitle != nil {
<span>({ *song.LatinTitle })</span>
@@ -74,7 +74,7 @@ templ Artist(params ArtistParams) {
<ul>
for _, song := range params.Singles {
<li>
- <a href={ fmt.Sprintf("/song/%d/%s", song.ID, song.Title) }>
+ <a href={ routes.Song(song) }>
{ song.Title }
if song.LatinTitle != nil {
<span>({ *song.LatinTitle })</span>
@@ -89,7 +89,7 @@ templ Artist(params ArtistParams) {
<ul>
for _, song := range params.Featured {
<li>
- <a href={ fmt.Sprintf("/song/%d/%s", song.ID, song.Title) }>
+ <a href={ routes.Song(song) }>
{ song.Title }
if song.LatinTitle != nil {
<span>({ *song.LatinTitle })</span>
diff --git a/internal/server/ui/views/song/song.templ b/internal/server/ui/views/song/song.templ
@@ -1,8 +1,8 @@
package song
import (
- "fmt"
"lyrics/internal/domain"
+ "lyrics/internal/server/routes"
"lyrics/internal/server/ui/layouts/base"
"time"
)
@@ -22,7 +22,7 @@ templ Song(params SongParams) {
<ul>
for _, artist := range params.Song.Artists {
<li>
- <a href={ fmt.Sprintf("/artist/%d/%s", artist.Artist.ID, artist.Artist.Name) }>
+ <a href={ routes.Artist(artist.Artist) }>
{ artist.Artist.Name }
if artist.Artist.LatinName != nil {
<span>({ *artist.Artist.LatinName })</span>
@@ -45,7 +45,7 @@ templ Song(params SongParams) {
<ul>
for _, album := range params.Song.Albums {
<li>
- <a href={ fmt.Sprintf("/album/%d/%s", album.Album.ID, album.Album.Title) }>
+ <a href={ routes.Album(album.Album) }>
{ album.Album.Title }
if album.Album.LatinName != nil {
<span>({ *album.Album.LatinName })</span>