diff --git a/cmd/backend/articles.go b/cmd/backend/articles.go
index ffee3af..deeb93c 100644
--- a/cmd/backend/articles.go
+++ b/cmd/backend/articles.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"path/filepath"
 	"time"
 
 	"github.com/google/uuid"
@@ -334,9 +335,9 @@ func (db *DB) DeleteArticle(id int64) error {
 }
 
 func WriteArticleToFile(c *Config, articleUUID uuid.UUID, content []byte) error {
-	articleAbsName := fmt.Sprint(c.ArticleDir, "/", articleUUID, ".md")
+	articlePath := filepath.Join(c.ArticleDir, fmt.Sprint(articleUUID, ".md"))
 
-	if err := os.WriteFile(articleAbsName, content, 0644); err != nil {
+	if err := os.WriteFile(articlePath, content, 0644); err != nil {
 		return fmt.Errorf("error writing article %v to file: %v", articleUUID, err)
 	}
 
diff --git a/cmd/backend/config.go b/cmd/backend/config.go
index 3a28519..7d55367 100644
--- a/cmd/backend/config.go
+++ b/cmd/backend/config.go
@@ -58,12 +58,9 @@ func newConfig() *Config {
 }
 
 func mkDir(path string, perm fs.FileMode) (string, error) {
-	var err error
+	name := filepath.Base(path)
 
-	stringSlice := strings.Split(path, "/")
-	name := stringSlice[len(stringSlice)-1]
-
-	path, err = filepath.Abs(path)
+	path, err := filepath.Abs(path)
 	if err != nil {
 		return "", fmt.Errorf("error finding absolute path for %v directory: %v", name, err)
 	}
@@ -82,20 +79,20 @@ func mkFile(path string, filePerm, dirPerm fs.FileMode) (string, error) {
 		return "", fmt.Errorf("error finding absolute path for %v: %v", path, err)
 	}
 
-	stringSlice := strings.Split(path, "/")
 	_, err = os.Stat(path)
 	if os.IsNotExist(err) {
-		dir := strings.Join(stringSlice[:len(stringSlice)-1], "/")
+		dir := filepath.Dir(path)
 		if err = os.MkdirAll(dir, dirPerm); err != nil {
 			return "", fmt.Errorf("error creating %v: %v", dir, err)
 		}
 
-		fileName := stringSlice[len(stringSlice)-1]
+		fileName := filepath.Base(path)
 		file, err := os.Create(filepath.Join(dir, fileName))
 		if err != nil {
 			return "", fmt.Errorf("error creating %v: %v", fileName, err)
 		}
 		defer file.Close()
+
 		if err = file.Chmod(filePerm); err != nil {
 			return "", fmt.Errorf("error setting permissions for %v: %v", fileName, err)
 		}
diff --git a/cmd/calls/articles.go b/cmd/calls/articles.go
index 3e46703..9908780 100644
--- a/cmd/calls/articles.go
+++ b/cmd/calls/articles.go
@@ -5,6 +5,7 @@ import (
 	"log"
 	"net/http"
 	"os"
+	"path/filepath"
 
 	"github.com/google/uuid"
 	b "streifling.com/jason/cpolis/cmd/backend"
@@ -56,8 +57,8 @@ func ServeArticle(c *b.Config, db *b.DB) http.HandlerFunc {
 			return
 		}
 
-		articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.UUID, ".md")
-		contentBytes, err := os.ReadFile(articleAbsName)
+		articlePath := filepath.Join(c.ArticleDir, fmt.Sprint(article.UUID, ".md"))
+		contentBytes, err := os.ReadFile(articlePath)
 		if err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
diff --git a/cmd/calls/pdf.go b/cmd/calls/pdf.go
index 5de6a20..71bf215 100644
--- a/cmd/calls/pdf.go
+++ b/cmd/calls/pdf.go
@@ -5,6 +5,7 @@ import (
 	"log"
 	"net/http"
 	"os"
+	"path/filepath"
 
 	b "streifling.com/jason/cpolis/cmd/backend"
 )
@@ -42,6 +43,6 @@ func ServePDF(c *b.Config) http.HandlerFunc {
 			return
 		}
 
-		http.ServeFile(w, r, c.PDFDir+"/"+r.PathValue("id"))
+		http.ServeFile(w, r, filepath.Join(c.PDFDir, r.PathValue("id")))
 	}
 }
diff --git a/cmd/frontend/articles.go b/cmd/frontend/articles.go
index c8947f5..26088db 100644
--- a/cmd/frontend/articles.go
+++ b/cmd/frontend/articles.go
@@ -456,8 +456,8 @@ func ReviewRejectedArticle(c *b.Config, db *b.DB, s map[string]*Session) http.Ha
 
 		data.Image = data.Article.BannerLink
 
-		articleAbsName := fmt.Sprint(c.ArticleDir, "/", data.Article.UUID, ".md")
-		content, err := os.ReadFile(articleAbsName)
+		articlePath := filepath.Join(c.ArticleDir, fmt.Sprint(data.Article.UUID, ".md"))
+		content, err := os.ReadFile(articlePath)
 		if err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -587,7 +587,7 @@ func PublishArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFu
 				return
 			}
 
-			if err = os.Remove(fmt.Sprint(c.ArticleDir, "/", oldArticle.UUID, ".md")); err != nil {
+			if err = os.Remove(filepath.Join(c.ArticleDir, fmt.Sprint(oldArticle.UUID, ".md"))); err != nil {
 				log.Println(err)
 				http.Error(w, err.Error(), http.StatusInternalServerError)
 				return
@@ -765,8 +765,8 @@ func ReviewArticle(c *b.Config, db *b.DB, s map[string]*Session, action, title,
 			return
 		}
 
-		articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.UUID, ".md")
-		content, err := os.ReadFile(articleAbsName)
+		articlePath := filepath.Join(c.ArticleDir, fmt.Sprint(article.UUID, ".md"))
+		content, err := os.ReadFile(articlePath)
 		if err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -840,7 +840,7 @@ func DeleteArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFun
 			return
 		}
 
-		if err = os.Remove(fmt.Sprint(c.ArticleDir, "/", article.UUID, ".md")); err != nil {
+		if err = os.Remove(filepath.Join(c.ArticleDir, fmt.Sprint(article.UUID, ".md"))); err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return
@@ -918,8 +918,8 @@ func AllowEditArticle(c *b.Config, db *b.DB, s map[string]*Session) http.Handler
 			return
 		}
 
-		src := fmt.Sprint(c.ArticleDir, "/", oldArticle.UUID, ".md")
-		dst := fmt.Sprint(c.ArticleDir, "/", newArticle.UUID, ".md")
+		src := filepath.Join(c.ArticleDir, fmt.Sprint(oldArticle.UUID, ".md"))
+		dst := filepath.Join(c.ArticleDir, fmt.Sprint(newArticle.UUID, ".md"))
 		if err = b.CopyFile(src, dst); err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -995,7 +995,7 @@ func EditArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc
 
 		data.Image = data.Article.BannerLink
 
-		content, err := os.ReadFile(fmt.Sprint(c.ArticleDir, "/", data.Article.UUID, ".md"))
+		content, err := os.ReadFile(filepath.Join(c.ArticleDir, fmt.Sprint(data.Article.UUID, ".md")))
 		if err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
diff --git a/cmd/frontend/images.go b/cmd/frontend/images.go
index fb785f0..4889818 100644
--- a/cmd/frontend/images.go
+++ b/cmd/frontend/images.go
@@ -25,7 +25,7 @@ func UploadEasyMDEImage(c *b.Config, s map[string]*Session) http.HandlerFunc {
 		}
 		defer file.Close()
 
-		filename, err := b.SaveImage(file, c.MaxImgHeight, c.MaxImgWidth, c.PicsDir+"/")
+		filename, err := b.SaveImage(file, c.MaxImgHeight, c.MaxImgWidth, c.ImgDir)
 		if err != nil {
 			if err == b.ErrUnsupportedFormat {
 				http.Error(w, "Das Dateiformat wird nicht unterstützt.", http.StatusBadRequest)
@@ -57,7 +57,7 @@ func UploadImage(c *b.Config, s map[string]*Session, fileKey, htmlFile, htmlTemp
 		}
 		defer file.Close()
 
-		filename, err := b.SaveImage(file, c.MaxBannerHeight, c.MaxBannerWidth, c.PicsDir+"/")
+		filename, err := b.SaveImage(file, c.MaxBannerHeight, c.MaxBannerWidth, c.ImgDir)
 		if err != nil {
 			if err == b.ErrUnsupportedFormat {
 				http.Error(w, "Das Dateiformat wird nicht unterstützt.", http.StatusBadRequest)
diff --git a/cmd/frontend/issues.go b/cmd/frontend/issues.go
index 7c41f75..d694c28 100644
--- a/cmd/frontend/issues.go
+++ b/cmd/frontend/issues.go
@@ -58,8 +58,8 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s map[string]*Session) http.Handl
 			return
 		}
 
-		articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.UUID, ".md")
-		if err = os.WriteFile(articleAbsName, content, 0644); err != nil {
+		articlePath := filepath.Join(c.ArticleDir, fmt.Sprint(article.UUID, ".md"))
+		if err = os.WriteFile(articlePath, content, 0644); err != nil {
 			log.Println(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return