-- site — writeonce.de: the language tutorial, served BY the language. -- Full stack in one binary: writeonce-framework ([deps]) for HTTP/routing/ -- auth, wo-html ([deps]) for server-rendered pages with Tailwind-style -- utilities, @table + WAL for the chapters themselves. The site is its own -- final chapter: /ch/serving shows this file's shape. -- -- SITE_TOKEN=... WO_DATA=./data ./site 8080 -- SITE_HOST=0.0.0.0 ... ./site 8080 (reachable from the network) -- -- Behind nginx/caddy for writeonce.de: the proxy terminates TLS and -- forwards to 127.0.0.1:8080 (the framework speaks HTTP/1.1 keep-alive). -- -- This file is the BOOTSTRAP and nothing else: seed, routes, serve. The -- model is types.wo; every feature is a directory holding its view and -- its controller. use env use framework use framework/router use home use chapter use install use packages use admin use health use favicon fn main(args: multi Text) -> Int { if len(args) < 1 { print_err("usage: site (SITE_TOKEN gates /admin; WO_DATA makes chapters durable)"); return 2; } let port = parse_int(args[0]); if port == nil { print_err("site: must be a number"); return 2; } let token = env.get("SITE_TOKEN"); if token == nil { print_err("site: SITE_TOKEN is required (the admin route's bearer token)"); return 2; } -- Bind to loopback unless SITE_HOST says otherwise. Behind a proxy -- loopback is right; SITE_HOST=0.0.0.0 (or a LAN address) is how you -- reach it from another machine while developing. let host = "127.0.0.1"; let h = env.get("SITE_HOST"); if h != nil { host = "${h}"; } seed_if_empty(); let app = App { middleware: [], routes: [] }; app.use_mw(Mw { m: Logging {} }); app.get("/", Home {}); app.get("/install", ShowInstall {}); app.get("/packages", ShowPackages {}); app.get("/packages/:name", ShowPackage {}); app.get("/health", Health {}); app.get("/favicon.svg", Favicon {}); app.get("/ch/:slug", ShowChapter {}); app.post("/admin/ch/:slug", AdminEdit { token: "${token}" }); print_err("site: listening on ${host}:${port}"); return app.serve(host, port); }