commit cfb3f16f8200d63f35e3d212ec903751ea97326a Author: Eric Christensen Date: Tue Aug 4 18:34:18 2026 -0700 8/4/26 18:34 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aeeaa92 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.exe +/bin diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4249b5c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/odin-http"] + path = submodules/odin-http + url = https://github.com/laytan/odin-http.git diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..b1222b2 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,15 @@ +param( + [ValidateSet("run","build","debug","test","clean")] + [string]$Command = "build" +) + +$src = "." +$out = "bin\server.exe" + +switch ($Command) { + "run" { odin run $src } + "build" { odin build $src -out:$out -o:speed } + "debug" { odin build $src -out:$out -debug } + "test" { odin test .\tests\ -all-packages } + "clean" { Remove-Item -Recurse -Force bin -ErrorAction SilentlyContinue } +} diff --git a/handlers.odin b/handlers.odin new file mode 100644 index 0000000..1faa13f --- /dev/null +++ b/handlers.odin @@ -0,0 +1 @@ +package pheynnx diff --git a/ols.json b/ols.json new file mode 100644 index 0000000..4866a27 --- /dev/null +++ b/ols.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json", + "enable_document_symbols": true, + "enable_hover": true, + "enable_snippets": true +} diff --git a/routes.odin b/routes.odin new file mode 100644 index 0000000..1faa13f --- /dev/null +++ b/routes.odin @@ -0,0 +1 @@ +package pheynnx diff --git a/server.odin b/server.odin new file mode 100644 index 0000000..aba6a33 --- /dev/null +++ b/server.odin @@ -0,0 +1,80 @@ +package pheynnx + +import "core:fmt" +import "core:log" +import "core:net" +import "core:os" +import "core:path/filepath" +import "core:strings" +import http "submodules/odin-http" + +State :: struct { + num: int, + global_css: string, +} + +state := State { + num = 1, +} + +main :: proc() { + context.logger = log.create_console_logger(.Info) + + data, err2 := os.read_entire_file_from_path("styles/main.css", context.temp_allocator) + state.global_css = string(data) + + s: http.Server + http.server_shutdown_on_interrupt(&s) + + router: http.Router + http.router_init(&router) + defer http.router_destroy(&router) + + root_routes(&router) + + http.route_get(&router, "/static/(.*)", proc() -> http.Handler { + return http.Handler { + handle = proc(handler: ^http.Handler, req: ^http.Request, res: ^http.Response) { + rel_path := strings.trim_prefix(req.url.path, "/static/") + full_path, _ := filepath.join({"web/static", rel_path}) + defer delete(full_path) + + info, err := os.stat(full_path, context.temp_allocator) + if err != os.ERROR_NONE || info.type == .Directory { + http.respond(res, http.Status.Not_Found) + return + } + http.respond_dir(res, "/static/", "web/static", req.url.path) + + free_all(context.temp_allocator) + }, + } + + }()) + + routed := http.router_handler(&router) + + err := http.listen_and_serve(&s, routed, net.Endpoint{address = net.IP4_Loopback, port = 6969}) + fmt.assertf(err == nil, "server stopped with error: %v", err) +} + +// ROUTERS +root_routes :: proc(r: ^http.Router) { + http.route_get(r, "/one", one_handler()) + http.route_get(r, "/two", http.handler(two_handler)) +} + +// HANDLERS +one_handler :: proc() -> http.Handler { + return http.Handler { + handle = proc(handler: ^http.Handler, req: ^http.Request, res: ^http.Response) { + state.num += 1 + http.respond_html(res, render_index_page(&state)) + }, + } +} + +two_handler :: proc(req: ^http.Request, res: ^http.Response) { + state.num *= 2 + http.respond_html(res, render_index_page(&state)) +} diff --git a/styles/main.css b/styles/main.css new file mode 100644 index 0000000..0e2b391 --- /dev/null +++ b/styles/main.css @@ -0,0 +1,23 @@ +html { + background-color: black; + color: wheat; + font-family: "Inter", "Helvetica", ui-sans-serif, system-ui, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + -webkit-font-smoothing: antialiased; +} + +@font-face { + font-family: "Inter"; + font-weight: normal; + src: url("/static/fonts/InterVariable.woff2") format("woff2"); + font-display: swap; + font-weight: 100 900; +} + +@font-face { + font-family: "GeistMono"; + font-display: swap; + font-style: normal; + font-weight: normal; + src: url("/static/fonts/GeistMono.ttf"); +} diff --git a/submodules/odin-http b/submodules/odin-http new file mode 160000 index 0000000..65f57ca --- /dev/null +++ b/submodules/odin-http @@ -0,0 +1 @@ +Subproject commit 65f57ca5ed4978fba58b0c8d6cbabadbf1154e11 diff --git a/views.odin b/views.odin new file mode 100644 index 0000000..f3afe8e --- /dev/null +++ b/views.odin @@ -0,0 +1,26 @@ +package pheynnx + +import "core:fmt" +import "core:strings" + +render_index_page :: proc(s: ^State) -> string { + b: strings.Builder + strings.builder_init(&b) + defer strings.builder_destroy(&b) + + strings.write_string( + &b, + ` + My Blog + + `, + ) + fmt.sbprintf(&b, ``, state.global_css) + strings.write_string(&b, ` +
+

Hello!

`) + fmt.sbprintf(&b, `

%v

`, state.num) + strings.write_string(&b, `
`) + + return strings.clone(strings.to_string(b)) +} diff --git a/web/static/fonts/GeistMono.ttf b/web/static/fonts/GeistMono.ttf new file mode 100644 index 0000000..5ea4e68 Binary files /dev/null and b/web/static/fonts/GeistMono.ttf differ diff --git a/web/static/fonts/InterVariable.woff2 b/web/static/fonts/InterVariable.woff2 new file mode 100644 index 0000000..5a8d3e7 Binary files /dev/null and b/web/static/fonts/InterVariable.woff2 differ diff --git a/web/static/js/scripts.js b/web/static/js/scripts.js new file mode 100644 index 0000000..088fb21 --- /dev/null +++ b/web/static/js/scripts.js @@ -0,0 +1 @@ +console.log("WEHA!");