diff --git a/app/cmd/server/server.go b/app/cmd/server/server.go
index 7d40808..e7b847f 100644
--- a/app/cmd/server/server.go
+++ b/app/cmd/server/server.go
@@ -3,8 +3,11 @@ package server
 import (
 	"dankmuzikk/config"
 	"dankmuzikk/db"
-	"dankmuzikk/handlers"
 	"dankmuzikk/handlers/apis"
+	"dankmuzikk/handlers/middlewares/auth"
+	"dankmuzikk/handlers/middlewares/contenttype"
+	"dankmuzikk/handlers/middlewares/ismobile"
+	"dankmuzikk/handlers/middlewares/theme"
 	"dankmuzikk/handlers/pages"
 	"dankmuzikk/log"
 	"dankmuzikk/models"
@@ -53,7 +56,7 @@ func StartServer(staticFS embed.FS) error {
 
 	jwtUtil := jwt.NewJWTImpl()
 
-	gHandler := handlers.NewHandler(profileRepo, jwtUtil)
+	authMw := auth.New(profileRepo, jwtUtil)
 
 	///////////// Pages and files /////////////
 	pagesHandler := http.NewServeMux()
@@ -74,16 +77,16 @@ func StartServer(staticFS embed.FS) error {
 	pagesHandler.Handle("/muzikkx/", http.StripPrefix("/muzikkx", http.FileServer(http.Dir(config.Env().YouTube.MusicDir))))
 
 	pagesRouter := pages.NewPagesHandler(profileRepo, playlistsService, jwtUtil, &search.ScraperSearch{}, downloadService, historyService, songsService)
-	pagesHandler.HandleFunc("/", gHandler.OptionalAuthPage(pagesRouter.HandleHomePage))
-	pagesHandler.HandleFunc("GET /signup", gHandler.AuthPage(pagesRouter.HandleSignupPage))
-	pagesHandler.HandleFunc("GET /login", gHandler.AuthPage(pagesRouter.HandleLoginPage))
-	pagesHandler.HandleFunc("GET /profile", gHandler.AuthPage(pagesRouter.HandleProfilePage))
-	pagesHandler.HandleFunc("GET /about", gHandler.NoAuthPage(pagesRouter.HandleAboutPage))
-	pagesHandler.HandleFunc("GET /playlists", gHandler.AuthPage(pagesRouter.HandlePlaylistsPage))
-	pagesHandler.HandleFunc("GET /playlist/{playlist_id}", gHandler.AuthPage(pagesRouter.HandleSinglePlaylistPage))
-	pagesHandler.HandleFunc("GET /song/{song_id}", gHandler.OptionalAuthPage(pagesRouter.HandleSingleSongPage))
-	pagesHandler.HandleFunc("GET /privacy", gHandler.NoAuthPage(pagesRouter.HandlePrivacyPage))
-	pagesHandler.HandleFunc("GET /search", gHandler.OptionalAuthPage(pagesRouter.HandleSearchResultsPage))
+	pagesHandler.HandleFunc("/", contenttype.Html(authMw.OptionalAuthPage(pagesRouter.HandleHomePage)))
+	pagesHandler.HandleFunc("GET /signup", contenttype.Html(authMw.AuthPage(pagesRouter.HandleSignupPage)))
+	pagesHandler.HandleFunc("GET /login", contenttype.Html(authMw.AuthPage(pagesRouter.HandleLoginPage)))
+	pagesHandler.HandleFunc("GET /profile", contenttype.Html(authMw.AuthPage(pagesRouter.HandleProfilePage)))
+	pagesHandler.HandleFunc("GET /about", contenttype.Html(pagesRouter.HandleAboutPage))
+	pagesHandler.HandleFunc("GET /playlists", contenttype.Html(authMw.AuthPage(pagesRouter.HandlePlaylistsPage)))
+	pagesHandler.HandleFunc("GET /playlist/{playlist_id}", contenttype.Html(authMw.AuthPage(pagesRouter.HandleSinglePlaylistPage)))
+	pagesHandler.HandleFunc("GET /song/{song_id}", contenttype.Html(authMw.OptionalAuthPage(pagesRouter.HandleSingleSongPage)))
+	pagesHandler.HandleFunc("GET /privacy", contenttype.Html(pagesRouter.HandlePrivacyPage))
+	pagesHandler.HandleFunc("GET /search", contenttype.Html(authMw.OptionalAuthPage(pagesRouter.HandleSearchResultsPage)))
 
 	///////////// APIs /////////////
 
@@ -102,25 +105,25 @@ func StartServer(staticFS embed.FS) error {
 	apisHandler.HandleFunc("/login/google/callback", googleLoginApi.HandleGoogleOAuthLoginCallback)
 	apisHandler.HandleFunc("GET /logout", apis.HandleLogout)
 	apisHandler.HandleFunc("GET /search-suggestion", apis.HandleSearchSuggestions)
-	apisHandler.HandleFunc("GET /song", gHandler.OptionalAuthApi(songApi.HandlePlaySong))
-	apisHandler.HandleFunc("GET /song/single", gHandler.OptionalAuthApi(songApi.HandleGetSong))
-	apisHandler.HandleFunc("PUT /song/playlist", gHandler.AuthApi(playlistsApi.HandleToggleSongInPlaylist))
-	apisHandler.HandleFunc("PUT /song/playlist/plays", gHandler.AuthApi(songApi.HandleIncrementSongPlaysInPlaylist))
-	apisHandler.HandleFunc("PUT /song/playlist/upvote", gHandler.AuthApi(songApi.HandleUpvoteSongPlaysInPlaylist))
-	apisHandler.HandleFunc("PUT /song/playlist/downvote", gHandler.AuthApi(songApi.HandleDownvoteSongPlaysInPlaylist))
-	apisHandler.HandleFunc("GET /playlist/all", gHandler.AuthApi(playlistsApi.HandleGetPlaylistsForPopover))
-	apisHandler.HandleFunc("GET /playlist", gHandler.AuthApi(playlistsApi.HandleGetPlaylist))
-	apisHandler.HandleFunc("POST /playlist", gHandler.AuthApi(playlistsApi.HandleCreatePlaylist))
-	apisHandler.HandleFunc("PUT /playlist/public", gHandler.AuthApi(playlistsApi.HandleTogglePublicPlaylist))
-	apisHandler.HandleFunc("PUT /playlist/join", gHandler.AuthApi(playlistsApi.HandleToggleJoinPlaylist))
-	apisHandler.HandleFunc("DELETE /playlist", gHandler.AuthApi(playlistsApi.HandleDeletePlaylist))
-	apisHandler.HandleFunc("GET /playlist/zip", gHandler.AuthApi(playlistsApi.HandleDonwnloadPlaylist))
-	apisHandler.HandleFunc("GET /history/{page}", gHandler.AuthApi(historyApi.HandleGetMoreHistoryItems))
+	apisHandler.HandleFunc("GET /song", authMw.OptionalAuthApi(songApi.HandlePlaySong))
+	apisHandler.HandleFunc("GET /song/single", authMw.OptionalAuthApi(songApi.HandleGetSong))
+	apisHandler.HandleFunc("PUT /song/playlist", authMw.AuthApi(playlistsApi.HandleToggleSongInPlaylist))
+	apisHandler.HandleFunc("PUT /song/playlist/plays", authMw.AuthApi(songApi.HandleIncrementSongPlaysInPlaylist))
+	apisHandler.HandleFunc("PUT /song/playlist/upvote", authMw.AuthApi(songApi.HandleUpvoteSongPlaysInPlaylist))
+	apisHandler.HandleFunc("PUT /song/playlist/downvote", authMw.AuthApi(songApi.HandleDownvoteSongPlaysInPlaylist))
+	apisHandler.HandleFunc("GET /playlist/all", authMw.AuthApi(playlistsApi.HandleGetPlaylistsForPopover))
+	apisHandler.HandleFunc("GET /playlist", authMw.AuthApi(playlistsApi.HandleGetPlaylist))
+	apisHandler.HandleFunc("POST /playlist", authMw.AuthApi(playlistsApi.HandleCreatePlaylist))
+	apisHandler.HandleFunc("PUT /playlist/public", authMw.AuthApi(playlistsApi.HandleTogglePublicPlaylist))
+	apisHandler.HandleFunc("PUT /playlist/join", authMw.AuthApi(playlistsApi.HandleToggleJoinPlaylist))
+	apisHandler.HandleFunc("DELETE /playlist", authMw.AuthApi(playlistsApi.HandleDeletePlaylist))
+	apisHandler.HandleFunc("GET /playlist/zip", authMw.AuthApi(playlistsApi.HandleDonwnloadPlaylist))
+	apisHandler.HandleFunc("GET /history/{page}", authMw.AuthApi(historyApi.HandleGetMoreHistoryItems))
 
 	applicationHandler := http.NewServeMux()
-	applicationHandler.Handle("/", pagesHandler)
-	applicationHandler.Handle("/api/", http.StripPrefix("/api", apisHandler))
+	applicationHandler.Handle("/", ismobile.Handler(theme.Handler(pagesHandler)))
+	applicationHandler.Handle("/api/", ismobile.Handler(theme.Handler(http.StripPrefix("/api", apisHandler))))
 
 	log.Info("Starting http server at port " + config.Env().Port)
-	return http.ListenAndServe(":"+config.Env().Port, m.Middleware(applicationHandler))
+	return http.ListenAndServe(":"+config.Env().Port, ismobile.Handler(theme.Handler(m.Middleware(applicationHandler))))
 }
diff --git a/app/handlers/apis/email_login.go b/app/handlers/apis/email_login.go
index 6d0bc64..f72e521 100644
--- a/app/handlers/apis/email_login.go
+++ b/app/handlers/apis/email_login.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"dankmuzikk/config"
 	"dankmuzikk/entities"
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
 	"dankmuzikk/log"
 	"dankmuzikk/services/login"
 	"dankmuzikk/views/components/otp"
@@ -50,7 +50,7 @@ func (e *emailLoginApi) HandleEmailLogin(w http.ResponseWriter, r *http.Request)
 	}
 
 	http.SetCookie(w, &http.Cookie{
-		Name:     handlers.VerificationTokenKey,
+		Name:     auth.VerificationTokenKey,
 		Value:    verificationToken,
 		HttpOnly: true,
 		Path:     "/api/verify-otp",
@@ -87,7 +87,7 @@ func (e *emailLoginApi) HandleEmailSignup(w http.ResponseWriter, r *http.Request
 	}
 
 	http.SetCookie(w, &http.Cookie{
-		Name:     handlers.VerificationTokenKey,
+		Name:     auth.VerificationTokenKey,
 		Value:    verificationToken,
 		HttpOnly: true,
 		Path:     "/api/verify-otp",
@@ -98,7 +98,7 @@ func (e *emailLoginApi) HandleEmailSignup(w http.ResponseWriter, r *http.Request
 }
 
 func (e *emailLoginApi) HandleEmailOTPVerification(w http.ResponseWriter, r *http.Request) {
-	verificationToken, err := r.Cookie(handlers.VerificationTokenKey)
+	verificationToken, err := r.Cookie(auth.VerificationTokenKey)
 	if err != nil {
 		// w.Write([]byte("Invalid verification token"))
 		status.
@@ -148,7 +148,7 @@ func (e *emailLoginApi) HandleEmailOTPVerification(w http.ResponseWriter, r *htt
 	}
 
 	http.SetCookie(w, &http.Cookie{
-		Name:     handlers.SessionTokenKey,
+		Name:     auth.SessionTokenKey,
 		Value:    sessionToken,
 		HttpOnly: true,
 		Path:     "/",
diff --git a/app/handlers/apis/google_login.go b/app/handlers/apis/google_login.go
index 2a9a07f..38dd83f 100644
--- a/app/handlers/apis/google_login.go
+++ b/app/handlers/apis/google_login.go
@@ -3,7 +3,7 @@ package apis
 import (
 	"context"
 	"dankmuzikk/config"
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
 	"dankmuzikk/log"
 	"dankmuzikk/services/login"
 	"dankmuzikk/views/components/status"
@@ -57,7 +57,7 @@ func (g *googleLoginApi) HandleGoogleOAuthLoginCallback(w http.ResponseWriter, r
 	}
 
 	http.SetCookie(w, &http.Cookie{
-		Name:     handlers.SessionTokenKey,
+		Name:     auth.SessionTokenKey,
 		Value:    sessionToken,
 		HttpOnly: true,
 		Path:     "/",
diff --git a/app/handlers/apis/history.go b/app/handlers/apis/history.go
index ab8da0b..ff1f4d6 100644
--- a/app/handlers/apis/history.go
+++ b/app/handlers/apis/history.go
@@ -3,7 +3,7 @@ package apis
 import (
 	"bytes"
 	"dankmuzikk/entities"
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
 	"dankmuzikk/log"
 	"dankmuzikk/services/history"
 	"dankmuzikk/views/components/playlist"
@@ -24,7 +24,7 @@ func NewHistoryApi(service *history.Service) *historyApi {
 }
 
 func (h *historyApi) HandleGetMoreHistoryItems(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.WriteHeader(http.StatusUnauthorized)
 		return
diff --git a/app/handlers/apis/logout.go b/app/handlers/apis/logout.go
index 6e1f926..2841691 100644
--- a/app/handlers/apis/logout.go
+++ b/app/handlers/apis/logout.go
@@ -2,13 +2,13 @@ package apis
 
 import (
 	"dankmuzikk/config"
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
 	"net/http"
 )
 
 func HandleLogout(w http.ResponseWriter, r *http.Request) {
 	http.SetCookie(w, &http.Cookie{
-		Name:   handlers.SessionTokenKey,
+		Name:   auth.SessionTokenKey,
 		Value:  "",
 		Path:   "/",
 		Domain: config.Env().Hostname,
diff --git a/app/handlers/apis/playlist.go b/app/handlers/apis/playlist.go
index 879c98b..15c3eec 100644
--- a/app/handlers/apis/playlist.go
+++ b/app/handlers/apis/playlist.go
@@ -3,7 +3,7 @@ package apis
 import (
 	"context"
 	"dankmuzikk/entities"
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
 	"dankmuzikk/log"
 	"dankmuzikk/services/playlists"
 	"dankmuzikk/services/playlists/songs"
@@ -26,7 +26,7 @@ func NewPlaylistApi(service *playlists.Service, songService *songs.Service) *pla
 }
 
 func (p *playlistApi) HandleCreatePlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -57,7 +57,7 @@ func (p *playlistApi) HandleCreatePlaylist(w http.ResponseWriter, r *http.Reques
 }
 
 func (p *playlistApi) HandleToggleSongInPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -89,7 +89,7 @@ func (p *playlistApi) HandleToggleSongInPlaylist(w http.ResponseWriter, r *http.
 }
 
 func (p *playlistApi) HandleTogglePublicPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -116,7 +116,7 @@ func (p *playlistApi) HandleTogglePublicPlaylist(w http.ResponseWriter, r *http.
 }
 
 func (p *playlistApi) HandleToggleJoinPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -145,7 +145,7 @@ func (p *playlistApi) HandleToggleJoinPlaylist(w http.ResponseWriter, r *http.Re
 }
 
 func (p *playlistApi) HandleGetPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -167,7 +167,7 @@ func (p *playlistApi) HandleGetPlaylist(w http.ResponseWriter, r *http.Request)
 }
 
 func (p *playlistApi) HandleDeletePlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -190,7 +190,7 @@ func (p *playlistApi) HandleDeletePlaylist(w http.ResponseWriter, r *http.Reques
 }
 
 func (p *playlistApi) HandleGetPlaylistsForPopover(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -214,7 +214,7 @@ func (p *playlistApi) HandleGetPlaylistsForPopover(w http.ResponseWriter, r *htt
 }
 
 func (p *playlistApi) HandleDonwnloadPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.WriteHeader(http.StatusUnauthorized)
 		w.Write([]byte("🤷‍♂️"))
diff --git a/app/handlers/apis/songs.go b/app/handlers/apis/songs.go
index 2fbb301..a9e1fc2 100644
--- a/app/handlers/apis/songs.go
+++ b/app/handlers/apis/songs.go
@@ -1,7 +1,7 @@
 package apis
 
 import (
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
 	"dankmuzikk/log"
 	"dankmuzikk/services/history"
 	"dankmuzikk/services/playlists/songs"
@@ -30,7 +30,7 @@ func NewDownloadHandler(
 }
 
 func (s *songDownloadHandler) HandleIncrementSongPlaysInPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -55,7 +55,7 @@ func (s *songDownloadHandler) HandleIncrementSongPlaysInPlaylist(w http.Response
 }
 
 func (s *songDownloadHandler) HandleUpvoteSongPlaysInPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -82,7 +82,7 @@ func (s *songDownloadHandler) HandleUpvoteSongPlaysInPlaylist(w http.ResponseWri
 }
 
 func (s *songDownloadHandler) HandleDownvoteSongPlaysInPlaylist(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		w.Write([]byte("🤷‍♂️"))
 		return
@@ -116,7 +116,7 @@ func (s *songDownloadHandler) HandlePlaySong(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if profileIdCorrect {
 		err := s.historyService.AddSongToHistory(id, profileId)
 		if err != nil {
diff --git a/app/handlers/handler.go b/app/handlers/middlewares/auth/auth.go
similarity index 55%
rename from app/handlers/handler.go
rename to app/handlers/middlewares/auth/auth.go
index 15ff944..b17f2a3 100644
--- a/app/handlers/handler.go
+++ b/app/handlers/middlewares/auth/auth.go
@@ -1,52 +1,50 @@
-package handlers
+package auth
 
 import (
 	"context"
 	"dankmuzikk/config"
 	"dankmuzikk/db"
 	"dankmuzikk/entities"
+	"dankmuzikk/handlers/middlewares/contenttype"
 	"dankmuzikk/models"
 	"dankmuzikk/services/jwt"
 	"net/http"
 	"slices"
-	"strings"
+)
+
+// Cookie keys
+const (
+	VerificationTokenKey = "verification-token"
+	SessionTokenKey      = "token"
+)
+
+// Context keys
+const (
+	ProfileIdKey       = "profile-id"
+	PlaylistPermission = "playlist-permission"
 )
 
 var noAuthPaths = []string{"/login", "/signup"}
 
-// Handler is handler for pages and APIs, where it wraps the common stuff in one place.
-type Handler struct {
+type mw struct {
 	profileRepo db.GORMDBGetter
 	jwtUtil     jwt.Decoder[jwt.Json]
 }
 
-// NewHandler returns a new AuthHandler instance.
+// New returns a new auth middle ware instance.
 // Using a GORMDBGetter because this is supposed to be a light fetch,
 // Where BaseDB doesn't provide column selection yet :(
-func NewHandler(
+func New(
 	accountRepo db.GORMDBGetter,
 	jwtUtil jwt.Decoder[jwt.Json],
-) *Handler {
-	return &Handler{accountRepo, jwtUtil}
-}
-
-// OptionalAuthPage authenticates a page's handler optionally (without redirection).
-func (a *Handler) OptionalAuthPage(h http.HandlerFunc) http.HandlerFunc {
-	return a.NoAuthPage(func(w http.ResponseWriter, r *http.Request) {
-		profile, err := a.authenticate(r)
-		if err != nil {
-			h(w, r)
-			return
-		}
-		ctx := context.WithValue(r.Context(), ProfileIdKey, profile.Id)
-		h(w, r.WithContext(ctx))
-	})
+) *mw {
+	return &mw{accountRepo, jwtUtil}
 }
 
 // AuthPage authenticates a page's handler.
-func (a *Handler) AuthPage(h http.HandlerFunc) http.HandlerFunc {
-	return a.NoAuthPage(func(w http.ResponseWriter, r *http.Request) {
-		htmxRedirect := IsNoLayoutPage(r)
+func (a *mw) AuthPage(h http.HandlerFunc) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		htmxRedirect := contenttype.IsNoLayoutPage(r)
 		profile, err := a.authenticate(r)
 		authed := err == nil
 		ctx := context.WithValue(r.Context(), ProfileIdKey, profile.Id)
@@ -63,21 +61,11 @@ func (a *Handler) AuthPage(h http.HandlerFunc) http.HandlerFunc {
 		default:
 			h(w, r.WithContext(ctx))
 		}
-	})
-}
-
-// NoAuthPage returns a page's handler after setting Content-Type to text/html, and some context values.
-func (a *Handler) NoAuthPage(h http.HandlerFunc) http.HandlerFunc {
-	return func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "text/html; charset=utf-8")
-		ctx := context.WithValue(r.Context(), ThemeKey, getTheme(r))
-		ctx = context.WithValue(ctx, IsMobileKey, isMobile(r))
-		h(w, r.WithContext(ctx))
 	}
 }
 
-// OptionalAuthApi authenticates a page's handler optionally (without 401).
-func (a *Handler) OptionalAuthApi(h http.HandlerFunc) http.HandlerFunc {
+// OptionalAuthPage authenticates a page's handler optionally (without redirection).
+func (a *mw) OptionalAuthPage(h http.HandlerFunc) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		profile, err := a.authenticate(r)
 		if err != nil {
@@ -85,13 +73,12 @@ func (a *Handler) OptionalAuthApi(h http.HandlerFunc) http.HandlerFunc {
 			return
 		}
 		ctx := context.WithValue(r.Context(), ProfileIdKey, profile.Id)
-		ctx = context.WithValue(ctx, IsMobileKey, isMobile(r))
 		h(w, r.WithContext(ctx))
 	}
 }
 
 // AuthApi authenticates an API's handler.
-func (a *Handler) AuthApi(h http.HandlerFunc) http.HandlerFunc {
+func (a *mw) AuthApi(h http.HandlerFunc) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		profile, err := a.authenticate(r)
 		if err != nil {
@@ -99,20 +86,24 @@ func (a *Handler) AuthApi(h http.HandlerFunc) http.HandlerFunc {
 			return
 		}
 		ctx := context.WithValue(r.Context(), ProfileIdKey, profile.Id)
-		ctx = context.WithValue(ctx, IsMobileKey, isMobile(r))
 		h(w, r.WithContext(ctx))
 	}
 }
 
-// NoAuthApi returns a page's handler after setting Content-Type to application/json.
-func (a *Handler) NoAuthApi(h http.HandlerFunc) http.HandlerFunc {
+// OptionalAuthApi authenticates a page's handler optionally (without 401).
+func (a *mw) OptionalAuthApi(h http.HandlerFunc) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
-		h(w, r.WithContext(context.WithValue(r.Context(), IsMobileKey, isMobile(r))))
+		profile, err := a.authenticate(r)
+		if err != nil {
+			h(w, r)
+			return
+		}
+		ctx := context.WithValue(r.Context(), ProfileIdKey, profile.Id)
+		h(w, r.WithContext(ctx))
 	}
 }
 
-func (a *Handler) authenticate(r *http.Request) (entities.Profile, error) {
+func (a *mw) authenticate(r *http.Request) (entities.Profile, error) {
 	sessionToken, err := r.Cookie(SessionTokenKey)
 	if err != nil {
 		return entities.Profile{}, err
@@ -146,30 +137,3 @@ func (a *Handler) authenticate(r *http.Request) (entities.Profile, error) {
 		Name: profile.Name,
 	}, nil
 }
-
-func isMobile(r *http.Request) bool {
-	return strings.Contains(strings.ToLower(r.Header.Get("User-Agent")), "mobile")
-}
-
-func getTheme(r *http.Request) string {
-	themeCookie, err := r.Cookie(ThemeName)
-	if err != nil || themeCookie == nil || themeCookie.Value == "" {
-		return "black"
-	}
-	switch themeCookie.Value {
-	case "dank":
-		return "dank"
-	case "white":
-		return "white"
-	case "black":
-		fallthrough
-	default:
-		return "black"
-	}
-}
-
-// IsNoLayoutPage checks if the requested page requires a no reload or not.
-func IsNoLayoutPage(r *http.Request) bool {
-	noReload, exists := r.URL.Query()["no_layout"]
-	return exists && noReload[0] == "true"
-}
diff --git a/app/handlers/middlewares/contenttype/html.go b/app/handlers/middlewares/contenttype/html.go
new file mode 100644
index 0000000..c1903fb
--- /dev/null
+++ b/app/handlers/middlewares/contenttype/html.go
@@ -0,0 +1,16 @@
+package contenttype
+
+import "net/http"
+
+func Html(h http.HandlerFunc) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "text/html; charset=utf-8")
+		h(w, r)
+	}
+}
+
+// IsNoLayoutPage checks if the requested page requires a no reload or not.
+func IsNoLayoutPage(r *http.Request) bool {
+	noReload, exists := r.URL.Query()["no_layout"]
+	return exists && noReload[0] == "true"
+}
diff --git a/app/handlers/middlewares/contenttype/json.go b/app/handlers/middlewares/contenttype/json.go
new file mode 100644
index 0000000..b8a86ef
--- /dev/null
+++ b/app/handlers/middlewares/contenttype/json.go
@@ -0,0 +1,10 @@
+package contenttype
+
+import "net/http"
+
+func Json(h http.HandlerFunc) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json; charset=utf-8")
+		h(w, r)
+	}
+}
diff --git a/app/handlers/middlewares/ismobile/ismobile.go b/app/handlers/middlewares/ismobile/ismobile.go
new file mode 100644
index 0000000..3c915c8
--- /dev/null
+++ b/app/handlers/middlewares/ismobile/ismobile.go
@@ -0,0 +1,20 @@
+package ismobile
+
+import (
+	"context"
+	"net/http"
+	"strings"
+)
+
+const IsMobileKey = "is-mobile"
+
+func Handler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		ctx := context.WithValue(r.Context(), IsMobileKey, isMobile(r))
+		h.ServeHTTP(w, r.WithContext(ctx))
+	})
+}
+
+func isMobile(r *http.Request) bool {
+	return strings.Contains(strings.ToLower(r.Header.Get("User-Agent")), "mobile")
+}
diff --git a/app/handlers/keys.go b/app/handlers/middlewares/keys.go
similarity index 94%
rename from app/handlers/keys.go
rename to app/handlers/middlewares/keys.go
index affff75..25a8e48 100644
--- a/app/handlers/keys.go
+++ b/app/handlers/middlewares/keys.go
@@ -1,4 +1,4 @@
-package handlers
+package middlewares
 
 // Cookie keys
 const (
diff --git a/app/handlers/middlewares/theme/theme.go b/app/handlers/middlewares/theme/theme.go
new file mode 100644
index 0000000..77049cb
--- /dev/null
+++ b/app/handlers/middlewares/theme/theme.go
@@ -0,0 +1,32 @@
+package theme
+
+import (
+	"context"
+	"net/http"
+)
+
+const ThemeKey = "theme-name"
+
+func Handler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		ctx := context.WithValue(r.Context(), ThemeKey, getTheme(r))
+		h.ServeHTTP(w, r.WithContext(ctx))
+	})
+}
+
+func getTheme(r *http.Request) string {
+	themeCookie, err := r.Cookie(ThemeKey)
+	if err != nil || themeCookie == nil || themeCookie.Value == "" {
+		return "black"
+	}
+	switch themeCookie.Value {
+	case "dank":
+		return "dank"
+	case "white":
+		return "white"
+	case "black":
+		fallthrough
+	default:
+		return "black"
+	}
+}
diff --git a/app/handlers/pages/pages.go b/app/handlers/pages/pages.go
index 825235b..267128f 100644
--- a/app/handlers/pages/pages.go
+++ b/app/handlers/pages/pages.go
@@ -5,7 +5,8 @@ import (
 	"dankmuzikk/config"
 	"dankmuzikk/db"
 	"dankmuzikk/entities"
-	"dankmuzikk/handlers"
+	"dankmuzikk/handlers/middlewares/auth"
+	"dankmuzikk/handlers/middlewares/contenttype"
 	"dankmuzikk/log"
 	"dankmuzikk/models"
 	"dankmuzikk/services/history"
@@ -56,7 +57,7 @@ func NewPagesHandler(
 func (p *pagesHandler) HandleHomePage(w http.ResponseWriter, r *http.Request) {
 	var recentPlays []entities.Song
 	var err error
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if profileIdCorrect {
 		recentPlays, err = p.historyService.Get(profileId, 1)
 		if err != nil {
@@ -64,7 +65,7 @@ func (p *pagesHandler) HandleHomePage(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", "Home")
 		w.Header().Set("HX-Push-Url", "/")
 		pages.Index(recentPlays).Render(r.Context(), w)
@@ -74,7 +75,7 @@ func (p *pagesHandler) HandleHomePage(w http.ResponseWriter, r *http.Request) {
 }
 
 func (p *pagesHandler) HandleAboutPage(w http.ResponseWriter, r *http.Request) {
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", "About")
 		w.Header().Set("HX-Push-Url", "/about")
 		pages.About().Render(r.Context(), w)
@@ -88,7 +89,7 @@ func (p *pagesHandler) HandleLoginPage(w http.ResponseWriter, r *http.Request) {
 }
 
 func (p *pagesHandler) HandlePlaylistsPage(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		status.
 			BugsBunnyError("I'm not sure what you're trying to do :)").
@@ -101,7 +102,7 @@ func (p *pagesHandler) HandlePlaylistsPage(w http.ResponseWriter, r *http.Reques
 		playlists = make([]entities.Playlist, 0)
 	}
 
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", "Playlists")
 		w.Header().Set("HX-Push-Url", "/playlists")
 		pages.Playlists(playlists).Render(r.Context(), w)
@@ -111,7 +112,7 @@ func (p *pagesHandler) HandlePlaylistsPage(w http.ResponseWriter, r *http.Reques
 }
 
 func (p *pagesHandler) HandleSinglePlaylistPage(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
 		status.
 			BugsBunnyError("I'm not sure what you're trying to do :)").
@@ -128,7 +129,7 @@ func (p *pagesHandler) HandleSinglePlaylistPage(w http.ResponseWriter, r *http.R
 	}
 
 	playlist, permission, err := p.playlistsService.Get(playlistPubId, profileId)
-	htmxReq := handlers.IsNoLayoutPage(r)
+	htmxReq := contenttype.IsNoLayoutPage(r)
 	switch {
 	case errors.Is(err, playlists.ErrUnauthorizedToSeePlaylist):
 		log.Errorln(err)
@@ -155,9 +156,9 @@ func (p *pagesHandler) HandleSinglePlaylistPage(w http.ResponseWriter, r *http.R
 				Render(r.Context(), w)
 		}
 	}
-	ctx := context.WithValue(r.Context(), handlers.PlaylistPermission, permission)
+	ctx := context.WithValue(r.Context(), auth.PlaylistPermission, permission)
 
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", playlist.Title)
 		w.Header().Set("HX-Push-Url", "/playlist/"+playlist.PublicId)
 		pages.Playlist(playlist).Render(ctx, w)
@@ -183,7 +184,7 @@ func (p *pagesHandler) HandleSingleSongPage(w http.ResponseWriter, r *http.Reque
 		return
 	}
 
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", song.Title)
 		w.Header().Set("HX-Push-Url", "/song/"+song.YtId)
 		pages.Song(song).Render(r.Context(), w)
@@ -197,9 +198,9 @@ func (p *pagesHandler) HandlePrivacyPage(w http.ResponseWriter, r *http.Request)
 }
 
 func (p *pagesHandler) HandleProfilePage(w http.ResponseWriter, r *http.Request) {
-	profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
+	profileId, profileIdCorrect := r.Context().Value(auth.ProfileIdKey).(uint)
 	if !profileIdCorrect {
-		if handlers.IsNoLayoutPage(r) {
+		if contenttype.IsNoLayoutPage(r) {
 			w.Header().Set("HX-Redirect", "/")
 		} else {
 			http.Redirect(w, r, config.Env().Hostname, http.StatusTemporaryRedirect)
@@ -213,7 +214,7 @@ func (p *pagesHandler) HandleProfilePage(w http.ResponseWriter, r *http.Request)
 		PfpLink:  dbProfile.PfpLink,
 		Username: dbProfile.Username,
 	}
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", "Profile")
 		w.Header().Set("HX-Push-Url", "/profile")
 		pages.Profile(profile).Render(r.Context(), w)
@@ -238,7 +239,7 @@ func (p *pagesHandler) HandleSearchResultsPage(w http.ResponseWriter, r *http.Re
 		_ = p.downloadService.DownloadYoutubeSongsMetadata(results)
 	}
 
-	if handlers.IsNoLayoutPage(r) {
+	if contenttype.IsNoLayoutPage(r) {
 		w.Header().Set("HX-Title", "Results for "+query)
 		w.Header().Set("HX-Push-Url", "/search?query="+query)
 		pages.SearchResults(results).Render(r.Context(), w)
diff --git a/nginx/dankmuzikk.conf b/nginx/dankmuzikk.conf
index 8924a16..5273966 100644
--- a/nginx/dankmuzikk.conf
+++ b/nginx/dankmuzikk.conf
@@ -1,23 +1,33 @@
 server {
-	listen 80;
-	listen [::]:80;
-	server_name dankmuzikk.com;
+    listen 80;
+    listen [::]:80;
+    server_name dankmuzikk.com;
 
-	location ~ ^/(.*)$ {
-		set $upstream http://127.0.0.1:20251;
-		proxy_read_timeout 180;
-		proxy_connect_timeout 180;
-		proxy_send_timeout 180;
+    location ~ ^/muzikkx(.*)$ {
+        set $upstream http://127.0.0.1:20251/muzikkx;
+        proxy_read_timeout 1800;
+        proxy_connect_timeout 1800;
+        proxy_send_timeout 1800;
         # required headers for safari :)
-		proxy_set_header Connection "keep-alive";
-		proxy_set_header Range "bytes=0-";
-		proxy_set_header Icy-Metadata "0";
-		proxy_pass_request_headers on;
-		proxy_pass $upstream/$1$is_args$args;
-	}
+        proxy_set_header Connection "keep-alive";
+        proxy_set_header Range "bytes=0-";
+        proxy_set_header Icy-Metadata "0";
+        proxy_pass_request_headers      on;
+        proxy_pass $upstream$1$is_args$args;
+    }
 
-	location / {
-		proxy_pass http://127.0.0.1:20251;
-	}
+    location ~ ^/(.*)$ {
+        set $upstream http://127.0.0.1:20251;
+        proxy_read_timeout 180;
+        proxy_connect_timeout 180;
+        proxy_send_timeout 180;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_pass_request_headers      on;
+        proxy_pass $upstream/$1$is_args$args;
+    }
+
+    location / {
+        proxy_pass http://127.0.0.1:20251;
+    }
 }