From af2e1bfdb238068ec6d7f2087832240ec8ff8e9c Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Wed, 22 Jul 2026 18:36:02 +0200 Subject: [PATCH] fixed config + cli-args + admin form --- README.md | 8 ++ run.sh | 3 + src/.init.lua | 59 ++++++----- src/.lua/cmd | 1 + src/.lua/config.lua | 51 ++++++++++ src/.lua/middleware | 1 + src/.lua/soakbean.lua | 17 ++-- src/.lua/util.lua | 36 ++++++- src/admin/index.html | 158 ----------------------------- src/cmd/help.lua | 14 +-- src/{ => css}/xrforge.css | 97 ++++++++++++++++-- src/{ => css}/xrforge.max.css | 17 +++- src/img/backdrop.jpg | Bin 0 -> 7858 bytes src/page/admin/index.html | 128 +++++++++++++++++++++++ src/page/admin/index.lua | 27 +++++ src/page/design.html | 127 +++++++++++++++++++++++ src/{template => page}/footer.html | 0 src/{template => page}/header.html | 19 ++-- src/{template => page}/index.html | 0 src/{ => page}/index.lua | 2 +- src/run.sh | 2 - src/ui-kit.html | 147 --------------------------- src/xrforge.lua | 1 + util/xrforge.sh | 2 +- 24 files changed, 549 insertions(+), 368 deletions(-) create mode 100755 run.sh create mode 120000 src/.lua/cmd create mode 100644 src/.lua/config.lua create mode 120000 src/.lua/middleware delete mode 100644 src/admin/index.html rename src/{ => css}/xrforge.css (60%) rename src/{ => css}/xrforge.max.css (67%) create mode 100644 src/img/backdrop.jpg create mode 100644 src/page/admin/index.html create mode 100644 src/page/admin/index.lua create mode 100644 src/page/design.html rename src/{template => page}/footer.html (100%) rename src/{template => page}/header.html (59%) rename src/{template => page}/index.html (100%) rename src/{ => page}/index.lua (82%) delete mode 100755 src/run.sh delete mode 100644 src/ui-kit.html create mode 120000 src/xrforge.lua diff --git a/README.md b/README.md index 58ff181..82d2c62 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,11 @@ manual scan (via cli?) curl -L -X 'GET' 'http://xrforge.isvery.ninja/models?page=1&order=name' -H 'accept: application/vnd.manyfold.v0+json' curl -L -X 'GET' 'http://xrforge.isvery.ninja/models?page=1&order=recent' -H 'accept: application/vnd.manyfold.v0+json' ``` + +## Permacomputing Spirit + +* developed on [Dillo](https://dillo-browser.github.io/) as lowest common denominator / compatibility +* does not use javascript unless really needed (WebXR being the exception) +* server is using lua-scripting via cosmopolitan libc's [redbean](https://redbean.dev) + +> So yes in case you'd think the codebase is 90-ish: that's **exactly why it works** on potato-devices AND modern devices. diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..73a5f05 --- /dev/null +++ b/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cd src +../result/bin/xrforge.com -D . -- server diff --git a/src/.init.lua b/src/.init.lua index bebd3a2..8ded0fa 100644 --- a/src/.init.lua +++ b/src/.init.lua @@ -3,6 +3,8 @@ package.path = package.path .. ";src/.lua/?.lua" package.path = package.path .. ";middleware/?.lua" package.path = package.path .. ";cmd/?.lua" +print = function(...) Log(kLogInfo, ... or "''") end -- nice redbean logging from now on + util = require "util" json = require "json" @@ -15,24 +17,32 @@ dir = require "opendirectory" -- create app = require("soakbean") { bin = "./xrforge.com", + bindir = arg[-1]:gsub("xrforge.com",""), cache = {}, - opts = { - title="My XRForge experiences", - subtitle="Portable XR experiences for PhoneVR, VRheadset, desktop & mobile." - }, + opts = {}, cmd={ - help = {file="help.lua", info="displays help cmds"}, - server = {file="server.lua", info="starts the webserver"} - }, - title = 'XRForge - local-first XR experiences', - subtitle = 'XRForge makes local-first XR easy', - notes = {'ðŸĪĐ portable selfsovereign', '🖧 JanusXR / XR Fragments', 'â™ŧ decentralized'} + help = {file="cmd/help.lua", info="display all possible flags"}, + server = {file="cmd/server.lua", info="starts the webserver"} + } } +-- api skeleton (implemented via soakbean's app.on(...)) +app.set = function(k,v) end +app.init = function() end + +-- load config +app.opts = require('config')(app) + + +app.runcmd(app) -- run clicmds + +-- init URL router app.url['^/data'] = '/data.lua' -- setup custom file endpoint -app.url['^/$'] = '/index.lua' -- alias for app.tpl( LoadAsset('index.html'), app ) -app.get('^/admin/$', app.template('admin/index.html') ) -- alias for app.tpl( LoadAsset('index.html'), app ) +app.url['^/$'] = '/page/index.lua' -- alias for app.tpl( LoadAsset('index.html'), app ) +app.get('^/design[/]?$', util.pagerender('page/design.html')) + +app.url['^/admin[/]?$'] = '/page/admin/index.lua' app.post('^/save', function(req,res,next) -- setup inline POST endpoint -- also .get(), .put(), .delete(), .options() @@ -43,23 +53,22 @@ app.post('^/save', function(req,res,next) -- setup inline POST endpoint end) app -- -.use( require("httpauth")() ) +.use( require("middleware/httpauth")() ) .use( require("json").middleware() ) -- try plug'n'play json API middleware .use( app.router( app.url ) ) -- try url router .use( app.response() ) -- try serve app response (if any) .use( function(req,next) Route() end) -- fallback default redbean fileserver -app.on('template', function(a,b,c,d,e) - print("TEMPLATE!") -end) - function OnHttpRequest() app.run() end -print("ja") ---function OnHttpRequest() --- if( not dir.serve("./experiences") ) then --- print("default") --- Route() --- end ---end --- +app.on('init', function() + if assert(unix.fork()) == 0 then + os.execute("ls ; sleep 5") + print("ok") + --local ok, headers, body = Fetch('http://127.0.0.1:8080/test') + end +end) + +OnServerStart = function() + app.init() -- this triggers init event +end diff --git a/src/.lua/cmd b/src/.lua/cmd new file mode 120000 index 0000000..9287aae --- /dev/null +++ b/src/.lua/cmd @@ -0,0 +1 @@ +../cmd \ No newline at end of file diff --git a/src/.lua/config.lua b/src/.lua/config.lua new file mode 100644 index 0000000..a181fa4 --- /dev/null +++ b/src/.lua/config.lua @@ -0,0 +1,51 @@ +local util = require('util') + +return function(app) + + local config = { -- default + name = "XRForge", + baseurl="/", + title="My XRForge experiences", + subtitle="Portable XR experiences for Phone, VRheadset & desktop.", + admin_title = "XRForge Admin", + admin_subtitle = "Manage your XR experiences here", + disk_dir = ".", + manyfold_instance_1 = "https://xrforge.isvery.ninja", + manyfold_instance_2 = "", + manyfold_instance_3 = "", + sync_interval = 30, + sync_strategy = "recent" + } + + local configfile = "xrforge.lua" + local savedconfig = util.readfile( app.bindir .. configfile, 'r', true) -- check local config + or LoadAsset(configfile) -- then internal saved config + + if savedconfig then + local eval = function(str) return load(str)() end + local status, result = pcall(eval, savedconfig ) -- Pass "string" as the first argument + if not status then + print("error: xrforge.lua contains errors:") + else + config = result -- overrule default config + end + end + + app.on('set', function(k,v) + if k == 'app.opts' then + app.opts = v + app.opts.updated = os.time() + local newconfig = "app.on('init', function()\n\tprint('config loaded')\nend)\n\nreturn " .. util.dump(app.opts) + newconfig = newconfig:gsub("^}$"," init = function() print('xrforge.lua config loaded') end\n}") + util.writefile( app.bindir .. configfile, newconfig ) + print("stored xrforge.lua") + end + end) + + -- store local config if not exist + if not util.readfile( app.bindir .. configfile, 'r', true) then + app.set('app.opts', config ) + end + + return config +end diff --git a/src/.lua/middleware b/src/.lua/middleware new file mode 120000 index 0000000..e7ecd4e --- /dev/null +++ b/src/.lua/middleware @@ -0,0 +1 @@ +../middleware \ No newline at end of file diff --git a/src/.lua/soakbean.lua b/src/.lua/soakbean.lua index 6fcf244..13ff4d7 100644 --- a/src/.lua/soakbean.lua +++ b/src/.lua/soakbean.lua @@ -23,7 +23,7 @@ sb = { sb.data[k] = (function(k,v) return function(a,b,c,d,e,f) v(a,b,c,d,e,f) - sb.pub(k,v) + sb.pub(k,v,a,b,c,d,e,f) end end)(k,v) else @@ -38,10 +38,14 @@ sb = { return sb.app end, - pub = function(k,v) + pub = function(k,v,a,b,c,d,e,f) if sb.handler[k] ~= nil then for i,handler in pairs(sb.handler[k]) do - coroutine.wrap(handler)(v,k) + if a then -- + coroutine.wrap(handler)(a,b,c,d,e,f) -- forward function args + else + coroutine.wrap(handler)(v,k) -- forward assignment + end end end end, @@ -187,13 +191,12 @@ sb = { end, init = function(app) - for k,v in pairs(argv) do - app.opts[ v:gsub("=.*","") ] = v:gsub(".*=","") - end - if( keys(app.cmd) > 0 ) then sb.runcmd(app) end end, runcmd = function(app) + for k,v in pairs(argv) do + app.opts[ v:gsub("=.*","") ] = v:gsub(".*=","") + end for k,v in pairs(app.opts) do if app.cmd[k] then local file = app.cmd[k].file diff --git a/src/.lua/util.lua b/src/.lua/util.lua index 2c4f421..c3b05d4 100644 --- a/src/.lua/util.lua +++ b/src/.lua/util.lua @@ -1,5 +1,26 @@ local util = { } +util.readfile = function(filename, mode, silent) + local file, err = io.open(filename, mode or "r") + if not file then + if not silent then print("Error opening file:", err) end + return + end + local content = file:read("*a") + file:close() + return content +end + +util.writefile = function(filename, content, mode) + local file, err = io.open(filename, mode or "w") -- Default write mode + if not file then + return print("Error opening file:", err) + end + file:write(content) + file:close() +end + + util.clone = function(orig) local orig_type = type(orig) local copy @@ -28,11 +49,20 @@ util.flatten = function(tbl, prefix, result) return result end +util.pagerender = function(file,data) + return function(req,res,next) + res.status(200) + res.header('content-type','text/html; charset=utf-8') + res.body( util.template( LoadAsset(file),data or app) ) + next() + end +end + util.template = function(content,data) - local finaldata = util.merge(app,{}) + local finaldata = util.merge(data or app,{}) finaldata = util.merge(finaldata, util.flatten(app.opts,"opts") ) - finaldata.header = app.tpl( LoadAsset('template/header.html'), finaldata ) - finaldata.footer = app.tpl( LoadAsset('template/footer.html'), finaldata ) + finaldata.header = app.tpl( LoadAsset('page/header.html'), finaldata ) + finaldata.footer = app.tpl( LoadAsset('page/footer.html'), finaldata ) return app.tpl( content, finaldata ) end diff --git a/src/admin/index.html b/src/admin/index.html deleted file mode 100644 index b074aa4..0000000 --- a/src/admin/index.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - Lorem ipsum - dolor sit - - - - - - - - - -
-
- -
-
- - - - - -
-
- - - -
-

HEADER 1

- Lorem ipsum dolor sit amter.
- Amet puti solor fati corpus a link flap.

-
- -
- button -
- - - - -
-
-
- -
    -
  • foo bar
  • -
  • flop flap
  • -
- - -
-
-
-
-┌─────────────────┐┌────────────────┐
-│  Foo     CLI    ││ Foo     Web    │
-└─────────────────┘└────────────────┘
-┌───────────────────────────────────┐
-│  Foo     Repository               │
-│ ┌────────┐ ┌────────┐ ┌─────────┐ │
-│ │  code  │ │ issues │ │ patches │ │
-│ └────────┘ └────────┘ └─────────┘ │
-├───────────────────────────────────â”Ī
-│  Foo     Storage (Git)            │
-└───────────────────────────────────┘
-┌────────────────┐┌─────────────────┐
-│  Foo     Node  ││  Foo     HTTPD  │
-├────────────────â”Ī├─────────────────â”Ī
-│    NoiseXK     ││   HTTP + JSON   │
-└────────────────┘└─────────────────┘
-
-
-
-┌─────────────────┐┌────────────────┐
-│  Foo     CLI    ││ Foo     Web    │
-└─────────────────┘└────────────────┘
-┌───────────────────────────────────┐
-│  Foo     Repository               │
-│ ┌────────┐ ┌────────┐ ┌─────────┐ │
-│ │  code  │ │ issues │ │ patches │ │
-│ └────────┘ └────────┘ └─────────┘ │
-├───────────────────────────────────â”Ī
-│  Foo     Storage (Git)            │
-└───────────────────────────────────┘
-┌────────────────┐┌─────────────────┐
-│  Foo     Node  ││  Foo     HTTPD  │
-├────────────────â”Ī├─────────────────â”Ī
-│    NoiseXK     ││   HTTP + JSON   │
-└────────────────┘└─────────────────┘
-
-
-
-┌─────────────────┐┌────────────────┐
-│  Foo     CLI    ││ Foo     Web    │
-└─────────────────┘└────────────────┘
-┌───────────────────────────────────┐
-│  Foo     Repository               │
-│ ┌────────┐ ┌────────┐ ┌─────────┐ │
-│ │  code  │ │ issues │ │ patches │ │
-│ └────────┘ └────────┘ └─────────┘ │
-├───────────────────────────────────â”Ī
-│  Foo     Storage (Git)            │
-└───────────────────────────────────┘
-┌────────────────┐┌─────────────────┐
-│  Foo     Node  ││  Foo     HTTPD  │
-├────────────────â”Ī├─────────────────â”Ī
-│    NoiseXK     ││   HTTP + JSON   │
-└────────────────┘└─────────────────┘
-
-

hello world

- Lorem ipsum -
-

hello world

- Lorem ipsum -
-

hello world

- Lorem ipsum - -
-
- - - - - - - - - -
-
-
-
- - - - - - - diff --git a/src/cmd/help.lua b/src/cmd/help.lua index 27ccc19..be36d37 100644 --- a/src/cmd/help.lua +++ b/src/cmd/help.lua @@ -1,13 +1,13 @@ return function(app,argv) - print("help!") + foreach( app.cmd, function(k,v) + io.write( app.bin .. " " .. k .. "\t\t # " .. v.info .. "\n") + end) + io.write("\nexample: " .. app.bin .. " title='My XRForge experiences'\n\n") + io.write("Flags: (overrides xrforge.lua configfile)\n\n") foreach( app.opts, function(k,v) - if not k:match("/") and not k:match("^help") then - print( app.bin .. " -- " .. k .. "=...\t # '" .. v .. "' e.g." ) + if not k:match("/") and not k:match("^help") and not k:match("updated") then + io.write( " " .. k .. "='" .. v .. "'\n") end end) - foreach( app.cmd, function(k,v) - print( app.bin .. " -- " .. k .. "\t\t # " .. v.info ) - end) - os.exit() end diff --git a/src/xrforge.css b/src/css/xrforge.css similarity index 60% rename from src/xrforge.css rename to src/css/xrforge.css index 761d172..f72695a 100644 --- a/src/xrforge.css +++ b/src/css/xrforge.css @@ -8,7 +8,7 @@ .col2{ color:#AAD; } .col3{ color:#878; } .col4{ color:#7070ff; } -.col5{ color:#557; } +.col5{ color:#447; } .col5{ color:#224; } .col5{ color:#112; } @@ -40,7 +40,28 @@ td,div,p{ line-height:24px; } -.btn{ +/* form elements */ + +input, +select{ + box-sizing: border-box; + margin: 0px 0px 10px 0px; + padding:7px; + display:block; + max-width:300px; + width:100%; + background: #000; + border: 1px solid #557; + color: #AAD; +} +input[type=checkbox]{ + transform:scale(1.7) translate(3px,4px) +} + +/* buttons */ + +.btn, +input[type=submit]{ display: inline-block; margin: 0px 10px 10px 0px; } @@ -48,21 +69,28 @@ td,div,p{ .btn a, .btn a:active, .btn a:visited, -.btn a:link { +.btn a:link, +input[type=submit] { + font-size:15px; display: inline-block; padding:8px 16px; color: #f3f; text-decoration:none; } -.btn a:hover{ +.btn a:hover, +input[type=submit] { color:#F7F; background:#000; } -.btn a, .border{ border:1px dotted #AAD; } +.btn a, +.border, +input[type=submit]{ + border:1px dotted #AAD; +} -a, a:active, a:visited, a:link { +a, a:active, a:visited, a:link, input[type=submit] { text-decoration: none; color:#FFF; border-bottom: 1px dotted #AAD; @@ -74,6 +102,27 @@ a:hover{ border-bottom:1px dotted #f3f; } +table{ + table-layout: fixed; +} +table tr td { + vertical-align: top; +} +form > table > tbody > tr > td{ + height:32px; +} +form > table > tbody > tr > td:nth-child(1) { + font-weight:bold; + padding-top: 4px; +} +form > table > tbody > tr > td:nth-child(3) { + font-size: 13px; + padding-top: 4px; + text-align:right; +} + + + .border.primary{ border:1px dotted #87a; } .border.secondary{ border:1px dotted #7070ff; } @@ -123,10 +172,17 @@ ul{ padding-left:0.8em; } +.menu{ + text-align: right; +} .menu a { padding-right:30px; } +.menu br { + display:none +} + .grid .tile{ border-radius:5px; } .grid .tile .text{ padding:3px 0px; } .grid .tile .img{ @@ -136,6 +192,35 @@ ul{ img.icon{ display:none; } +/* tab */ + +.tab{ + border-bottom: 1px solid #224; + margin-bottom: 25px; + margin-left: 140px; +} +.tab .label{ + display: block; + background: #000; + margin-bottom: -4px; + width: 158px; + margin-left: -140px; + border-top: 1px dotted #557; + border-left: 1px dotted #556; + border-right: 1px dotted #556; + padding: 9px 0px 0px 20px; + +} + +.notification{ + background: #7070ff; + padding: 20px; + text-align: center; + font-weight: bold; + border: 4px dashed #222; + margin-bottom: 25px; +} + /* progressive enhancement quirks */ @media (min-width:1px) { .grid .tile{ diff --git a/src/xrforge.max.css b/src/css/xrforge.max.css similarity index 67% rename from src/xrforge.max.css rename to src/css/xrforge.max.css index b4ba568..0fcc051 100644 --- a/src/xrforge.max.css +++ b/src/css/xrforge.max.css @@ -29,6 +29,13 @@ body{ width:100%; margin: 0px 0px 15px 0px; } + form table tr > th:nth-child(3), + form table tr > td:nth-child(3) { + display:none; + } + .menu br { + display:initial !important; + } } .grid .tile .text{ @@ -44,8 +51,12 @@ body{ } .jumbotron{ - padding:20px 0px; + padding:20px 20px; background:linear-gradient(45deg,#0000,#0000,#F7F2,#0000,#07F2,#0000,#0000); + background:url(./../img/backdrop.jpg); + background-size: cover; + background-position: bottom; + background-repeat: no-repeat; } img.icon{ @@ -55,6 +66,6 @@ img.icon{ width: 17px; } -.btn a.primary{ background: #ff33Ff; color:#000 !important;} -.btn a.secondary{ background: #7070ff; color:#000 !important;} +.btn .primary{ background: #ff33Ff; color:#000 !important;} +.btn .secondary{ background: #7070ff; color:#000 !important;} diff --git a/src/img/backdrop.jpg b/src/img/backdrop.jpg new file mode 100644 index 0000000000000000000000000000000000000000..96c3e3cee85cbffca7ff49022cb61b019eb7e419 GIT binary patch literal 7858 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 +

${opts.admin_title}

+ ${opts.admin_subtitle} + +
+ +${notification} + +
+
+ Local content +
+
+ +
+
+ + + + + + + + +
+ + +
+ Directory + + + + Directory to scan for experiences (use '.' for current) +
+
+ +
+
+ +
+
+ Manyfold instances +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ Instance URL 1 + + + + Manyfold URL goes here (https://xrforge.isvery.ninja e.g.) +
+ Instance URL 2 + + + + Manyfold URL goes here (https://xrforge.isvery.ninja e.g.) +
+ Instance URL 3 + + + + Manyfold URL goes here (https://xrforge.isvery.ninja e.g.) +
+ Sync strategy + + + + Specify how manyfold instances should be synced. +
+ Sync interval + + + + Specify how often manyfold instances should be checked for recent items. +
+
+
+
+ +
+
+
+
+ +${footer} diff --git a/src/page/admin/index.lua b/src/page/admin/index.lua new file mode 100644 index 0000000..47f102d --- /dev/null +++ b/src/page/admin/index.lua @@ -0,0 +1,27 @@ +local util = require("util") + +local data = util.merge({notification=''},{ opts = app.opts }) + +if GetMethod() == 'POST' then + local params = GetParams() + local saveconfig = false + foreach(params, function(k,v) + if v[1]:match("^opts.") then + app.opts[ v[1]:gsub("^opts.","") ] = v[2] -- update + saveconfig = true + end + end) + if saveconfig then + app.set('app.opts', app.opts ) + data.notification = '
updated
' + else + data.notification = '
no changes detected
' + end +end + +local html = util.template( LoadAsset("page/admin/index.html"),data) + + +SetStatus(200) +SetHeader('Content-Type', 'text/html; charset=utf-8') +Write( html ) diff --git a/src/page/design.html b/src/page/design.html new file mode 100644 index 0000000..e288463 --- /dev/null +++ b/src/page/design.html @@ -0,0 +1,127 @@ +${header} + +

HEADER 1

+Lorem ipsum dolor sit amter.
+Amet puti solor fati corpus a link flap.

+
+ +
+ button +
+ + + + +
+
+ +
+
+ Category B +
+
+ +
+
+ + + + + + + + + + + +
+ Instance URL 1 + + + + Infotext about input +
+ Sync interval + + + + Infotext about select (tip: use selectboxes not checkboxes) +
+
+ +
    +
  • foo bar
  • +
  • flop flap
  • +
+ + +
+  
+
+
+  ┌─────────────────┐┌────────────────┐
+  │  Foo     CLI    ││ Foo     Web    │
+  └─────────────────┘└────────────────┘
+  ┌───────────────────────────────────┐
+  │  Foo     Repository               │
+  │ ┌────────┐ ┌────────┐ ┌─────────┐ │
+  │ │  code  │ │ issues │ │ patches │ │
+  │ └────────┘ └────────┘ └─────────┘ │
+  ├───────────────────────────────────â”Ī
+  │  Foo     Storage (Git)            │
+  └───────────────────────────────────┘
+  ┌────────────────┐┌─────────────────┐
+  │  Foo     Node  ││  Foo     HTTPD  │
+  ├────────────────â”Ī├─────────────────â”Ī
+  │    NoiseXK     ││   HTTP + JSON   │
+  └────────────────┘└─────────────────┘
+  
+
+
+  ┌─────────────────┐┌────────────────┐
+  │  Foo     CLI    ││ Foo     Web    │
+  └─────────────────┘└────────────────┘
+  ┌───────────────────────────────────┐
+  │  Foo     Repository               │
+  │ ┌────────┐ ┌────────┐ ┌─────────┐ │
+  │ │  code  │ │ issues │ │ patches │ │
+  │ └────────┘ └────────┘ └─────────┘ │
+  ├───────────────────────────────────â”Ī
+  │  Foo     Storage (Git)            │
+  └───────────────────────────────────┘
+  ┌────────────────┐┌─────────────────┐
+  │  Foo     Node  ││  Foo     HTTPD  │
+  ├────────────────â”Ī├─────────────────â”Ī
+  │    NoiseXK     ││   HTTP + JSON   │
+  └────────────────┘└─────────────────┘
+  
+
+
+  ┌─────────────────┐┌────────────────┐
+  │  Foo     CLI    ││ Foo     Web    │
+  └─────────────────┘└────────────────┘
+  ┌───────────────────────────────────┐
+  │  Foo     Repository               │
+  │ ┌────────┐ ┌────────┐ ┌─────────┐ │
+  │ │  code  │ │ issues │ │ patches │ │
+  │ └────────┘ └────────┘ └─────────┘ │
+  ├───────────────────────────────────â”Ī
+  │  Foo     Storage (Git)            │
+  └───────────────────────────────────┘
+  ┌────────────────┐┌─────────────────┐
+  │  Foo     Node  ││  Foo     HTTPD  │
+  ├────────────────â”Ī├─────────────────â”Ī
+  │    NoiseXK     ││   HTTP + JSON   │
+  └────────────────┘└─────────────────┘
+  
+
+ +${footer} diff --git a/src/template/footer.html b/src/page/footer.html similarity index 100% rename from src/template/footer.html rename to src/page/footer.html diff --git a/src/template/header.html b/src/page/header.html similarity index 59% rename from src/template/header.html rename to src/page/header.html index bdfbb44..58948b4 100644 --- a/src/template/header.html +++ b/src/page/header.html @@ -3,25 +3,28 @@ + + XRForge - selfsovereign interoperable XR experiences - + - diff --git a/src/template/index.html b/src/page/index.html similarity index 100% rename from src/template/index.html rename to src/page/index.html diff --git a/src/index.lua b/src/page/index.lua similarity index 82% rename from src/index.lua rename to src/page/index.lua index 868ec14..eadf79e 100644 --- a/src/index.lua +++ b/src/page/index.lua @@ -4,7 +4,7 @@ if not app.cache['index.html'] then app.cache['index.html'] = util.memoize( function() print("processing!") - local html = util.template( LoadAsset("template/index.html"),app) + local html = util.template( LoadAsset("page/index.html"),app) return html end, 60*5 -- re-run every 5 mins (otherwise return cache) diff --git a/src/run.sh b/src/run.sh deleted file mode 100755 index e7e4477..0000000 --- a/src/run.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -../result/bin/xrforge.com -D . -p 8081 -- server diff --git a/src/ui-kit.html b/src/ui-kit.html deleted file mode 100644 index f4b2892..0000000 --- a/src/ui-kit.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - Lorem ipsum - dolor sit - - - - -
+
- + +
- - - - -
-
- -
-
- - - - - -
-
- - - -
-

HEADER 1

- Lorem ipsum dolor sit amter.
- Amet puti solor fati corpus a link flap.

-
- -
- button -
- - - - -
-
- -
    -
  • foo bar
  • -
  • flop flap
  • -
- - -
-
-
-
-┌─────────────────┐┌────────────────┐
-│  Foo     CLI    ││ Foo     Web    │
-└─────────────────┘└────────────────┘
-┌───────────────────────────────────┐
-│  Foo     Repository               │
-│ ┌────────┐ ┌────────┐ ┌─────────┐ │
-│ │  code  │ │ issues │ │ patches │ │
-│ └────────┘ └────────┘ └─────────┘ │
-├───────────────────────────────────â”Ī
-│  Foo     Storage (Git)            │
-└───────────────────────────────────┘
-┌────────────────┐┌─────────────────┐
-│  Foo     Node  ││  Foo     HTTPD  │
-├────────────────â”Ī├─────────────────â”Ī
-│    NoiseXK     ││   HTTP + JSON   │
-└────────────────┘└─────────────────┘
-
-
-
-┌─────────────────┐┌────────────────┐
-│  Foo     CLI    ││ Foo     Web    │
-└─────────────────┘└────────────────┘
-┌───────────────────────────────────┐
-│  Foo     Repository               │
-│ ┌────────┐ ┌────────┐ ┌─────────┐ │
-│ │  code  │ │ issues │ │ patches │ │
-│ └────────┘ └────────┘ └─────────┘ │
-├───────────────────────────────────â”Ī
-│  Foo     Storage (Git)            │
-└───────────────────────────────────┘
-┌────────────────┐┌─────────────────┐
-│  Foo     Node  ││  Foo     HTTPD  │
-├────────────────â”Ī├─────────────────â”Ī
-│    NoiseXK     ││   HTTP + JSON   │
-└────────────────┘└─────────────────┘
-
-
-
-┌─────────────────┐┌────────────────┐
-│  Foo     CLI    ││ Foo     Web    │
-└─────────────────┘└────────────────┘
-┌───────────────────────────────────┐
-│  Foo     Repository               │
-│ ┌────────┐ ┌────────┐ ┌─────────┐ │
-│ │  code  │ │ issues │ │ patches │ │
-│ └────────┘ └────────┘ └─────────┘ │
-├───────────────────────────────────â”Ī
-│  Foo     Storage (Git)            │
-└───────────────────────────────────┘
-┌────────────────┐┌─────────────────┐
-│  Foo     Node  ││  Foo     HTTPD  │
-├────────────────â”Ī├─────────────────â”Ī
-│    NoiseXK     ││   HTTP + JSON   │
-└────────────────┘└─────────────────┘
-
-

hello world

- Lorem ipsum -
-

hello world

- Lorem ipsum -
-

hello world

- Lorem ipsum - - -
-
-
-
- - - - - - - diff --git a/src/xrforge.lua b/src/xrforge.lua new file mode 120000 index 0000000..c58510a --- /dev/null +++ b/src/xrforge.lua @@ -0,0 +1 @@ +../result/bin/xrforge.lua \ No newline at end of file diff --git a/util/xrforge.sh b/util/xrforge.sh index cdb64cf..37b7384 100755 --- a/util/xrforge.sh +++ b/util/xrforge.sh @@ -25,7 +25,7 @@ download(){ build(){ download redbean cd src - zip -r ../result/bin/xrforge.com * .lua .init.lua + zip -r ../result/bin/xrforge.com * .lua .init.lua .args } "$@"