1diff --git a/README.md b/README.md
2index 0940ae4032c1b21ce7b111cc8f20bd972167f0dd..6103dbfc3432ba7615a19ab7d4026389bd854e9b 100644
3--- a/README.md
4+++ b/README.md
5@@ -7,7 +7,7 @@
6 * Thumbnail system
7 * Initial setup process
8 * Also allow setup user config file
9-* Single binary output
10+* ~~Single binary output~~
11 * Better worker pool. Allow cron job and ui config
12 * Alpine package and demo site
13 * Single image viewer and show exif info (not sure how yet)
14diff --git a/cmd/server/main.go b/cmd/server/main.go
15index 0fa5fea9d42fe4a4c8ea1c67444e034b938f68e9..4ca39de019df146d6b4348036a23abaa1087d090 100644
16--- a/cmd/server/main.go
17+++ b/cmd/server/main.go
18@@ -16,6 +16,7 @@ "gorm.io/driver/postgres"
19 "gorm.io/driver/sqlite"
20 "gorm.io/gorm"
21
22+ "git.sr.ht/~gabrielgio/img"
23 "git.sr.ht/~gabrielgio/img/pkg/components/auth"
24 "git.sr.ht/~gabrielgio/img/pkg/components/filesystem"
25 "git.sr.ht/~gabrielgio/img/pkg/components/media"
26@@ -69,8 +70,7 @@ panic("failed to decode key database: " + err.Error())
27 }
28
29 r := router.New()
30- r.ServeFiles("/static/{filepath:*}", "./static")
31- r.NotFound = ext.NotFoundHTML
32+ r.GET("/static/{filepath:*}", ext.FileServer(img.StaticFS, "static/"))
33
34 authMiddleware := ext.NewAuthMiddleware(hexKey, logger.WithField("context", "auth"))
35 logMiddleware := ext.NewLogMiddleare(logger.WithField("context", "http"))
36diff --git a/pkg/ext/fileserver.go b/pkg/ext/fileserver.go
37new file mode 100644
38index 0000000000000000000000000000000000000000..fdea08eb941ad2e92b15c9646aa4c4455c47d6a7
39--- /dev/null
40+++ b/pkg/ext/fileserver.go
41@@ -0,0 +1,18 @@
42+package ext
43+
44+import (
45+ "io/fs"
46+
47+ "github.com/valyala/fasthttp"
48+)
49+
50+type FileSystem interface {
51+ Open(name string) (fs.File, error)
52+}
53+
54+func FileServer(rootFS FileSystem, rootPath string) fasthttp.RequestHandler {
55+ return func(r *fasthttp.RequestCtx) {
56+ path := r.UserValue("filepath").(string)
57+ r.SendFile(rootPath + path)
58+ }
59+}
60diff --git a/pkg/worker/list_processor_test.go b/pkg/worker/list_processor_test.go
61index 35672f3b1e9b807fde0698ea752a7763777b7cfa..ce3ff0a3d531d278ac4afa5157d7fd8c3149acf8 100644
62--- a/pkg/worker/list_processor_test.go
63+++ b/pkg/worker/list_processor_test.go
64@@ -9,8 +9,9 @@ "math/rand"
65 "sync"
66 "testing"
67
68+ "github.com/sirupsen/logrus"
69+
70 "git.sr.ht/~gabrielgio/img/pkg/testkit"
71- "github.com/sirupsen/logrus"
72 )
73
74 type (
75diff --git a/tmpl.go b/static.go
76rename from tmpl.go
77rename to static.go
78index b11f9624a8e640836f0cef52fc7fffada179b776..1c6a086b026205651a0d837e10588b65c5df8aaf 100644
79--- a/tmpl.go
80+++ b/static.go
81@@ -7,10 +7,15 @@ "html/template"
82 "io"
83 )
84
85-//go:embed templates/*.html
86-var TemplateFS embed.FS
87+var (
88+ //go:embed templates/*.html
89+ TemplateFS embed.FS
90+
91+ //go:embed static/*
92+ StaticFS embed.FS
93
94-var Template *template.Template
95+ Template *template.Template
96+)
97
98 type HTMLView[T any] struct {
99 Title string