nx_family_hub.nx source
↩ module page · 118 lines · 7832 B
1// nx_family_hub.nx -- EMIT nishifamily.com/hub, AUTO-GENERATED from the sovereign
2// app registry (nx_app_store / seg_store). No hardcoded cards, no TSV: publish an
3// app into the store and it appears here automatically, grouped by category, with
4// CAD featured. Organ-authored; published via nx_aw_push to /hub/index.html.
5// license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "nx_app_store.nx"
8const HUB_MAGIC_8192: i64 = 8192
9const HUB_MAGIC_1024: i64 = 1024
10const HUB_MAGIC_65536: i64 = 65536
11
12const HUB_OUT: *u8 = "web_assets/hub.html"
13const HUB_CAP: i64 = 131072
14
15func cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[off+i]=s[i]; i=i+1 } return off+i }
16func catn(dst: *u8, off: i64, v: i64) -> i64 {
17 var o: i64=off; var n: i64=v; if n<0 { dst[o]=45 as u8; o=o+1; n=0-n }
18 let t: *u8=sys_mmap(32); var k: i64=0; if n==0{t[0]=48 as u8;k=1}; while n>0{t[k]=(48+(n%10)) as u8;n=n/10;k=k+1}
19 var j: i64=k-1; while j>=0{dst[o]=t[j];o=o+1;j=j-1} return o
20}
21// TAB-delimited field `fi` of rec[0..rl) into out (NUL-term); returns length
22func getfield(rec: *u8, rl: i64, fi: i64, out: *u8) -> i64 {
23 var f: i64=0; var i: i64=0
24 while f<fi { if i>=rl { out[0]=0 as u8; return 0 } if rec[i]==9 as u8 { f=f+1 } i=i+1 }
25 var o: i64=0
26 while i<rl { if rec[i]==9 as u8 { i=rl } else { out[o]=rec[i]; o=o+1; i=i+1 } }
27 out[o]=0 as u8; return o
28}
29// load app <name>'s fields; returns 0 ok / -1 missing
30func app_fields(name: *u8, path: *u8, title: *u8, blurb: *u8, cate: *u8) -> i64 {
31 let po: *i64=sys_mmap(16) as *i64; let lo: *i64=sys_mmap(16) as *i64
32 if nx_app_store_get(name, po, lo) < 0 { return 0 - 1 }
33 let rec: *u8=sys_mmap(HUB_MAGIC_8192); let src: *u8=po[0] as *u8; let rl: i64=lo[0]
34 var c: i64=0; while c<rl { rec[c]=src[c]; c=c+1 }
35 getfield(rec, rl, 0, path); getfield(rec, rl, 1, title); getfield(rec, rl, 2, blurb); getfield(rec, rl, 3, cate)
36 return 0
37}
38func streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
39
40// emit one category section: every app whose category == want
41func emit_cat(h: *u8, off: i64, idx: *u8, idxn: i64, want: *u8, header: *u8) -> i64 {
42 var o: i64=off
43 o=cat(h,o,"<h2>" as *u8); o=cat(h,o,header); o=cat(h,o,"</h2><div class=\"grid\">\n" as *u8)
44 let name: *u8=sys_mmap(256); let path: *u8=sys_mmap(256); let title: *u8=sys_mmap(256)
45 let blurb: *u8=sys_mmap(HUB_MAGIC_1024); let cate: *u8=sys_mmap(64)
46 var ls: i64=0; var i: i64=0
47 while i<=idxn {
48 var eol: i64=0
49 if i==idxn { eol=1 } else { if idx[i]==10 as u8 { eol=1 } }
50 if eol==1 {
51 if i>ls {
52 var c: i64=0; while c<i-ls { name[c]=idx[ls+c]; c=c+1 } name[i-ls]=0 as u8
53 if app_fields(name, path, title, blurb, cate)==0 {
54 if streq(cate, want)==1 {
55 o=cat(h,o,"<a class=\"card\" href=\"" as *u8); o=cat(h,o,path)
56 o=cat(h,o,"\"><h3>" as *u8); o=cat(h,o,title); o=cat(h,o,"</h3><p>" as *u8)
57 o=cat(h,o,blurb); o=cat(h,o,"</p></a>\n" as *u8)
58 }
59 }
60 }
61 ls=i+1
62 }
63 i=i+1
64 }
65 o=cat(h,o,"</div>\n" as *u8)
66 return o
67}
68
69func main() -> i64 {
70 let now: i64 = sys_now_realtime_sec()
71 let h: *u8 = sys_mmap(HUB_CAP)
72 var w: i64 = 0
73 let idx: *u8 = sys_mmap(HUB_MAGIC_65536)
74 let idxn: i64 = nx_app_store_index(idx)
75
76 w = cat(h, w, "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">\n" as *u8)
77 w = cat(h, w, "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n" as *u8)
78 w = cat(h, w, "<title>Nishi Family — Hub</title>\n<style>\n" as *u8)
79 w = cat(h, w, ":root{--bg:#0b0f14;--panel:#131b24;--ink:#e6edf3;--mut:#8aa0b4;--acc:#4cc2ff;--good:#3fb950;--line:#243140}\n" as *u8)
80 w = cat(h, w, "*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.55 system-ui,Segoe UI,Roboto,sans-serif}\n" as *u8)
81 w = cat(h, w, "header{padding:38px 20px 8px;max-width:1000px;margin:0 auto;text-align:center}h1{margin:0;font-size:32px}.sub{color:var(--mut);margin:.6em 0 0}.stamp{color:var(--mut);font-size:12px;margin:.5em 0 0}\n" as *u8)
82 w = cat(h, w, "main{max-width:1000px;margin:0 auto;padding:18px 20px 60px}\n" as *u8)
83 w = cat(h, w, ".grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px;margin-top:10px}\n" as *u8)
84 w = cat(h, w, "a.card{display:block;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 18px;text-decoration:none;color:var(--ink);transition:border-color .15s,transform .15s}\n" as *u8)
85 w = cat(h, w, "a.card:hover{border-color:var(--acc);transform:translateY(-2px)}a.card h3{margin:0 0 6px;font-size:17px;color:var(--acc)}a.card p{margin:0;color:var(--mut);font-size:13.5px}\n" as *u8)
86 w = cat(h, w, "a.feat{display:block;text-decoration:none;color:var(--ink);background:linear-gradient(135deg,#10212e,#13243a);border:1px solid #2c4a63;border-radius:12px;padding:16px 18px;margin-top:10px}a.feat h3{margin:.1em 0 6px;font-size:21px;color:var(--acc)}a.feat p{margin:0;color:var(--mut)}a.feat .tagx{color:var(--good);font-size:12px;font-weight:600;letter-spacing:.4px;text-transform:uppercase}\n" as *u8)
87 w = cat(h, w, "h2{font-size:13px;color:var(--mut);text-transform:uppercase;letter-spacing:.5px;margin:26px 0 2px}\n" as *u8)
88 w = cat(h, w, "footer{max-width:1000px;margin:0 auto;padding:8px 20px 40px;color:var(--mut);font-size:12px;text-align:center}\n" as *u8)
89 w = cat(h, w, "</style></head><body>\n" as *u8)
90
91 w = cat(h, w, "<header><h1>Nishi Family — Hub</h1>\n" as *u8)
92 w = cat(h, w, "<p class=\"sub\">Home of the Nishi sovereign ecosystem — every app below is built from the hardware rung up, served bits-up over our own TLS 1.3.</p>\n" as *u8)
93 w = cat(h, w, "<p class=\"stamp\">Auto-generated by <code>nx_family_hub</code> from the sovereign app registry (<code>nx_app_store</code> on seg_store) at epoch " as *u8)
94 w = catn(h, w, now)
95 w = cat(h, w, "</p></header>\n<main>\n" as *u8)
96
97 // featured: CAD (read from the store)
98 let fpath: *u8=sys_mmap(256); let ftitle: *u8=sys_mmap(256); let fblurb: *u8=sys_mmap(HUB_MAGIC_1024); let fcate: *u8=sys_mmap(64)
99 if app_fields("cad" as *u8, fpath, ftitle, fblurb, fcate)==0 {
100 w=cat(h,w,"<a class=\"feat\" href=\"" as *u8); w=cat(h,w,fpath); w=cat(h,w,"\"><div class=\"tagx\">★ Featured</div><h3>" as *u8)
101 w=cat(h,w,ftitle); w=cat(h,w," →</h3><p>" as *u8); w=cat(h,w,fblurb); w=cat(h,w,"</p></a>\n" as *u8)
102 }
103
104 w = emit_cat(h, w, idx, idxn, "make" as *u8, "Make & build" as *u8)
105 w = emit_cat(h, w, idx, idxn, "play" as *u8, "Play" as *u8)
106 w = emit_cat(h, w, idx, idxn, "home" as *u8, "Home & family" as *u8)
107
108 w = cat(h, w, "</main>\n<footer>Served bits-up by the Nishi stack · TLS 1.3, no third-party web server · registry: <code>nx_app_store</code> (seg_store) · hub: <code>nx_family_hub</code> · nishifamily.com/hub</footer>\n</body></html>\n" as *u8)
109
110 let fd: i64 = sys_openat_wr(HUB_OUT, 0x1a4)
111 if fd < 0 { sys_write(2, "FATAL: hub.html open\n" as *u8, 21); sys_exit(2); return 2 }
112 sys_write(fd, h, w); sys_close(fd)
113 sys_write(1, "[nx_family_hub] hub.html auto-generated from registry, bytes=" as *u8, 60)
114 let nb: *u8 = sys_mmap(28); var k2: i64=0; var m2: i64=w; if m2==0{nb[0]=48 as u8;k2=1}; while m2>0{nb[k2]=(48+(m2%10)) as u8;m2=m2/10;k2=k2+1}
115 var qd: i64=k2-1; while qd>=0 { let o1: *u8=sys_mmap(1); o1[0]=nb[qd]; sys_write(1,o1,1); qd=qd-1 }
116 sys_write(1, "\n" as *u8, 1)
117 sys_exit(0); return 0
118}