diff --git a/.idea/webResources.xml b/.idea/webResources.xml
new file mode 100644
index 0000000..d29937f
--- /dev/null
+++ b/.idea/webResources.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Makefile b/Makefile
index dd59880..627a037 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ ids:
run: build
mkdir -p .run-data
- sudo _build/bunny_backend
+ sudo BUNNY_LIVERELOAD="$(shell pwd)/webassets" CONF_NS="local-host" _build/bunny_backend
gow:
# go install github.com/mitranim/gow@latest
diff --git a/api/handler/apiHandler.go b/api/handler/apiHandler.go
new file mode 100644
index 0000000..f1ecaa8
--- /dev/null
+++ b/api/handler/apiHandler.go
@@ -0,0 +1,47 @@
+package handler
+
+import (
+ "gogs.mikescher.com/BlackForestBytes/goext/ginext"
+ bunny "locbunny"
+ "locbunny/logic"
+ "locbunny/models"
+ "net/http"
+)
+
+type APIHandler struct {
+ app *logic.Application
+}
+
+func NewAPIHandler(app *logic.Application) APIHandler {
+ return APIHandler{
+ app: app,
+ }
+}
+
+// ListServer swaggerdoc
+//
+// @Summary List running server
+//
+// @Success 200 {object} handler.ListServer.response
+// @Failure 400 {object} models.APIError
+// @Failure 500 {object} models.APIError
+//
+// @Router /server [GET]
+func (h APIHandler) ListServer(pctx ginext.PreContext) ginext.HTTPResponse {
+ type response struct {
+ Server []models.Server `json:"server"`
+ }
+
+ ctx, _, errResp := pctx.Start()
+ if errResp != nil {
+ return *errResp
+ }
+ defer ctx.Cancel()
+
+ srvs, err := h.app.ListServer(ctx, bunny.Conf.VerifyConnTimeoutAPI)
+ if err != nil {
+ return ginext.Error(err)
+ }
+
+ return ginext.JSON(http.StatusOK, response{Server: srvs})
+}
diff --git a/api/handler/webHandler.go b/api/handler/webHandler.go
index c0d4ebe..2fd0682 100644
--- a/api/handler/webHandler.go
+++ b/api/handler/webHandler.go
@@ -1,11 +1,20 @@
package handler
import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "github.com/gin-gonic/gin"
"gogs.mikescher.com/BlackForestBytes/goext/ginext"
- "gogs.mikescher.com/BlackForestBytes/goext/langext"
+ templhtml "html/template"
+ bunny "locbunny"
"locbunny/logic"
"locbunny/models"
+ "locbunny/webassets"
"net/http"
+ "path/filepath"
+ templtext "text/template"
+ "time"
)
type WebHandler struct {
@@ -18,32 +27,151 @@ func NewWebHandler(app *logic.Application) WebHandler {
}
}
-// ListServer swaggerdoc
+// ServeIndexHTML swaggerdoc
//
-// @Summary List running server
+// @Summary (Website)
//
-// @Success 200 {object} handler.ListServer.response
-// @Failure 400 {object} models.APIError
-// @Failure 500 {object} models.APIError
-//
-// @Router /server [GET]
-func (h WebHandler) ListServer(pctx ginext.PreContext) ginext.HTTPResponse {
- type response struct {
- Server []models.Server `json:"server"`
- }
-
+// @Router / [GET]
+// @Router /index.html [GET]
+func (h WebHandler) ServeIndexHTML(pctx ginext.PreContext) ginext.HTTPResponse {
ctx, _, errResp := pctx.Start()
if errResp != nil {
return *errResp
}
defer ctx.Cancel()
- srvs, err := h.app.ListServer(ctx)
+ templ, err := h.app.Assets.Template("index.html", h.buildIndexHTMLTemplate)
if err != nil {
return ginext.Error(err)
}
- langext.SortBy(srvs, func(v models.Server) int { return v.Port })
+ data := map[string]any{}
- return ginext.JSON(http.StatusOK, response{Server: srvs})
+ bin := bytes.Buffer{}
+ err = templ.Execute(&bin, data)
+ if err != nil {
+ return ginext.Error(err)
+ }
+
+ return ginext.Data(http.StatusOK, "text/html", bin.Bytes())
+}
+
+// ServeScriptJS swaggerdoc
+//
+// @Summary (Website)
+//
+// @Router /scripts.script.js [GET]
+func (h WebHandler) ServeScriptJS(pctx ginext.PreContext) ginext.HTTPResponse {
+ ctx, _, errResp := pctx.Start()
+ if errResp != nil {
+ return *errResp
+ }
+ defer ctx.Cancel()
+
+ templ, err := h.app.Assets.Template("scripts/script.js", h.buildScriptJSTemplate)
+ if err != nil {
+ return ginext.Error(err)
+ }
+
+ data := map[string]any{}
+
+ bin := bytes.Buffer{}
+ err = templ.Execute(&bin, data)
+ if err != nil {
+ return ginext.Error(err)
+ }
+
+ return ginext.Data(http.StatusOK, "text/javascript", bin.Bytes())
+}
+
+func (h WebHandler) buildIndexHTMLTemplate(content []byte) (webassets.ITemplate, error) {
+ t := templhtml.New("index.html")
+
+ t.Funcs(h.templateFuncMap())
+
+ _, err := t.Parse(string(content))
+ if err != nil {
+ return nil, err
+ }
+
+ return t, nil
+}
+
+func (h WebHandler) ServeAssets(pctx ginext.PreContext) ginext.HTTPResponse {
+ type uri struct {
+ FP1 *string `uri:"fp1"`
+ FP2 *string `uri:"fp2"`
+ FP3 *string `uri:"fp3"`
+ }
+
+ var u uri
+ ctx, _, errResp := pctx.URI(&u).Start()
+ if errResp != nil {
+ return *errResp
+ }
+ defer ctx.Cancel()
+
+ assetpath := ""
+ if u.FP1 == nil && u.FP2 == nil && u.FP3 == nil {
+ assetpath = filepath.Join()
+ } else if u.FP2 == nil && u.FP3 == nil {
+ assetpath = filepath.Join(*u.FP1)
+ } else if u.FP3 == nil {
+ assetpath = filepath.Join(*u.FP1, *u.FP2)
+ } else {
+ assetpath = filepath.Join(*u.FP1, *u.FP2, *u.FP3)
+ }
+
+ data, err := h.app.Assets.Read(assetpath)
+ if err != nil {
+ return ginext.JSON(http.StatusNotFound, gin.H{"error": "AssetNotFound", "assetpath": assetpath})
+ }
+
+ mime := bunny.FilenameToMime(assetpath, "text/plain")
+
+ return ginext.Data(http.StatusOK, mime, data)
+}
+
+func (h WebHandler) buildScriptJSTemplate(content []byte) (webassets.ITemplate, error) {
+ t := templtext.New("scripts/script.js")
+
+ t.Funcs(h.templateFuncMap())
+
+ _, err := t.Parse(string(content))
+ if err != nil {
+ return nil, err
+ }
+
+ return t, nil
+}
+
+func (h WebHandler) templateFuncMap() map[string]any {
+ return map[string]any{
+ "listServers": func() []models.Server {
+ ctx, cancel := context.WithTimeout(context.Background(), bunny.Conf.VerifyConnTimeoutHTML+2*time.Second)
+ defer cancel()
+ v, err := h.app.ListServer(ctx, bunny.Conf.VerifyConnTimeoutHTML)
+ if err != nil {
+ panic(err)
+ }
+ return v
+ },
+ "safe_html": func(s string) templhtml.HTML { return templhtml.HTML(s) }, //nolint:gosec
+ "safe_js": func(s string) templhtml.JS { return templhtml.JS(s) }, //nolint:gosec
+ "json": func(obj any) string {
+ v, err := json.Marshal(obj)
+ if err != nil {
+ panic(err)
+ }
+ return string(v)
+ },
+ "json_indent": func(obj any) string {
+ v, err := json.MarshalIndent(obj, "", " ")
+ if err != nil {
+ panic(err)
+ }
+ return string(v)
+ },
+ "mkarr": func(ln int) []int { return make([]int, ln) },
+ }
}
diff --git a/api/router.go b/api/router.go
index 8cd0b4e..70afc34 100644
--- a/api/router.go
+++ b/api/router.go
@@ -13,6 +13,7 @@ type Router struct {
app *logic.Application
commonHandler handler.CommonHandler
+ apiHandler handler.APIHandler
webHandler handler.WebHandler
}
@@ -21,6 +22,7 @@ func NewRouter(app *logic.Application) *Router {
app: app,
commonHandler: handler.NewCommonHandler(app),
+ apiHandler: handler.NewAPIHandler(app),
webHandler: handler.NewWebHandler(app),
}
}
@@ -50,9 +52,18 @@ func (r *Router) Init(e *ginext.GinWrapper) {
docs.GET("/swagger/*sub").Handle(swagger.Handle)
}
+ // ================ Website ================
+
+ e.Routes().GET("/").Handle(r.webHandler.ServeIndexHTML)
+ e.Routes().GET("/index.html").Handle(r.webHandler.ServeIndexHTML)
+ e.Routes().GET("/scripts/script.js").Handle(r.webHandler.ServeScriptJS)
+ e.Routes().GET("/:fp1").Handle(r.webHandler.ServeAssets)
+ e.Routes().GET("/:fp1/:fp2").Handle(r.webHandler.ServeAssets)
+ e.Routes().GET("/:fp1/:fp2/:fp3").Handle(r.webHandler.ServeAssets)
+
// ================ API ================
- api.GET("/server").Handle(r.webHandler.ListServer)
+ api.GET("/server").Handle(r.apiHandler.ListServer)
// ================ ================
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 2e8d5e6..db9ea1c 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -7,6 +7,7 @@ import (
bunny "locbunny"
"locbunny/api"
"locbunny/logic"
+ "locbunny/webassets"
)
func main() {
@@ -16,7 +17,9 @@ func main() {
log.Info().Msg(fmt.Sprintf("Starting with config-namespace <%s>", conf.Namespace))
- app := logic.NewApp()
+ assets := webassets.NewAssets()
+
+ app := logic.NewApp(assets)
ginengine := ginext.NewEngine(conf.Cors, conf.GinDebug, true, conf.RequestTimeout)
diff --git a/config.go b/config.go
index 92eb59f..7fb8446 100644
--- a/config.go
+++ b/config.go
@@ -14,92 +14,110 @@ const APILevel = 1
var SelfProcessID int
type Config struct {
- Namespace string
- GinDebug bool `env:"GINDEBUG"`
- ReturnRawErrors bool `env:"RETURNERRORS"`
- Custom404 bool `env:"CUSTOM404"`
- LogLevel zerolog.Level `env:"LOGLEVEL"`
- ServerIP string `env:"IP"`
- ServerPort int `env:"PORT"`
- RequestTimeout time.Duration `env:"REQUEST_TIMEOUT"`
- Cors bool `env:"CORS"`
- VerifyConnTimeout time.Duration `env:"VERIFY_CONN_TIMEOUT"`
+ Namespace string
+ GinDebug bool `env:"GINDEBUG"`
+ ReturnRawErrors bool `env:"RETURNERRORS"`
+ Custom404 bool `env:"CUSTOM404"`
+ LogLevel zerolog.Level `env:"LOGLEVEL"`
+ ServerIP string `env:"IP"`
+ ServerPort int `env:"PORT"`
+ RequestTimeout time.Duration `env:"REQUEST_TIMEOUT"`
+ Cors bool `env:"CORS"`
+ VerifyConnTimeoutHTML time.Duration `env:"VERIFY_CONN_TIMEOUT_HTML"`
+ VerifyConnTimeoutAPI time.Duration `env:"VERIFY_CONN_TIMEOUT_API"`
+ LiveReload *string `env:"LIVERELOAD"`
+ CacheDuration time.Duration `env:"CACHE_DURATION"`
}
var Conf Config
var configLocHost = func() Config {
return Config{
- Namespace: "local",
- GinDebug: true,
- ServerIP: "0.0.0.0",
- ServerPort: 80,
- Custom404: true,
- ReturnRawErrors: true,
- RequestTimeout: 16 * time.Second,
- LogLevel: zerolog.DebugLevel,
- Cors: true,
- VerifyConnTimeout: time.Second,
+ Namespace: "local",
+ GinDebug: true,
+ ServerIP: "0.0.0.0",
+ ServerPort: 80,
+ Custom404: true,
+ ReturnRawErrors: true,
+ RequestTimeout: 16 * time.Second,
+ LogLevel: zerolog.DebugLevel,
+ Cors: true,
+ VerifyConnTimeoutAPI: 2 * time.Second,
+ VerifyConnTimeoutHTML: 500 * time.Millisecond,
+ LiveReload: nil,
+ CacheDuration: 8 * time.Second,
}
}
var configLocDocker = func() Config {
return Config{
- Namespace: "local-docker",
- GinDebug: true,
- ServerIP: "0.0.0.0",
- ServerPort: 80,
- Custom404: true,
- ReturnRawErrors: true,
- RequestTimeout: 16 * time.Second,
- LogLevel: zerolog.DebugLevel,
- Cors: true,
- VerifyConnTimeout: time.Second,
+ Namespace: "local-docker",
+ GinDebug: true,
+ ServerIP: "0.0.0.0",
+ ServerPort: 80,
+ Custom404: true,
+ ReturnRawErrors: true,
+ RequestTimeout: 16 * time.Second,
+ LogLevel: zerolog.DebugLevel,
+ Cors: true,
+ VerifyConnTimeoutAPI: 2 * time.Second,
+ VerifyConnTimeoutHTML: 500 * time.Millisecond,
+ LiveReload: nil,
+ CacheDuration: 8 * time.Second,
}
}
var configDev = func() Config {
return Config{
- Namespace: "develop",
- GinDebug: true,
- ServerIP: "0.0.0.0",
- ServerPort: 80,
- Custom404: false,
- ReturnRawErrors: false,
- RequestTimeout: 16 * time.Second,
- LogLevel: zerolog.DebugLevel,
- Cors: false,
- VerifyConnTimeout: time.Second,
+ Namespace: "develop",
+ GinDebug: true,
+ ServerIP: "0.0.0.0",
+ ServerPort: 80,
+ Custom404: false,
+ ReturnRawErrors: false,
+ RequestTimeout: 16 * time.Second,
+ LogLevel: zerolog.DebugLevel,
+ Cors: false,
+ VerifyConnTimeoutAPI: 2 * time.Second,
+ VerifyConnTimeoutHTML: 500 * time.Millisecond,
+ LiveReload: nil,
+ CacheDuration: 8 * time.Second,
}
}
var configStag = func() Config {
return Config{
- Namespace: "staging",
- GinDebug: true,
- ServerIP: "0.0.0.0",
- ServerPort: 80,
- Custom404: false,
- ReturnRawErrors: false,
- RequestTimeout: 16 * time.Second,
- LogLevel: zerolog.DebugLevel,
- Cors: false,
- VerifyConnTimeout: time.Second,
+ Namespace: "staging",
+ GinDebug: true,
+ ServerIP: "0.0.0.0",
+ ServerPort: 80,
+ Custom404: false,
+ ReturnRawErrors: false,
+ RequestTimeout: 16 * time.Second,
+ LogLevel: zerolog.DebugLevel,
+ Cors: false,
+ VerifyConnTimeoutAPI: 2 * time.Second,
+ VerifyConnTimeoutHTML: 500 * time.Millisecond,
+ LiveReload: nil,
+ CacheDuration: 8 * time.Second,
}
}
var configProd = func() Config {
return Config{
- Namespace: "production",
- GinDebug: false,
- ServerIP: "0.0.0.0",
- ServerPort: 80,
- Custom404: false,
- ReturnRawErrors: false,
- RequestTimeout: 16 * time.Second,
- LogLevel: zerolog.InfoLevel,
- Cors: false,
- VerifyConnTimeout: time.Second,
+ Namespace: "production",
+ GinDebug: false,
+ ServerIP: "0.0.0.0",
+ ServerPort: 80,
+ Custom404: false,
+ ReturnRawErrors: false,
+ RequestTimeout: 16 * time.Second,
+ LogLevel: zerolog.InfoLevel,
+ Cors: false,
+ VerifyConnTimeoutAPI: 2 * time.Second,
+ VerifyConnTimeoutHTML: 500 * time.Millisecond,
+ LiveReload: nil,
+ CacheDuration: 8 * time.Second,
}
}
@@ -119,7 +137,7 @@ func InstanceID() string {
func getConfig(ns string) (Config, bool) {
if ns == "" {
- ns = "local-host"
+ ns = "production"
}
if cfn, ok := allConfig[ns]; ok {
c := cfn()
diff --git a/logic/application.go b/logic/application.go
index c0ee0ee..5a05163 100644
--- a/logic/application.go
+++ b/logic/application.go
@@ -12,6 +12,7 @@ import (
"io"
bunny "locbunny"
"locbunny/models"
+ "locbunny/webassets"
"net"
"net/http"
"os"
@@ -30,12 +31,19 @@ type Application struct {
Port string
IsRunning *syncext.AtomicBool
- Gin *ginext.GinWrapper
- Jobs []Job
+ Gin *ginext.GinWrapper
+ Assets *webassets.Assets
+ Jobs []Job
+
+ cacheLock sync.Mutex
+ serverCacheValue []models.Server
+ serverCacheTime *time.Time
}
-func NewApp() *Application {
+func NewApp(ass *webassets.Assets) *Application {
+ //nolint:exhaustruct
return &Application{
+ Assets: ass,
stopChan: make(chan bool),
IsRunning: syncext.NewAtomicBool(false),
}
@@ -110,18 +118,35 @@ func (app *Application) Run() {
app.IsRunning.Set(false)
}
-func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, error) {
+func (app *Application) ListServer(ctx context.Context, timeout time.Duration) ([]models.Server, error) {
+
+ app.cacheLock.Lock()
+ if app.serverCacheTime != nil && app.serverCacheTime.After(time.Now().Add(-bunny.Conf.CacheDuration)) {
+ v := langext.ArrCopy(app.serverCacheValue)
+ log.Debug().Msg(fmt.Sprintf("Return cache values (from %s)", app.serverCacheTime.Format(time.RFC3339Nano)))
+ app.cacheLock.Unlock()
+ return v, nil
+ }
+ app.cacheLock.Unlock()
socks4, err := netstat.TCPSocks(netstat.NoopFilter)
if err != nil {
return nil, err
}
+ if err := ctx.Err(); err != nil {
+ return nil, err
+ }
+
socks6, err := netstat.TCP6Socks(netstat.NoopFilter)
if err != nil {
return nil, err
}
+ if err := ctx.Err(); err != nil {
+ return nil, err
+ }
+
sockCount := len(socks4) + len(socks6)
wg := sync.WaitGroup{}
@@ -135,7 +160,7 @@ func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, err
go func() {
defer wg.Done()
- con1, err := app.verifyHTTPConn(socks4[i], "HTTP", "v4")
+ con1, err := app.verifyHTTPConn(socks4[i], "HTTP", "v4", timeout)
if err == nil {
rchan <- con1
return
@@ -148,7 +173,7 @@ func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, err
go func() {
defer wg.Done()
- con2, err := app.verifyHTTPConn(socks4[i], "HTTPS", "v4")
+ con2, err := app.verifyHTTPConn(socks4[i], "HTTPS", "v4", timeout)
if err == nil {
rchan <- con2
return
@@ -164,7 +189,7 @@ func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, err
go func() {
defer wg.Done()
- con1, err := app.verifyHTTPConn(socks6[i], "HTTP", "v6")
+ con1, err := app.verifyHTTPConn(socks6[i], "HTTP", "v6", timeout)
if err == nil {
rchan <- con1
return
@@ -177,7 +202,7 @@ func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, err
go func() {
defer wg.Done()
- con2, err := app.verifyHTTPConn(socks6[i], "HTTPS", "v6")
+ con2, err := app.verifyHTTPConn(socks6[i], "HTTPS", "v6", timeout)
if err == nil {
rchan <- con2
return
@@ -191,6 +216,10 @@ func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, err
close(echan)
close(rchan)
+ if err := ctx.Err(); err != nil {
+ return nil, err
+ }
+
duplicates := make(map[int]bool, sockCount*3)
res := make([]models.Server, 0, sockCount*3)
for v := range rchan {
@@ -201,35 +230,44 @@ func (app *Application) ListServer(ctx *ginext.AppContext) ([]models.Server, err
}
}
+ langext.SortBy(res, func(v models.Server) int { return v.Port })
+
+ app.cacheLock.Lock()
+ app.serverCacheValue = langext.ArrCopy(res)
+ app.serverCacheTime = langext.Ptr(time.Now())
+ app.cacheLock.Unlock()
+
return res, nil
}
-func (app *Application) verifyHTTPConn(sock netstat.SockTabEntry, proto string, ipversion string) (models.Server, error) {
+func (app *Application) verifyHTTPConn(sock netstat.SockTabEntry, proto string, ipversion string, timeout time.Duration) (models.Server, error) {
- ctx, cancel := context.WithTimeout(context.Background(), bunny.Conf.VerifyConnTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
- if sock.State != netstat.Listen {
- log.Debug().Msg(fmt.Sprintf("Failed to verify socket [%s|%s] invalid state: %s", ipversion, strings.ToUpper(proto), sock.State.String()))
+ port := int(sock.LocalAddr.Port)
+
+ if sock.State != netstat.Listen && sock.State != netstat.Established && sock.State != netstat.TimeWait {
+ log.Debug().Msg(fmt.Sprintf("Failed to verify socket [%s|%s|%d] invalid state: %s", strings.ToUpper(proto), ipversion, port, sock.State.String()))
return models.Server{}, errors.New("invalid sock-state")
}
- if int(sock.LocalAddr.Port) == bunny.Conf.ServerPort && sock.Process != nil && sock.Process.Pid == bunny.SelfProcessID {
- log.Debug().Msg(fmt.Sprintf("Skip socket [%s|%s] (this is our own server)", ipversion, strings.ToUpper(proto)))
+ if port == bunny.Conf.ServerPort && sock.Process != nil && sock.Process.Pid == bunny.SelfProcessID {
+ log.Debug().Msg(fmt.Sprintf("Skip socket [%s|%s|%d] (this is our own server)", strings.ToUpper(proto), ipversion, port))
return models.Server{}, errors.New("skip self")
}
c := http.Client{}
- url := fmt.Sprintf("%s://localhost:%d", strings.ToLower(proto), sock.LocalAddr.Port)
- req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+ url := fmt.Sprintf("%s://localhost:%d", strings.ToLower(proto), port)
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
- log.Debug().Msg(fmt.Sprintf("Failed to create [%s|%s] request to %d", ipversion, strings.ToUpper(proto), sock.LocalAddr.Port))
+ log.Debug().Msg(fmt.Sprintf("Failed to create [%s|%s|%d] request to %d (-> %s)", strings.ToUpper(proto), ipversion, port, port, err.Error()))
return models.Server{}, err
}
resp1, err := c.Do(req)
if err != nil {
- log.Debug().Msg(fmt.Sprintf("Failed to send [%s|%s] request to %s", ipversion, strings.ToUpper(proto), url))
+ log.Debug().Msg(fmt.Sprintf("Failed to send [%s|%s|%d] request to %s (-> %s)", strings.ToUpper(proto), ipversion, port, url, err.Error()))
return models.Server{}, err
}
@@ -237,7 +275,7 @@ func (app *Application) verifyHTTPConn(sock netstat.SockTabEntry, proto string,
resbody, err := io.ReadAll(resp1.Body)
if err != nil {
- log.Debug().Msg(fmt.Sprintf("Failed to read [%s|%s] response from %s", ipversion, strings.ToUpper(proto), url))
+ log.Debug().Msg(fmt.Sprintf("Failed to read [%s|%s|%d] response from %s (-> %s)", strings.ToUpper(proto), ipversion, port, url, err.Error()))
return models.Server{}, err
}
@@ -252,7 +290,7 @@ func (app *Application) verifyHTTPConn(sock netstat.SockTabEntry, proto string,
}
return models.Server{
- Port: int(sock.LocalAddr.Port),
+ Port: port,
IP: sock.LocalAddr.IP.String(),
Protocol: proto,
StatusCode: resp1.StatusCode,
@@ -265,6 +303,6 @@ func (app *Application) verifyHTTPConn(sock netstat.SockTabEntry, proto string,
}, nil
}
- log.Debug().Msg(fmt.Sprintf("Failed to categorize [%s|%s] response from %s (Content-Type: '%s')", ipversion, strings.ToUpper(proto), url, ct))
+ log.Debug().Msg(fmt.Sprintf("Failed to categorize [%s|%s|%d] response from %s (Content-Type: '%s')", strings.ToUpper(proto), ipversion, port, url, ct))
return models.Server{}, errors.New("invalid response-type")
}
diff --git a/swagger/swagger.go b/swagger/swagger.go
index fef7094..ca09267 100644
--- a/swagger/swagger.go
+++ b/swagger/swagger.go
@@ -2,7 +2,6 @@ package swagger
import (
"embed"
- _ "embed"
"github.com/gin-gonic/gin"
"gogs.mikescher.com/BlackForestBytes/goext/ginext"
"net/http"
diff --git a/swagger/swagger.json b/swagger/swagger.json
index 6251f76..982e59e 100644
--- a/swagger/swagger.json
+++ b/swagger/swagger.json
@@ -8,6 +8,12 @@
"host": "localhost",
"basePath": "/api/v1/",
"paths": {
+ "/": {
+ "get": {
+ "summary": "(Website)",
+ "responses": {}
+ }
+ },
"/api/health": {
"get": {
"tags": [
@@ -169,6 +175,18 @@
}
}
},
+ "/index.html": {
+ "get": {
+ "summary": "(Website)",
+ "responses": {}
+ }
+ },
+ "/scripts.script.js": {
+ "get": {
+ "summary": "(Website)",
+ "responses": {}
+ }
+ },
"/server": {
"get": {
"summary": "List running server",
diff --git a/swagger/swagger.yaml b/swagger/swagger.yaml
index f1b3c9f..202e263 100644
--- a/swagger/swagger.yaml
+++ b/swagger/swagger.yaml
@@ -83,6 +83,10 @@ info:
title: LocalHostBunny
version: "1.0"
paths:
+ /:
+ get:
+ responses: {}
+ summary: (Website)
/api/health:
get:
responses:
@@ -187,6 +191,14 @@ paths:
summary: Return 200 after x seconds
tags:
- Common
+ /index.html:
+ get:
+ responses: {}
+ summary: (Website)
+ /scripts.script.js:
+ get:
+ responses: {}
+ summary: (Website)
/server:
get:
responses:
diff --git a/utils.go b/utils.go
new file mode 100644
index 0000000..e7f9bfa
--- /dev/null
+++ b/utils.go
@@ -0,0 +1,39 @@
+package bunny
+
+import "strings"
+
+func FilenameToMime(fn string, fallback string) string {
+ lowerFN := strings.ToLower(fn)
+ if strings.HasSuffix(lowerFN, ".html") || strings.HasSuffix(lowerFN, ".htm") {
+ return "text/html"
+ }
+ if strings.HasSuffix(lowerFN, ".css") {
+ return "text/css"
+ }
+ if strings.HasSuffix(lowerFN, ".js") {
+ return "text/javascript"
+ }
+ if strings.HasSuffix(lowerFN, ".json") {
+ return "application/json"
+ }
+ if strings.HasSuffix(lowerFN, ".jpeg") || strings.HasSuffix(lowerFN, ".jpg") {
+ return "image/jpeg"
+ }
+ if strings.HasSuffix(lowerFN, ".png") {
+ return "image/png"
+ }
+ if strings.HasSuffix(lowerFN, ".svg") {
+ return "image/svg+xml"
+ }
+ if strings.HasSuffix(lowerFN, ".gif") {
+ return "image/gif"
+ }
+ if strings.HasSuffix(lowerFN, ".webp") {
+ return "audio/webm"
+ }
+ if strings.HasSuffix(lowerFN, ".bmp") {
+ return "image/bmp"
+ }
+
+ return fallback
+}
diff --git a/webassets/css/fonts.css b/webassets/css/fonts.css
new file mode 100644
index 0000000..27af7ff
--- /dev/null
+++ b/webassets/css/fonts.css
@@ -0,0 +1,20 @@
+@font-face { font-display: swap; font-family: 'MonaspaceArgon'; font-weight: bold; font-style: normal; src: url('/fonts/MonaspaceArgon-Bold.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceArgon'; font-weight: bold; font-style: italic; src: url('/fonts/MonaspaceArgon-BoldItalic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceArgon'; font-weight: normal; font-style: italic; src: url('/fonts/MonaspaceArgon-Italic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceArgon'; font-weight: normal; font-style: normal; src: url('/fonts/MonaspaceArgon-Regular.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceKrypton'; font-weight: bold; font-style: normal; src: url('/fonts/MonaspaceKrypton-Bold.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceKrypton'; font-weight: bold; font-style: italic; src: url('/fonts/MonaspaceKrypton-BoldItalic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceKrypton'; font-weight: normal; font-style: italic; src: url('/fonts/MonaspaceKrypton-Italic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceKrypton'; font-weight: normal; font-style: normal; src: url('/fonts/MonaspaceKrypton-Regular.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceNeon'; font-weight: bold; font-style: normal; src: url('/fonts/MonaspaceNeon-Bold.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceNeon'; font-weight: bold; font-style: italic; src: url('/fonts/MonaspaceNeon-BoldItalic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceNeon'; font-weight: normal; font-style: italic; src: url('/fonts/MonaspaceNeon-Italic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceNeon'; font-weight: normal; font-style: normal; src: url('/fonts/MonaspaceNeon-Regular.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceRadon'; font-weight: bold; font-style: normal; src: url('/fonts/MonaspaceRadon-Bold.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceRadon'; font-weight: bold; font-style: italic; src: url('/fonts/MonaspaceRadon-BoldItalic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceRadon'; font-weight: normal; font-style: italic; src: url('/fonts/MonaspaceRadon-Italic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceRadon'; font-weight: normal; font-style: normal; src: url('/fonts/MonaspaceRadon-Regular.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceXenon'; font-weight: bold; font-style: normal; src: url('/fonts/MonaspaceXenon-Bold.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceXenon'; font-weight: bold; font-style: italic; src: url('/fonts/MonaspaceXenon-BoldItalic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceXenon'; font-weight: normal; font-style: italic; src: url('/fonts/MonaspaceXenon-Italic.woff') format('woff2') }
+@font-face { font-display: swap; font-family: 'MonaspaceXenon'; font-weight: normal; font-style: normal; src: url('/fonts/MonaspaceXenon-Regular.woff') format('woff2') }
diff --git a/webassets/css/reset.css b/webassets/css/reset.css
new file mode 100644
index 0000000..932c3e9
--- /dev/null
+++ b/webassets/css/reset.css
@@ -0,0 +1,51 @@
+
+
+/* https://meyerweb.com/eric/tools/css/reset/ */
+
+
+/*
+ 1. Use a more-intuitive box-sizing model.
+*/
+*, *::before, *::after {
+ box-sizing: border-box;
+}
+/*
+ 2. Remove default margin
+*/
+* {
+ margin: 0;
+}
+/*
+ Typographic tweaks!
+ 3. Add accessible line-height
+ 4. Improve text rendering
+*/
+body {
+ line-height: 1.5;
+ -webkit-font-smoothing: antialiased;
+}
+/*
+ 5. Improve media defaults
+*/
+img, picture, video, canvas, svg {
+ display: block;
+ max-width: 100%;
+}
+/*
+ 6. Remove built-in form typography styles
+*/
+input, button, textarea, select {
+ font: inherit;
+}
+/*
+ 7. Avoid text overflows
+*/
+p, h1, h2, h3, h4, h5, h6 {
+ overflow-wrap: break-word;
+}
+/*
+ 8. Create a root stacking context
+*/
+#root, #__next {
+ isolation: isolate;
+}
\ No newline at end of file
diff --git a/webassets/css/styles.css b/webassets/css/styles.css
new file mode 100644
index 0000000..9b9a250
--- /dev/null
+++ b/webassets/css/styles.css
@@ -0,0 +1,55 @@
+
+* {
+ font-family: 'MonaspaceXenon';
+}
+
+html, body {
+ width: 100%;
+}
+
+body {
+ display: flex;
+ justify-content: center;
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+
+ margin: 1rem;
+}
+
+h1 {
+ margin-bottom: 1rem;
+}
+
+#maincontent {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+
+ padding: 0 1rem;
+}
+
+.server {
+ background-color: #CCC;
+ text-align: center;
+ padding: 2px 0.5rem;
+
+ color: black;
+ text-decoration: none;
+
+ border-radius: 6px;
+ border: 1px solid #888;
+
+ box-shadow: 0 0 4px #888;
+
+ transition: all 0.2s;
+}
+
+.server:hover {
+ box-shadow: 0 0 4px #000;
+ background-color: #AAA;
+ color: #00F;
+}
+
diff --git a/webassets/favicon.ico b/webassets/favicon.ico
new file mode 100644
index 0000000..37d44b8
Binary files /dev/null and b/webassets/favicon.ico differ
diff --git a/webassets/fonts/MonaspaceArgon-Bold.woff b/webassets/fonts/MonaspaceArgon-Bold.woff
new file mode 100644
index 0000000..1c00d13
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-Bold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-BoldItalic.woff b/webassets/fonts/MonaspaceArgon-BoldItalic.woff
new file mode 100644
index 0000000..05006ea
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-BoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-ExtraBold.woff b/webassets/fonts/MonaspaceArgon-ExtraBold.woff
new file mode 100644
index 0000000..ec5d5e6
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-ExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-ExtraBoldItalic.woff b/webassets/fonts/MonaspaceArgon-ExtraBoldItalic.woff
new file mode 100644
index 0000000..79dad47
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-ExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-ExtraLight.woff b/webassets/fonts/MonaspaceArgon-ExtraLight.woff
new file mode 100644
index 0000000..4d7c6a2
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-ExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-ExtraLightItalic.woff b/webassets/fonts/MonaspaceArgon-ExtraLightItalic.woff
new file mode 100644
index 0000000..b878e39
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-ExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-Italic.woff b/webassets/fonts/MonaspaceArgon-Italic.woff
new file mode 100644
index 0000000..140547c
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-Italic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-Light.woff b/webassets/fonts/MonaspaceArgon-Light.woff
new file mode 100644
index 0000000..1f008e9
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-Light.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-LightItalic.woff b/webassets/fonts/MonaspaceArgon-LightItalic.woff
new file mode 100644
index 0000000..dc64d0d
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-LightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-Medium.woff b/webassets/fonts/MonaspaceArgon-Medium.woff
new file mode 100644
index 0000000..7ffe215
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-Medium.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-MediumItalic.woff b/webassets/fonts/MonaspaceArgon-MediumItalic.woff
new file mode 100644
index 0000000..ca4053e
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-MediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-Regular.woff b/webassets/fonts/MonaspaceArgon-Regular.woff
new file mode 100644
index 0000000..adcd7ba
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-Regular.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiBold.woff b/webassets/fonts/MonaspaceArgon-SemiBold.woff
new file mode 100644
index 0000000..26b60db
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiBoldItalic.woff b/webassets/fonts/MonaspaceArgon-SemiBoldItalic.woff
new file mode 100644
index 0000000..ca613e8
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideBold.woff b/webassets/fonts/MonaspaceArgon-SemiWideBold.woff
new file mode 100644
index 0000000..96b7f4d
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideBoldItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideBoldItalic.woff
new file mode 100644
index 0000000..8ec1b93
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideExtraBold.woff b/webassets/fonts/MonaspaceArgon-SemiWideExtraBold.woff
new file mode 100644
index 0000000..e7d7bfb
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideExtraBoldItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideExtraBoldItalic.woff
new file mode 100644
index 0000000..57b75fc
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideExtraLight.woff b/webassets/fonts/MonaspaceArgon-SemiWideExtraLight.woff
new file mode 100644
index 0000000..561de12
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideExtraLightItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideExtraLightItalic.woff
new file mode 100644
index 0000000..9eb06f3
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideItalic.woff
new file mode 100644
index 0000000..98fa54f
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideLight.woff b/webassets/fonts/MonaspaceArgon-SemiWideLight.woff
new file mode 100644
index 0000000..809e92c
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideLight.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideLightItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideLightItalic.woff
new file mode 100644
index 0000000..f177036
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideMedium.woff b/webassets/fonts/MonaspaceArgon-SemiWideMedium.woff
new file mode 100644
index 0000000..d344175
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideMediumItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideMediumItalic.woff
new file mode 100644
index 0000000..4021053
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideRegular.woff b/webassets/fonts/MonaspaceArgon-SemiWideRegular.woff
new file mode 100644
index 0000000..26b6c1f
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideSemiBold.woff b/webassets/fonts/MonaspaceArgon-SemiWideSemiBold.woff
new file mode 100644
index 0000000..0be9d54
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-SemiWideSemiBoldItalic.woff b/webassets/fonts/MonaspaceArgon-SemiWideSemiBoldItalic.woff
new file mode 100644
index 0000000..4bae061
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-SemiWideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideBold.woff b/webassets/fonts/MonaspaceArgon-WideBold.woff
new file mode 100644
index 0000000..c03ddc2
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideBoldItalic.woff b/webassets/fonts/MonaspaceArgon-WideBoldItalic.woff
new file mode 100644
index 0000000..f99890a
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideExtraBold.woff b/webassets/fonts/MonaspaceArgon-WideExtraBold.woff
new file mode 100644
index 0000000..693213d
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideExtraBoldItalic.woff b/webassets/fonts/MonaspaceArgon-WideExtraBoldItalic.woff
new file mode 100644
index 0000000..8da659a
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideExtraLight.woff b/webassets/fonts/MonaspaceArgon-WideExtraLight.woff
new file mode 100644
index 0000000..7b3f395
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideExtraLightItalic.woff b/webassets/fonts/MonaspaceArgon-WideExtraLightItalic.woff
new file mode 100644
index 0000000..9809437
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideItalic.woff b/webassets/fonts/MonaspaceArgon-WideItalic.woff
new file mode 100644
index 0000000..6ecdc3c
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideLight.woff b/webassets/fonts/MonaspaceArgon-WideLight.woff
new file mode 100644
index 0000000..98af621
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideLight.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideLightItalic.woff b/webassets/fonts/MonaspaceArgon-WideLightItalic.woff
new file mode 100644
index 0000000..bb0577f
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideMedium.woff b/webassets/fonts/MonaspaceArgon-WideMedium.woff
new file mode 100644
index 0000000..f045979
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideMediumItalic.woff b/webassets/fonts/MonaspaceArgon-WideMediumItalic.woff
new file mode 100644
index 0000000..a24855f
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideRegular.woff b/webassets/fonts/MonaspaceArgon-WideRegular.woff
new file mode 100644
index 0000000..abbb77b
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideSemiBold.woff b/webassets/fonts/MonaspaceArgon-WideSemiBold.woff
new file mode 100644
index 0000000..a0c546c
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceArgon-WideSemiBoldItalic.woff b/webassets/fonts/MonaspaceArgon-WideSemiBoldItalic.woff
new file mode 100644
index 0000000..3d9956a
Binary files /dev/null and b/webassets/fonts/MonaspaceArgon-WideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceArgonVarVF[wght,wdth,slnt].woff b/webassets/fonts/MonaspaceArgonVarVF[wght,wdth,slnt].woff
new file mode 100644
index 0000000..b10ceac
Binary files /dev/null and b/webassets/fonts/MonaspaceArgonVarVF[wght,wdth,slnt].woff differ
diff --git a/webassets/fonts/MonaspaceArgonVarVF[wght,wdth,slnt].woff2 b/webassets/fonts/MonaspaceArgonVarVF[wght,wdth,slnt].woff2
new file mode 100644
index 0000000..6ec49f0
Binary files /dev/null and b/webassets/fonts/MonaspaceArgonVarVF[wght,wdth,slnt].woff2 differ
diff --git a/webassets/fonts/MonaspaceKrypton-Bold.woff b/webassets/fonts/MonaspaceKrypton-Bold.woff
new file mode 100644
index 0000000..19fe6e7
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-Bold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-BoldItalic.woff b/webassets/fonts/MonaspaceKrypton-BoldItalic.woff
new file mode 100644
index 0000000..e82e99c
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-BoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-ExtraBold.woff b/webassets/fonts/MonaspaceKrypton-ExtraBold.woff
new file mode 100644
index 0000000..8bc44da
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-ExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-ExtraBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-ExtraBoldItalic.woff
new file mode 100644
index 0000000..2c5b631
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-ExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-ExtraLight.woff b/webassets/fonts/MonaspaceKrypton-ExtraLight.woff
new file mode 100644
index 0000000..b6150be
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-ExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-ExtraLightItalic.woff b/webassets/fonts/MonaspaceKrypton-ExtraLightItalic.woff
new file mode 100644
index 0000000..2ca63fb
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-ExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-Italic.woff b/webassets/fonts/MonaspaceKrypton-Italic.woff
new file mode 100644
index 0000000..d2c9cfe
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-Italic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-Light.woff b/webassets/fonts/MonaspaceKrypton-Light.woff
new file mode 100644
index 0000000..f2ad9ff
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-Light.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-LightItalic.woff b/webassets/fonts/MonaspaceKrypton-LightItalic.woff
new file mode 100644
index 0000000..f7d3b1b
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-LightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-Medium.woff b/webassets/fonts/MonaspaceKrypton-Medium.woff
new file mode 100644
index 0000000..87ee1cd
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-Medium.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-MediumItalic.woff b/webassets/fonts/MonaspaceKrypton-MediumItalic.woff
new file mode 100644
index 0000000..fde0ec8
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-MediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-Regular.woff b/webassets/fonts/MonaspaceKrypton-Regular.woff
new file mode 100644
index 0000000..34e5a87
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-Regular.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiBold.woff b/webassets/fonts/MonaspaceKrypton-SemiBold.woff
new file mode 100644
index 0000000..7a7185e
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiBoldItalic.woff
new file mode 100644
index 0000000..3ed5727
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideBold.woff b/webassets/fonts/MonaspaceKrypton-SemiWideBold.woff
new file mode 100644
index 0000000..fb575b3
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideBoldItalic.woff
new file mode 100644
index 0000000..42ca502
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideExtraBold.woff b/webassets/fonts/MonaspaceKrypton-SemiWideExtraBold.woff
new file mode 100644
index 0000000..8b48386
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideExtraBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideExtraBoldItalic.woff
new file mode 100644
index 0000000..a1786a3
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideExtraLight.woff b/webassets/fonts/MonaspaceKrypton-SemiWideExtraLight.woff
new file mode 100644
index 0000000..891bd12
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideExtraLightItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideExtraLightItalic.woff
new file mode 100644
index 0000000..b2f16ce
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideItalic.woff
new file mode 100644
index 0000000..fcd54c8
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideLight.woff b/webassets/fonts/MonaspaceKrypton-SemiWideLight.woff
new file mode 100644
index 0000000..42b924c
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideLight.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideLightItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideLightItalic.woff
new file mode 100644
index 0000000..12b19d7
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideMedium.woff b/webassets/fonts/MonaspaceKrypton-SemiWideMedium.woff
new file mode 100644
index 0000000..2a9fea8
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideMediumItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideMediumItalic.woff
new file mode 100644
index 0000000..0fa808d
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideRegular.woff b/webassets/fonts/MonaspaceKrypton-SemiWideRegular.woff
new file mode 100644
index 0000000..b9dea16
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideSemiBold.woff b/webassets/fonts/MonaspaceKrypton-SemiWideSemiBold.woff
new file mode 100644
index 0000000..1b1617e
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-SemiWideSemiBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-SemiWideSemiBoldItalic.woff
new file mode 100644
index 0000000..c23969d
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-SemiWideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideBold.woff b/webassets/fonts/MonaspaceKrypton-WideBold.woff
new file mode 100644
index 0000000..3b98b7f
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-WideBoldItalic.woff
new file mode 100644
index 0000000..3846089
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideExtraBold.woff b/webassets/fonts/MonaspaceKrypton-WideExtraBold.woff
new file mode 100644
index 0000000..8988e49
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideExtraBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-WideExtraBoldItalic.woff
new file mode 100644
index 0000000..d5197ad
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideExtraLight.woff b/webassets/fonts/MonaspaceKrypton-WideExtraLight.woff
new file mode 100644
index 0000000..d34ac4f
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideExtraLightItalic.woff b/webassets/fonts/MonaspaceKrypton-WideExtraLightItalic.woff
new file mode 100644
index 0000000..1fab466
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideItalic.woff b/webassets/fonts/MonaspaceKrypton-WideItalic.woff
new file mode 100644
index 0000000..0b5914f
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideLight.woff b/webassets/fonts/MonaspaceKrypton-WideLight.woff
new file mode 100644
index 0000000..137707d
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideLight.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideLightItalic.woff b/webassets/fonts/MonaspaceKrypton-WideLightItalic.woff
new file mode 100644
index 0000000..ecd5738
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideMedium.woff b/webassets/fonts/MonaspaceKrypton-WideMedium.woff
new file mode 100644
index 0000000..b141388
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideMediumItalic.woff b/webassets/fonts/MonaspaceKrypton-WideMediumItalic.woff
new file mode 100644
index 0000000..9725fdd
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideRegular.woff b/webassets/fonts/MonaspaceKrypton-WideRegular.woff
new file mode 100644
index 0000000..ee89b68
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideSemiBold.woff b/webassets/fonts/MonaspaceKrypton-WideSemiBold.woff
new file mode 100644
index 0000000..3b4f039
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceKrypton-WideSemiBoldItalic.woff b/webassets/fonts/MonaspaceKrypton-WideSemiBoldItalic.woff
new file mode 100644
index 0000000..54cdb84
Binary files /dev/null and b/webassets/fonts/MonaspaceKrypton-WideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceKryptonVarVF[wght,wdth,slnt].woff b/webassets/fonts/MonaspaceKryptonVarVF[wght,wdth,slnt].woff
new file mode 100644
index 0000000..0c38488
Binary files /dev/null and b/webassets/fonts/MonaspaceKryptonVarVF[wght,wdth,slnt].woff differ
diff --git a/webassets/fonts/MonaspaceKryptonVarVF[wght,wdth,slnt].woff2 b/webassets/fonts/MonaspaceKryptonVarVF[wght,wdth,slnt].woff2
new file mode 100644
index 0000000..dfb9866
Binary files /dev/null and b/webassets/fonts/MonaspaceKryptonVarVF[wght,wdth,slnt].woff2 differ
diff --git a/webassets/fonts/MonaspaceNeon-Bold.woff b/webassets/fonts/MonaspaceNeon-Bold.woff
new file mode 100644
index 0000000..541cb4b
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-Bold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-BoldItalic.woff b/webassets/fonts/MonaspaceNeon-BoldItalic.woff
new file mode 100644
index 0000000..1509ddd
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-BoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-ExtraBold.woff b/webassets/fonts/MonaspaceNeon-ExtraBold.woff
new file mode 100644
index 0000000..f2640e8
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-ExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-ExtraBoldItalic.woff b/webassets/fonts/MonaspaceNeon-ExtraBoldItalic.woff
new file mode 100644
index 0000000..fcbafb6
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-ExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-ExtraLight.woff b/webassets/fonts/MonaspaceNeon-ExtraLight.woff
new file mode 100644
index 0000000..f8380b7
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-ExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-ExtraLightItalic.woff b/webassets/fonts/MonaspaceNeon-ExtraLightItalic.woff
new file mode 100644
index 0000000..1bb5381
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-ExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-Italic.woff b/webassets/fonts/MonaspaceNeon-Italic.woff
new file mode 100644
index 0000000..9264e0b
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-Italic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-Light.woff b/webassets/fonts/MonaspaceNeon-Light.woff
new file mode 100644
index 0000000..192619c
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-Light.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-LightItalic.woff b/webassets/fonts/MonaspaceNeon-LightItalic.woff
new file mode 100644
index 0000000..a920535
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-LightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-Medium.woff b/webassets/fonts/MonaspaceNeon-Medium.woff
new file mode 100644
index 0000000..91ae113
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-Medium.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-MediumItalic.woff b/webassets/fonts/MonaspaceNeon-MediumItalic.woff
new file mode 100644
index 0000000..9a7a07f
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-MediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-Regular.woff b/webassets/fonts/MonaspaceNeon-Regular.woff
new file mode 100644
index 0000000..ce0168b
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-Regular.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiBold.woff b/webassets/fonts/MonaspaceNeon-SemiBold.woff
new file mode 100644
index 0000000..c31abc1
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiBoldItalic.woff b/webassets/fonts/MonaspaceNeon-SemiBoldItalic.woff
new file mode 100644
index 0000000..9e0a4e6
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideBold.woff b/webassets/fonts/MonaspaceNeon-SemiWideBold.woff
new file mode 100644
index 0000000..1bd5544
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideBoldItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideBoldItalic.woff
new file mode 100644
index 0000000..36d969e
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideExtraBold.woff b/webassets/fonts/MonaspaceNeon-SemiWideExtraBold.woff
new file mode 100644
index 0000000..66c6e10
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideExtraBoldItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideExtraBoldItalic.woff
new file mode 100644
index 0000000..8a6f43d
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideExtraLight.woff b/webassets/fonts/MonaspaceNeon-SemiWideExtraLight.woff
new file mode 100644
index 0000000..2df8b26
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideExtraLightItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideExtraLightItalic.woff
new file mode 100644
index 0000000..6252c87
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideItalic.woff
new file mode 100644
index 0000000..e60fad9
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideLight.woff b/webassets/fonts/MonaspaceNeon-SemiWideLight.woff
new file mode 100644
index 0000000..7ca6ddc
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideLight.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideLightItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideLightItalic.woff
new file mode 100644
index 0000000..a06c738
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideMedium.woff b/webassets/fonts/MonaspaceNeon-SemiWideMedium.woff
new file mode 100644
index 0000000..57a67ab
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideMediumItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideMediumItalic.woff
new file mode 100644
index 0000000..f59f939
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideRegular.woff b/webassets/fonts/MonaspaceNeon-SemiWideRegular.woff
new file mode 100644
index 0000000..d9baf49
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideSemiBold.woff b/webassets/fonts/MonaspaceNeon-SemiWideSemiBold.woff
new file mode 100644
index 0000000..0f31632
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-SemiWideSemiBoldItalic.woff b/webassets/fonts/MonaspaceNeon-SemiWideSemiBoldItalic.woff
new file mode 100644
index 0000000..89816fa
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-SemiWideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideBold.woff b/webassets/fonts/MonaspaceNeon-WideBold.woff
new file mode 100644
index 0000000..0eadcb9
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideBoldItalic.woff b/webassets/fonts/MonaspaceNeon-WideBoldItalic.woff
new file mode 100644
index 0000000..1040f92
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideExtraBold.woff b/webassets/fonts/MonaspaceNeon-WideExtraBold.woff
new file mode 100644
index 0000000..6e3a20a
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideExtraBoldItalic.woff b/webassets/fonts/MonaspaceNeon-WideExtraBoldItalic.woff
new file mode 100644
index 0000000..c3f24c3
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideExtraLight.woff b/webassets/fonts/MonaspaceNeon-WideExtraLight.woff
new file mode 100644
index 0000000..d569685
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideExtraLightItalic.woff b/webassets/fonts/MonaspaceNeon-WideExtraLightItalic.woff
new file mode 100644
index 0000000..fa657b3
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideItalic.woff b/webassets/fonts/MonaspaceNeon-WideItalic.woff
new file mode 100644
index 0000000..fa8627b
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideLight.woff b/webassets/fonts/MonaspaceNeon-WideLight.woff
new file mode 100644
index 0000000..58197a8
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideLight.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideLightItalic.woff b/webassets/fonts/MonaspaceNeon-WideLightItalic.woff
new file mode 100644
index 0000000..e8cceb3
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideMedium.woff b/webassets/fonts/MonaspaceNeon-WideMedium.woff
new file mode 100644
index 0000000..36afb79
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideMediumItalic.woff b/webassets/fonts/MonaspaceNeon-WideMediumItalic.woff
new file mode 100644
index 0000000..f1efbe7
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideRegular.woff b/webassets/fonts/MonaspaceNeon-WideRegular.woff
new file mode 100644
index 0000000..b4dbee5
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideSemiBold.woff b/webassets/fonts/MonaspaceNeon-WideSemiBold.woff
new file mode 100644
index 0000000..3e204d7
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceNeon-WideSemiBoldItalic.woff b/webassets/fonts/MonaspaceNeon-WideSemiBoldItalic.woff
new file mode 100644
index 0000000..9a6ef6a
Binary files /dev/null and b/webassets/fonts/MonaspaceNeon-WideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceNeonVarVF[wght,wdth,slnt].woff b/webassets/fonts/MonaspaceNeonVarVF[wght,wdth,slnt].woff
new file mode 100644
index 0000000..cc93a04
Binary files /dev/null and b/webassets/fonts/MonaspaceNeonVarVF[wght,wdth,slnt].woff differ
diff --git a/webassets/fonts/MonaspaceNeonVarVF[wght,wdth,slnt].woff2 b/webassets/fonts/MonaspaceNeonVarVF[wght,wdth,slnt].woff2
new file mode 100644
index 0000000..74117fc
Binary files /dev/null and b/webassets/fonts/MonaspaceNeonVarVF[wght,wdth,slnt].woff2 differ
diff --git a/webassets/fonts/MonaspaceRadon-Bold.woff b/webassets/fonts/MonaspaceRadon-Bold.woff
new file mode 100644
index 0000000..75b8894
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-Bold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-BoldItalic.woff b/webassets/fonts/MonaspaceRadon-BoldItalic.woff
new file mode 100644
index 0000000..b27d652
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-BoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-ExtraBold.woff b/webassets/fonts/MonaspaceRadon-ExtraBold.woff
new file mode 100644
index 0000000..7695651
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-ExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-ExtraBoldItalic.woff b/webassets/fonts/MonaspaceRadon-ExtraBoldItalic.woff
new file mode 100644
index 0000000..92cdbbb
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-ExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-ExtraLight.woff b/webassets/fonts/MonaspaceRadon-ExtraLight.woff
new file mode 100644
index 0000000..75cbe70
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-ExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-ExtraLightItalic.woff b/webassets/fonts/MonaspaceRadon-ExtraLightItalic.woff
new file mode 100644
index 0000000..9030786
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-ExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-Italic.woff b/webassets/fonts/MonaspaceRadon-Italic.woff
new file mode 100644
index 0000000..4a2939c
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-Italic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-Light.woff b/webassets/fonts/MonaspaceRadon-Light.woff
new file mode 100644
index 0000000..81bcaf1
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-Light.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-LightItalic.woff b/webassets/fonts/MonaspaceRadon-LightItalic.woff
new file mode 100644
index 0000000..5e93a26
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-LightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-Medium.woff b/webassets/fonts/MonaspaceRadon-Medium.woff
new file mode 100644
index 0000000..2f0aa07
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-Medium.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-MediumItalic.woff b/webassets/fonts/MonaspaceRadon-MediumItalic.woff
new file mode 100644
index 0000000..938c7ef
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-MediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-Regular.woff b/webassets/fonts/MonaspaceRadon-Regular.woff
new file mode 100644
index 0000000..2a72b04
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-Regular.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiBold.woff b/webassets/fonts/MonaspaceRadon-SemiBold.woff
new file mode 100644
index 0000000..af383b0
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiBoldItalic.woff b/webassets/fonts/MonaspaceRadon-SemiBoldItalic.woff
new file mode 100644
index 0000000..ade405d
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideBold.woff b/webassets/fonts/MonaspaceRadon-SemiWideBold.woff
new file mode 100644
index 0000000..7d76db6
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideBoldItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideBoldItalic.woff
new file mode 100644
index 0000000..85e0486
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideExtraBold.woff b/webassets/fonts/MonaspaceRadon-SemiWideExtraBold.woff
new file mode 100644
index 0000000..2513973
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideExtraBoldItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideExtraBoldItalic.woff
new file mode 100644
index 0000000..4ebb9a5
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideExtraLight.woff b/webassets/fonts/MonaspaceRadon-SemiWideExtraLight.woff
new file mode 100644
index 0000000..cf4574d
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideExtraLightItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideExtraLightItalic.woff
new file mode 100644
index 0000000..60b8dd0
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideItalic.woff
new file mode 100644
index 0000000..b23b008
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideLight.woff b/webassets/fonts/MonaspaceRadon-SemiWideLight.woff
new file mode 100644
index 0000000..2d05296
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideLight.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideLightItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideLightItalic.woff
new file mode 100644
index 0000000..c00d6ca
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideMedium.woff b/webassets/fonts/MonaspaceRadon-SemiWideMedium.woff
new file mode 100644
index 0000000..057e397
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideMediumItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideMediumItalic.woff
new file mode 100644
index 0000000..dfaed41
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideRegular.woff b/webassets/fonts/MonaspaceRadon-SemiWideRegular.woff
new file mode 100644
index 0000000..cf55da5
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideSemiBold.woff b/webassets/fonts/MonaspaceRadon-SemiWideSemiBold.woff
new file mode 100644
index 0000000..5f5b50c
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-SemiWideSemiBoldItalic.woff b/webassets/fonts/MonaspaceRadon-SemiWideSemiBoldItalic.woff
new file mode 100644
index 0000000..bae92e4
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-SemiWideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideBold.woff b/webassets/fonts/MonaspaceRadon-WideBold.woff
new file mode 100644
index 0000000..fe477fd
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideBoldItalic.woff b/webassets/fonts/MonaspaceRadon-WideBoldItalic.woff
new file mode 100644
index 0000000..820906c
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideExtraBold.woff b/webassets/fonts/MonaspaceRadon-WideExtraBold.woff
new file mode 100644
index 0000000..c14184d
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideExtraBoldItalic.woff b/webassets/fonts/MonaspaceRadon-WideExtraBoldItalic.woff
new file mode 100644
index 0000000..7ffe48d
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideExtraLight.woff b/webassets/fonts/MonaspaceRadon-WideExtraLight.woff
new file mode 100644
index 0000000..393e742
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideExtraLightItalic.woff b/webassets/fonts/MonaspaceRadon-WideExtraLightItalic.woff
new file mode 100644
index 0000000..3416740
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideItalic.woff b/webassets/fonts/MonaspaceRadon-WideItalic.woff
new file mode 100644
index 0000000..c9d071c
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideLight.woff b/webassets/fonts/MonaspaceRadon-WideLight.woff
new file mode 100644
index 0000000..65ab94b
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideLight.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideLightItalic.woff b/webassets/fonts/MonaspaceRadon-WideLightItalic.woff
new file mode 100644
index 0000000..8a9c4bc
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideMedium.woff b/webassets/fonts/MonaspaceRadon-WideMedium.woff
new file mode 100644
index 0000000..6c342d0
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideMediumItalic.woff b/webassets/fonts/MonaspaceRadon-WideMediumItalic.woff
new file mode 100644
index 0000000..db5dbc1
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideRegular.woff b/webassets/fonts/MonaspaceRadon-WideRegular.woff
new file mode 100644
index 0000000..567246f
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideSemiBold.woff b/webassets/fonts/MonaspaceRadon-WideSemiBold.woff
new file mode 100644
index 0000000..491ded7
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceRadon-WideSemiBoldItalic.woff b/webassets/fonts/MonaspaceRadon-WideSemiBoldItalic.woff
new file mode 100644
index 0000000..0555bdd
Binary files /dev/null and b/webassets/fonts/MonaspaceRadon-WideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceRadonVarVF[wght,wdth,slnt].woff b/webassets/fonts/MonaspaceRadonVarVF[wght,wdth,slnt].woff
new file mode 100644
index 0000000..e328b99
Binary files /dev/null and b/webassets/fonts/MonaspaceRadonVarVF[wght,wdth,slnt].woff differ
diff --git a/webassets/fonts/MonaspaceRadonVarVF[wght,wdth,slnt].woff2 b/webassets/fonts/MonaspaceRadonVarVF[wght,wdth,slnt].woff2
new file mode 100644
index 0000000..b2feb7b
Binary files /dev/null and b/webassets/fonts/MonaspaceRadonVarVF[wght,wdth,slnt].woff2 differ
diff --git a/webassets/fonts/MonaspaceXenon-Bold.woff b/webassets/fonts/MonaspaceXenon-Bold.woff
new file mode 100644
index 0000000..99daf27
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-Bold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-BoldItalic.woff b/webassets/fonts/MonaspaceXenon-BoldItalic.woff
new file mode 100644
index 0000000..50ed959
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-BoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-ExtraBold.woff b/webassets/fonts/MonaspaceXenon-ExtraBold.woff
new file mode 100644
index 0000000..1f18154
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-ExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-ExtraBoldItalic.woff b/webassets/fonts/MonaspaceXenon-ExtraBoldItalic.woff
new file mode 100644
index 0000000..e8242f7
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-ExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-ExtraLight.woff b/webassets/fonts/MonaspaceXenon-ExtraLight.woff
new file mode 100644
index 0000000..7318830
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-ExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-ExtraLightItalic.woff b/webassets/fonts/MonaspaceXenon-ExtraLightItalic.woff
new file mode 100644
index 0000000..a0ae787
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-ExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-Italic.woff b/webassets/fonts/MonaspaceXenon-Italic.woff
new file mode 100644
index 0000000..2fd2009
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-Italic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-Light.woff b/webassets/fonts/MonaspaceXenon-Light.woff
new file mode 100644
index 0000000..2fdbe64
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-Light.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-LightItalic.woff b/webassets/fonts/MonaspaceXenon-LightItalic.woff
new file mode 100644
index 0000000..f702449
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-LightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-Medium.woff b/webassets/fonts/MonaspaceXenon-Medium.woff
new file mode 100644
index 0000000..abaf72b
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-Medium.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-MediumItalic.woff b/webassets/fonts/MonaspaceXenon-MediumItalic.woff
new file mode 100644
index 0000000..43d2045
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-MediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-Regular.woff b/webassets/fonts/MonaspaceXenon-Regular.woff
new file mode 100644
index 0000000..ad34890
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-Regular.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiBold.woff b/webassets/fonts/MonaspaceXenon-SemiBold.woff
new file mode 100644
index 0000000..a397b0f
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiBoldItalic.woff b/webassets/fonts/MonaspaceXenon-SemiBoldItalic.woff
new file mode 100644
index 0000000..5496ce3
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideBold.woff b/webassets/fonts/MonaspaceXenon-SemiWideBold.woff
new file mode 100644
index 0000000..1e603b7
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideBoldItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideBoldItalic.woff
new file mode 100644
index 0000000..d2da3c6
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideExtraBold.woff b/webassets/fonts/MonaspaceXenon-SemiWideExtraBold.woff
new file mode 100644
index 0000000..5cbce66
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideExtraBoldItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideExtraBoldItalic.woff
new file mode 100644
index 0000000..e58b7a3
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideExtraLight.woff b/webassets/fonts/MonaspaceXenon-SemiWideExtraLight.woff
new file mode 100644
index 0000000..5df264e
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideExtraLightItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideExtraLightItalic.woff
new file mode 100644
index 0000000..1301f44
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideItalic.woff
new file mode 100644
index 0000000..2537b82
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideLight.woff b/webassets/fonts/MonaspaceXenon-SemiWideLight.woff
new file mode 100644
index 0000000..8a81ffd
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideLight.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideLightItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideLightItalic.woff
new file mode 100644
index 0000000..007ccc1
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideMedium.woff b/webassets/fonts/MonaspaceXenon-SemiWideMedium.woff
new file mode 100644
index 0000000..ab2ab03
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideMediumItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideMediumItalic.woff
new file mode 100644
index 0000000..9428598
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideRegular.woff b/webassets/fonts/MonaspaceXenon-SemiWideRegular.woff
new file mode 100644
index 0000000..f2951e1
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideSemiBold.woff b/webassets/fonts/MonaspaceXenon-SemiWideSemiBold.woff
new file mode 100644
index 0000000..8bfdc66
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-SemiWideSemiBoldItalic.woff b/webassets/fonts/MonaspaceXenon-SemiWideSemiBoldItalic.woff
new file mode 100644
index 0000000..97a4ffd
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-SemiWideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideBold.woff b/webassets/fonts/MonaspaceXenon-WideBold.woff
new file mode 100644
index 0000000..d0bdadc
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideBoldItalic.woff b/webassets/fonts/MonaspaceXenon-WideBoldItalic.woff
new file mode 100644
index 0000000..acc0485
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideExtraBold.woff b/webassets/fonts/MonaspaceXenon-WideExtraBold.woff
new file mode 100644
index 0000000..27ecf88
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideExtraBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideExtraBoldItalic.woff b/webassets/fonts/MonaspaceXenon-WideExtraBoldItalic.woff
new file mode 100644
index 0000000..8d481b1
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideExtraBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideExtraLight.woff b/webassets/fonts/MonaspaceXenon-WideExtraLight.woff
new file mode 100644
index 0000000..4db048b
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideExtraLight.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideExtraLightItalic.woff b/webassets/fonts/MonaspaceXenon-WideExtraLightItalic.woff
new file mode 100644
index 0000000..16a0381
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideExtraLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideItalic.woff b/webassets/fonts/MonaspaceXenon-WideItalic.woff
new file mode 100644
index 0000000..9dd6d39
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideLight.woff b/webassets/fonts/MonaspaceXenon-WideLight.woff
new file mode 100644
index 0000000..ecd2cab
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideLight.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideLightItalic.woff b/webassets/fonts/MonaspaceXenon-WideLightItalic.woff
new file mode 100644
index 0000000..dd7a014
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideLightItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideMedium.woff b/webassets/fonts/MonaspaceXenon-WideMedium.woff
new file mode 100644
index 0000000..7d65fcc
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideMedium.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideMediumItalic.woff b/webassets/fonts/MonaspaceXenon-WideMediumItalic.woff
new file mode 100644
index 0000000..c2895f2
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideMediumItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideRegular.woff b/webassets/fonts/MonaspaceXenon-WideRegular.woff
new file mode 100644
index 0000000..40d9cbf
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideRegular.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideSemiBold.woff b/webassets/fonts/MonaspaceXenon-WideSemiBold.woff
new file mode 100644
index 0000000..319dd5a
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideSemiBold.woff differ
diff --git a/webassets/fonts/MonaspaceXenon-WideSemiBoldItalic.woff b/webassets/fonts/MonaspaceXenon-WideSemiBoldItalic.woff
new file mode 100644
index 0000000..a667e3c
Binary files /dev/null and b/webassets/fonts/MonaspaceXenon-WideSemiBoldItalic.woff differ
diff --git a/webassets/fonts/MonaspaceXenonVarVF[wght,wdth,slnt].woff b/webassets/fonts/MonaspaceXenonVarVF[wght,wdth,slnt].woff
new file mode 100644
index 0000000..87ebf9b
Binary files /dev/null and b/webassets/fonts/MonaspaceXenonVarVF[wght,wdth,slnt].woff differ
diff --git a/webassets/fonts/MonaspaceXenonVarVF[wght,wdth,slnt].woff2 b/webassets/fonts/MonaspaceXenonVarVF[wght,wdth,slnt].woff2
new file mode 100644
index 0000000..a9f8115
Binary files /dev/null and b/webassets/fonts/MonaspaceXenonVarVF[wght,wdth,slnt].woff2 differ
diff --git a/webassets/index.html b/webassets/index.html
new file mode 100644
index 0000000..91abd03
--- /dev/null
+++ b/webassets/index.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+ LocalhostBunny
+
+
+
+
+
+
+
+
+
+
+
+ LocalHostBunny
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webassets/scripts/script.js b/webassets/scripts/script.js
new file mode 100644
index 0000000..315a56e
--- /dev/null
+++ b/webassets/scripts/script.js
@@ -0,0 +1,17 @@
+
+function updateHTML() {
+
+ const main = document.getElementById('maincontent')
+
+ let html = '';
+
+ for (const srv of servers) {
+
+ html += `${encodeURIComponent(srv['process'])} @ ${encodeURIComponent(srv['port'])}`
+
+ }
+ main.innerHTML = html;
+
+}
+
+document.addEventListener("DOMContentLoaded", updateHTML);
\ No newline at end of file
diff --git a/webassets/website.go b/webassets/website.go
new file mode 100644
index 0000000..bdd5eb3
--- /dev/null
+++ b/webassets/website.go
@@ -0,0 +1,222 @@
+package webassets
+
+import (
+ "embed"
+ "fmt"
+ "github.com/rs/zerolog/log"
+ "io"
+ bunny "locbunny"
+ "os"
+ "path/filepath"
+ "sync"
+ "time"
+)
+
+//go:embed *.html
+//go:embed *.ico
+//go:embed scripts/*.js
+//go:embed css/*.css
+//go:embed fonts/*.woff
+//go:embed fonts/*.woff2
+var _assets embed.FS
+
+type templateCacheEntry struct {
+ MDate time.Time
+ Value ITemplate
+}
+
+type fileCacheEntry struct {
+ MDate time.Time
+ Value []byte
+}
+
+type Assets struct {
+ templateCache map[string]templateCacheEntry
+ fileCache map[string]fileCacheEntry
+ lock sync.RWMutex
+}
+
+func NewAssets() *Assets {
+ return &Assets{
+ templateCache: make(map[string]templateCacheEntry, 128),
+ fileCache: make(map[string]fileCacheEntry, 128),
+ lock: sync.RWMutex{},
+ }
+}
+
+type ITemplate interface {
+ Execute(wr io.Writer, data any) error
+}
+
+func (a *Assets) ListAssets() []string {
+ result := make([]string, 0)
+
+ entries, err := _assets.ReadDir(".")
+ if err != nil {
+ panic(err)
+ }
+
+ for _, entry := range entries {
+ if entry.IsDir() {
+ panic("TODO implement recursion")
+ }
+
+ if entry.Name() == "index.html" {
+ continue
+ }
+
+ result = append(result, "/"+entry.Name())
+ }
+
+ return result
+}
+
+func (a *Assets) Read(fp string) ([]byte, error) {
+ if bunny.Conf.LiveReload == nil {
+
+ // no live-reload: use embedded data
+
+ bin, err := _assets.ReadFile(fp)
+ if err != nil {
+ return nil, err
+ }
+ return bin, nil
+
+ } else {
+
+ liveFP := filepath.Join(*bunny.Conf.LiveReload, fp)
+
+ stat, err := os.Stat(liveFP)
+ if err != nil {
+ return nil, err
+ }
+
+ a.lock.RLock()
+ v, ok := a.fileCache[fp]
+ a.lock.RUnlock()
+
+ if !ok {
+
+ // initial load
+
+ bin, err := os.ReadFile(liveFP)
+ if err != nil {
+ return nil, err
+ }
+
+ a.lock.Lock()
+ a.fileCache[fp] = fileCacheEntry{MDate: stat.ModTime(), Value: bin}
+ a.lock.Unlock()
+
+ return bin, nil
+
+ } else if v.MDate != stat.ModTime() {
+
+ // live reload
+
+ log.Info().Msg(fmt.Sprintf("[>>] Live reload file '%s' from filesystem (file changed)", fp))
+
+ bin, err := os.ReadFile(liveFP)
+ if err != nil {
+ return nil, err
+ }
+
+ a.lock.Lock()
+ a.fileCache[fp] = fileCacheEntry{MDate: stat.ModTime(), Value: bin}
+ a.lock.Unlock()
+
+ return bin, nil
+
+ } else {
+ // return from cache
+ return v.Value, nil
+ }
+ }
+}
+
+func (a *Assets) Template(fp string, builder func([]byte) (ITemplate, error)) (ITemplate, error) {
+ if bunny.Conf.LiveReload == nil {
+
+ // no live-reload: use embedded data, and permanently cache template
+
+ a.lock.RLock()
+ v, ok := a.templateCache[fp]
+ a.lock.RUnlock()
+ if ok {
+ return v.Value, nil
+ }
+
+ bin, err := _assets.ReadFile(fp)
+ if err != nil {
+ return nil, err
+ }
+ t, err := builder(bin)
+ if err != nil {
+ panic(err)
+ }
+
+ a.lock.Lock()
+ a.templateCache[fp] = templateCacheEntry{MDate: time.Now(), Value: t}
+ a.lock.Unlock()
+
+ return t, nil
+
+ } else {
+
+ a.lock.RLock()
+ v, ok := a.templateCache[fp]
+ a.lock.RUnlock()
+
+ liveFP := filepath.Join(*bunny.Conf.LiveReload, fp)
+
+ stat, err := os.Stat(liveFP)
+ if err != nil {
+ return nil, err
+ }
+
+ if !ok {
+
+ // initial load
+
+ bin, err := os.ReadFile(liveFP)
+ if err != nil {
+ return nil, err
+ }
+ t, err := builder(bin)
+ if err != nil {
+ return nil, err
+ }
+
+ a.lock.Lock()
+ a.templateCache[fp] = templateCacheEntry{MDate: stat.ModTime(), Value: t}
+ a.lock.Unlock()
+
+ return t, nil
+
+ } else if v.MDate != stat.ModTime() {
+
+ // live reload
+
+ log.Info().Msg(fmt.Sprintf("[>>] Live reload file '%s' from filesystem (file changed)", fp))
+
+ bin, err := os.ReadFile(liveFP)
+ if err != nil {
+ return nil, err
+ }
+ t, err := builder(bin)
+ if err != nil {
+ return nil, err
+ }
+
+ a.lock.Lock()
+ a.templateCache[fp] = templateCacheEntry{MDate: stat.ModTime(), Value: t}
+ a.lock.Unlock()
+
+ return t, nil
+
+ } else {
+ // return from cache
+ return v.Value, nil
+ }
+ }
+}