Compare commits

...

67 commits

Author SHA1 Message Date
7b78a1c0f6 broken pngs? 2024-11-03 15:58:39 -05:00
058e586042 broken pngs? 2024-11-03 15:56:32 -05:00
b530b6a9af untrack webms 2024-11-03 04:48:02 -05:00
8b5e6931df ignore webms 2024-11-03 04:46:33 -05:00
8564f1bd81 rm all webms 2024-11-03 04:38:59 -05:00
c0fc7ce758 remove broken webms 2024-11-03 04:34:46 -05:00
6af93824aa rm broken webm 2024-11-03 04:31:54 -05:00
d4363e2758 specific game, move or project page templates 2024-11-03 02:57:15 -05:00
92ea838dce games, moves, projects collection pages 2024-11-03 02:56:54 -05:00
e3c0fa72d1 about brand x people page 2024-11-03 02:56:08 -05:00
34e029cbb0 moves, games, projects carousels 2024-11-03 02:55:19 -05:00
43b2cb6c71 highlight header overlay 2024-11-03 02:54:21 -05:00
01b39a1bc1 top img 2024-11-03 02:50:36 -05:00
6a9ec3b6e5 move mono template 2024-11-03 02:50:01 -05:00
00c3e7f677 integrate braille page template 2024-11-03 02:48:59 -05:00
4a5f23da84 route pages 2024-11-03 02:46:55 -05:00
c40f003590 spatial computing page 2024-11-03 02:46:20 -05:00
73a37bcffe drop deprecated explicit page path 2024-11-03 02:45:45 -05:00
37a432d621 about page handler with peer project data 2024-11-03 02:45:14 -05:00
9491eb0586 navigation client side js with helper functions 2024-11-03 02:43:53 -05:00
ca8ba91bde pull in moves, games and project data for template 2024-11-03 02:42:43 -05:00
d716bcf70e projects package with data and page handlers for one and all 2024-11-03 02:41:25 -05:00
c04cbc2a24 moves package with data and page handlers for one and all 2024-11-03 02:41:09 -05:00
e5afc16a04 games package with data and page handlers for one and all 2024-11-03 02:40:59 -05:00
6d09f217e3 daemonxr icon 2024-11-03 02:33:33 -05:00
038bfc4400 pfp placeholder 2024-11-03 02:33:17 -05:00
dcd89fe3ab art 2024-11-03 02:31:15 -05:00
480978dacc footer snippet 2024-11-03 02:30:33 -05:00
2007a27303 title_desc snippet 2024-11-03 02:30:25 -05:00
1dba0bb1d0 main main 2024-11-03 02:28:22 -05:00
2b79ea73a3 side nav 2024-11-03 02:28:14 -05:00
7134d18c9e navbar 2024-11-03 02:27:31 -05:00
62b4aa17e0 canonical link 2024-11-03 02:14:02 -05:00
fc9d86a67a include mono js 2024-11-03 02:13:36 -05:00
c29a70b34b shortcut icon 2024-11-03 02:13:17 -05:00
8cb0eeba28 seo tags 2024-11-03 02:13:05 -05:00
0b33c0d947 details 2024-11-03 02:12:44 -05:00
28d7648c50 pass page path automatically to header 2024-11-03 02:10:46 -05:00
3c182fc1df handle nested templates 2024-11-03 02:06:07 -05:00
dc7cc9e7dc simplify server 2024-11-03 02:05:15 -05:00
f702890d6b core head template 2024-11-03 01:59:29 -05:00
889955adbc consolidate the biz 2024-11-03 01:54:29 -05:00
bbfde69bab disabled class 2024-11-03 01:47:36 -05:00
a43f93b343 boilerplate 2024-11-03 01:46:44 -05:00
dcaa7f2b8a inheritance 2024-11-03 01:46:21 -05:00
b69b2d6b57 headers 2024-11-03 01:45:59 -05:00
7b11b92ae2 top img 2024-11-03 01:45:45 -05:00
78cb787323 mainest main 2024-11-03 01:45:37 -05:00
e5f2080e4d side bar 2024-11-03 01:44:10 -05:00
f27164c111 top nav 2024-11-03 01:43:33 -05:00
1a793b7440 hide revealed tags and set page up 2024-11-03 01:43:09 -05:00
bc01a6b5a6 subtle placeholders 2024-11-03 01:42:00 -05:00
0b6bb58195 custom scrollbar 2024-11-03 01:40:38 -05:00
4824d9d104 default font 2024-11-03 01:40:12 -05:00
42fd23ee39 unset all 2024-11-03 01:39:48 -05:00
8b0e08306d root color vars 2024-11-03 01:39:32 -05:00
2a5ba61bb5 font faces 2024-11-03 01:39:20 -05:00
95603d106c custom vector icons 2024-11-03 01:38:36 -05:00
3861812c63 use media kit instead 2024-11-03 01:35:38 -05:00
55f12c69a2 old game videos 2024-11-03 01:32:55 -05:00
a3f324846c placeholder videos 2024-11-03 01:32:43 -05:00
4de34dede0 todo snake leaderboard 2024-11-03 01:30:28 -05:00
092ef934cc update shell cmds 2024-11-03 01:30:17 -05:00
23630205d3 no_sync.txt for rsync 2024-11-03 01:29:07 -05:00
c328185abc module dofdev 2024-11-03 01:28:26 -05:00
4cd2ef7f71 ignore tmp and fonts folders 2024-11-03 01:25:57 -05:00
daeaa7fe0e vid 2024-03-07 23:57:46 -05:00
48 changed files with 1602 additions and 340 deletions

1
.gitattributes vendored
View file

@ -3,4 +3,3 @@
*.webp filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.webm filter=lfs diff=lfs merge=lfs -text

6
.gitignore vendored
View file

@ -1,3 +1,9 @@
dofdev
tmp/
*.json
web/public/fonts/
*.webm

6
go.mod
View file

@ -1,5 +1,5 @@
module github.com/spatialfree/dofdev
module dofdev
go 1.20
go 1.23.2
require github.com/gorilla/mux v1.8.1 // indirect
require github.com/gorilla/mux v1.8.1

10
no_sync.txt Normal file
View file

@ -0,0 +1,10 @@
.git
.env
.gitignore
go.mod
go.sum
/tmp
data/*.json

View file

@ -1,11 +1,23 @@
```shell
# build and run
go build && ./dofdev
# develop
air
# deploy
rsync -avz --progress ~/go/src/dofdev/ root@dofdev:/root/dofdev/
# server starting at: http://localhost:3210
go build
rsync -avz --exclude-from='no_sync.txt' --progress ~/go/src/dofdev/ root@dofdev:/root/dofdev/
# misc
# track lfs
git lfs track "*.psd"
git lfs track "*.svg"
```
todo:
snake leaderboard
POST store and GET snake{ []XYZi, len#, initials"" }
to keep data costs low as possible:
just store and share top 10
+buffer incase of removing cheater
and just store local top 10 highscores locally
page on spatial cursors

View file

@ -5,8 +5,8 @@ import (
"log"
"net/http"
"github.com/spatialfree/dofdev/src/router"
"github.com/spatialfree/dofdev/tem"
"dofdev/src/router"
"dofdev/tem"
)
func init() {
@ -18,44 +18,9 @@ func main() {
r := router.New()
// Start the web server
log.Println("server starting on port 3210...")
addr := ":3210"
// addr := "192.168.0.21:3000"
addr := ":3232"
log.Println("server starting on port" + addr)
if err := http.ListenAndServe(addr, r); err != nil {
log.Fatalf("error starting server: %v", err)
}
// fs := http.FileServer(http.Dir("./res"))
// http.Handle("/res/", http.StripPrefix("/res/", fs))
// http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// fmt.Println("request: ", r.URL.Path)
// http.ServeFile(w, r, "./index.html")
// })
// http.HandleFunc("/pass", func(w http.ResponseWriter, r *http.Request) {
// fmt.Println("request: ", r.URL.Path)
// // fmt.Println("request: ", r.Header)
// fmt.Println("request: ", r.FormValue("pass"))
// fmt.Println("request: ", hash(r.FormValue("pass")))
// if hash(r.FormValue("pass")) == 3556498 {
// http.ServeFile(w, r, "./biz.html")
// } else {
// http.Error(w, "Forbidden", http.StatusForbidden)
// }
// })
// fmt.Println("server starting @ http://localhost:3210 ...")
// if err := http.ListenAndServe(":3210", nil); err != nil {
// panic(err)
// }
}
// hash function
func hash(s string) uint32 {
h := uint32(0)
for i := 0; i < len(s); i++ {
h = 31*h + uint32(s[i])
}
return h
}

View file

@ -3,10 +3,15 @@ package router
import (
"net/http"
"dofdev/web/pages/about"
braillexr "dofdev/web/pages/braille_xr"
"dofdev/web/pages/games"
"dofdev/web/pages/mono"
"dofdev/web/pages/moves"
"dofdev/web/pages/projects"
"dofdev/web/pages/sc"
"github.com/gorilla/mux"
braillexr "github.com/spatialfree/dofdev/web/pages/braille_xr"
"github.com/spatialfree/dofdev/web/pages/mono"
"github.com/spatialfree/dofdev/tem"
)
func New() *mux.Router {
@ -14,12 +19,22 @@ func New() *mux.Router {
r.PathPrefix(("/public/")).Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("web/public/"))))
r.HandleFunc("/", mono.Handler)
r.HandleFunc("/about", about.Handler)
r.HandleFunc("/moves", moves.Handler)
r.HandleFunc("/move/{hash}", moves.MoveHandler)
r.HandleFunc("/games", games.Handler)
r.HandleFunc("/game/{hash}", games.GameHandler)
r.HandleFunc("/projects", projects.Handler)
r.HandleFunc("/project/{hash}", projects.ProjectHandler)
r.HandleFunc("/sc", sc.Handler)
r.HandleFunc("/braille_xr", braillexr.Handler)
r.HandleFunc("/reload", func(w http.ResponseWriter, r *http.Request) {
tem.Load()
// route them back to where they came from
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusFound)
})
// r.HandleFunc("/reload", func(w http.ResponseWriter, r *http.Request) {
// tem.Load()
// // route them back to where they came from
// http.Redirect(w, r, r.Header.Get("Referer"), http.StatusFound)
// })
return r
}

View file

@ -1,49 +0,0 @@
<h2>shared accounts:</h2>
<!-- there might be sections for personal accounts later ~ -->
<div id='accounts'></div>
<script>
accounts = []
el = document.getElementById('accounts')
for (i = 0; i < accounts.length; i++) {
a = accounts[i]
el.innerHTML += `<div class='account ${(a.dead ? 'dead' : '')}'>
<div>
<b>${a.name}</b>
<a href='${a.link}'>&RightArrow;</a>
</div>
<div>${a.user}</div>
<div class='pass'>
<div onclick='
this.innerHTML="&checkmark;&nbsp;";
navigator.clipboard.writeText("${a.pass}")
'>&boxbox;&nbsp;</div>
<div onclick='
this.innerHTML === "${a.pass}" ?
window.getSelection().selectAllChildren(this) :
this.innerHTML = "${a.pass}"
'>${'*'.repeat(a.pass.length)}</div>
</div>
</div>`
}
</script>
<style>
.account {
margin-bottom: 32px;
}
.dead {
opacity: 0.666;
}
.pass {
cursor: pointer;
display: flex;
font-family: 'Courier Prime', monospace;
}
a {
text-decoration: none;
}
</style>

140
tem/html/core/head.html Normal file
View file

@ -0,0 +1,140 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<meta name="language" content="English">
<title>{{ .Title }}</title>
<meta name="description" content="{{ .Desc }}">
<meta name="og:image" content="/public/img/knuckles_owo.png">
<link rel="shortcut icon" href="https://media.dof.dev/kit/logo.svg" type="image/svg+xml">
<link rel="stylesheet" href="/public/style.css?v4">
<script src="/public/js/mono.js?v1"></script>
<link rel="canonical" href="https://{{ .Host }}{{ .PagePath }}">
</head>
<body>
<!-- nav -->
<div id="nav">
<div style="display: flex; gap: 12px;">
<div
id="nav_side"
style="
display: flex;
gap: 12px;
width: auto;
"
>
<a href="javascript:toggle_side()">
<img src="/public/img/icons/menu.svg?v1" height="32" width="auto" />
</a>
<a href="/about" style="display: flex; align-items: center; gap: 6px; text-decoration: none;">
<img src="https://media.dof.dev/kit/logo.svg?v1" height="32" width="auto" style="border-radius: 16px;" />
<div
style="
color: #fff;
font-weight: bold;
font-size: 16px;
"
>
dofdev&nbsp;
</div>
</a>
</div>
<div
style="
display: flex;
align-items: center;
gap: 12px;
background-color: #11111166;
color: var(--col-10);
font-size: 12px;
padding: 0 12px;
border-radius: 16px;
"
>
<a href="/">
<img src="/public/img/icons/search.svg?v1" height="16" width="auto" />
</a>
<input id="search" maxlength="24" placeholder="search" />
</div>
</div>
<div id="nav_border"></div>
<div class="disabled" style="display: flex; gap: 12px;">
<a href="/settings">
<img src="/public/img/icons/settings.svg?v2" height="32" width="auto" />
</a>
<a href="/profile">
<img src="/public/img/profile-pic.png?v1" height="32" width="auto" style="border-radius: 16px;" />
</a>
</div>
</div>
<div id="side">
<div
style="
display: flex;
flex-flow: column;
gap: 6px;
"
>
<a href="/" class="onpage">
<img src="/public/img/icons/home.svg?v1" height="32" width="auto" />
<div>home</div>
</a>
<a href="/moves">
<img src="/public/img/icons/dofs.svg?v1" height="32" width="auto" />
<div>moves</div>
</a>
<a href="/games">
<img src="/public/img/icons/games.svg?v1" height="32" width="auto" />
<div>games</div>
</a>
<a href="/projects">
<img src="/public/img/icons/projects.svg?v1" height="32" width="auto" />
<div>projects</div>
</a>
</div>
<div>
<div
style="
height: 2px;
width: 75%;
margin: 6px auto;
background: var(--col-06);
"
></div>
<a href="https://discord.com/invite/v9UF3TsX?utm_source=Discord%20Widget&amp;utm_medium=Connect">
<img src="/public/img/icons/discord.svg?v1" height="32" width="auto" />
<div>discord</div>
</a>
</div>
<div style="flex: 1;"></div>
<div id="support">
<a href="https://www.patreon.com/bePatron?u=31202689">
<img width="48px" src="/public/img/icons/patreon.svg?v29" style="border-radius: 24px;">
</a>
<a href="https://dofdev-shop.fourthwall.com">
<img width="48px" src="/public/img/icons/merch.svg?v29" style="border-radius: 24px;">
</a>
<a href="https://ko-fi.com/dofdev">
<img width="48px" src="/public/img/icons/kofi.svg?v29" style="border-radius: 24px;">
</a>
</div>
<div id="foot">
{{ template "footer.html" }}
</div>
</div>
<div id="side_border"></div>
<main id="main">

View file

@ -1,18 +0,0 @@
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<script src='https://unpkg.com/htmx.org@1.9.5'></script>
<link rel="stylesheet" href="/public/style.css?v19">
</head>
<body>
<a style='
position: fixed;
top: 10px;
left: 10px;
width: 32px;
height: 32px;
background-color: #000;
opacity: 0.02;
' href='/reload'></a>

View file

@ -1,99 +0,0 @@
{{ template "head.html" .}}
<main>
<p style='
width: 100%;
padding-right: 20px;
font-size: 18px;
line-height: 2.0;
text-align: right;
color: white;
'>
An effort to open higher degrees of<br>
spatial interaction free<br>
to the world.
</p>
<img src='/public/img/dofdev_logo.svg?v22' width='100%'>
<p>degrees of freedom development</p>
<div class='shuffle' style='
display: flex;
flex-flow: column;
align-items: center;
'>
<div style='color: white; font-size: 20px;'>Ethan Merchant
<a href='https://ethanmerchant.com' style='color: var(--light);'>@spatialfree</a>
</div>
<div style='color: white; font-size: 20px;'>Niko Ryan
<a href='https://twitter.com/opendegree' style='color: var(--light);'>@opendegree</a>
</div>
</div>
<div class='t_symbol' style='
font-size: 32px;
'>&times;</div>
<div id='x'>
<a href='https://stereokit.net' target='_blank'>
<div style='
background-image: url("https://stereokit.net/img/StereoKitLogoLight.svg");
'></div>
</a>
<a href='https://www.projectnorthstar.org/' target='_blank'>
<div style='
background-image: url("/public/img/icons/northstar.svg");
'></div>
</a>
<a href='https://stardustxr.org' target='_blank'>
<div style='
background-image: url("https://stardustxr.org/img/icon.gif");
'></div>
</a>
</div>
<div class='t_symbol' style='
margin-top: 4rem;
'>&conint;</div>
<!-- <div style='height: 32px;'></div> -->
<!-- <div id='fdeg'>&plus;</div> -->
<h1>projects</h1>
<p class='subtitle'>xr based interfaces</p>
<a href='/braille_xr'>braille_xr</a>
<div style='height: 32px;'></div>
<img src='/public/img/logo.svg' width='64px'>
<div style='height: 24px;'></div>
<input type='password' autofocus
name='pass' placeholder='pass'
hx-post='/pass'
hx-vals='{"pass": this.value}'
hx-swap='outerHTML'
>
<!-- <button hx-post='/clicked' hx-swap='outerHTML'>
Click Me
</button> -->
<footer>&copy; 2018-2024 dofdev</footer>
<style>
#x {
display: flex;
flex-flow: wrap;
justify-content: center;
gap: 32px;
> a > div {
min-width: 64px;
min-height: 64px;
background-size: contain;
}
}
</style>

200
tem/html/pages/about.html Normal file
View file

@ -0,0 +1,200 @@
{{ template "head.html" .}}
<div style="height: 64px; width: 100%;"></div>
<p style='
line-height: 1.75;
color: white;
font-style: italic;
text-align: center;
'>
An effort to open higher degrees of<br>
spatial interaction free<br>
to the world.
</p>
<div style="height: 12px; width: 100%;"></div>
<img src='https://media.dof.dev/kit/logotype.svg?v22' width='256'>
<p>degrees of freedom development</p>
<div style="height: 12px; width: 100%;"></div>
<div class='shuffle' style='
display: flex;
flex-flow: column;
align-items: center;
'>
<div style='color: white; font-size: 18px;'>
Ethan Merchant <span style="color: var(--col-01); font-size: 14px;">@spatialfree</span>
<a
href='https://ethanmerchant.com'
target="_blank"
style="text-decoration: none;"
>
🔗
</a>
</div>
<div style='color: white; font-size: 18px;'>
Niko Ryan <span style="color: var(--col-01); font-size: 14px;">@opendegree</span>
<a
href='https://nikoryan.com'
target="_blank"
style="text-decoration: none;"
>
🔗
</a>
</div>
</div>
<div style='
color: var(--col-06);
font-size: 48px;
padding: 12px;
'>&times;</div>
<div id='x'>
{{ range .Data.Peers }}
<a
href='{{ .Project.Url }}'
title='{{ .Project.Name }}'
target='_blank'
>
<div style='
background-image: url("{{ .Project.Icon }}");
'></div>
</a>
{{ end }}
</div>
<div style="flex: 1;"></div>
<div style="display: block; position: relative; width: auto;">
<div style="display: block; position: relative;">
<img src="/public/img/knuckles_owo-removebg.png?v29" loading="lazy" height="360px" style="margin-right: 0;">
<div class="scene">
<div class="cube">
<img class="degree" src="/public/img/icons/degree.svg?v29">
<div class="cube__face cube__face--front">
<div class="edge" style="position: absolute; left: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(000, 000, 255, 1), rgba(000, 255, 255, 1));"></div>
<div class="edge" style="position: absolute; top: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 255, 255, 1), rgba(255, 255, 255, 1));"></div>
<div class="edge" style="position: absolute; bottom: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 000, 255, 1), rgba(255, 000, 255, 1));"></div>
<div class="edge" style="position: absolute; right: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(255, 000, 255, 1), rgba(255, 255, 255, 1));"></div>
</div>
<div class="cube__face cube__face--back">
<div class="edge" style="position: absolute; left: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(255, 000, 000, 1), rgba(255, 255, 000, 1));"></div>
<div class="edge" style="position: absolute; top: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(255, 255, 000, 1), rgba(000, 255, 000, 1));"></div>
<div class="edge" style="position: absolute; bottom: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(255, 000, 000, 1), rgba(000, 000, 000, 1));"></div>
<div class="edge" style="position: absolute; right: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(000, 000, 000, 1), rgba(000, 255, 000, 1));"></div>
</div>
<div class="cube__face cube__face--right">
<div class="edge" style="position: absolute; left: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(255, 000, 255, 1), rgba(255, 255, 255, 1));"></div>
<div class="edge" style="position: absolute; top: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(255, 255, 255, 1), rgba(255, 255, 000, 1));"></div>
<div class="edge" style="position: absolute; bottom: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(255, 000, 255, 1), rgba(255, 000, 000, 1));"></div>
<div class="edge" style="position: absolute; right: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(255, 000, 000, 1), rgba(255, 255, 000, 1));"></div>
</div>
<div class="cube__face cube__face--left">
<div class="edge" style="position: absolute; left: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(000, 000, 000, 1), rgba(000, 255, 000, 1));"></div>
<div class="edge" style="position: absolute; top: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 255, 000, 1), rgba(000, 255, 255, 1));"></div>
<div class="edge" style="position: absolute; bottom: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 000, 000, 1), rgba(000, 000, 255, 1));"></div>
<div class="edge" style="position: absolute; right: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(000, 000, 255, 1), rgba(000, 255, 255, 1));"></div>
</div>
<div class="cube__face cube__face--top">
<div class="edge" style="position: absolute; left: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(000, 255, 255, 1), rgba(000, 255, 000, 1));"></div>
<div class="edge" style="position: absolute; top: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 255, 000, 1), rgba(255, 255, 000, 1));"></div>
<div class="edge" style="position: absolute; bottom: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 255, 255, 1), rgba(255, 255, 255, 1));"></div>
<div class="edge" style="position: absolute; right: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(255, 255, 255, 1), rgba(255, 255, 000, 1));"></div>
</div>
<div class="cube__face cube__face--bottom">
<div class="edge" style="position: absolute; left: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(000, 000, 000, 1), rgba(000, 000, 255, 1));"></div>
<div class="edge" style="position: absolute; top: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 000, 255, 1), rgba(255, 000, 255, 1));"></div>
<div class="edge" style="position: absolute; bottom: -1px; left: -1px; right: -1px; height: 2px; background: linear-gradient(90deg, rgba(000, 000, 000, 1), rgba(255, 000, 000, 1));"></div>
<div class="edge" style="position: absolute; right: -1px; width: 2px; top: -1px; bottom: -1px; background: linear-gradient(00deg, rgba(255, 000, 000, 1), rgba(255, 000, 255, 1));"></div>
</div>
</div>
</div>
</div>
<div style="display: block; position: absolute; bottom: 0; right: 0; padding: 10px;">
<a href="https://twitter.com/luciherzig" style="color: rgb(170 175 255);">@luciherzig</a>
</div>
</div>
<style>
#x {
display: flex;
flex-flow: wrap;
justify-content: center;
gap: 32px;
> a > div {
width: 64px;
height: 64px;
background-size: contain;
border-radius: 50%;
}
}
.scene {
position: absolute;
bottom: 184px;
right: 206px;
width: 32px;
height: 32px;
perspective: 120px;
perspective-origin: 32px 16px;
transform-style: preserve-3d;
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.666));
}
.degree {
position: absolute;
width: 32px;
height: 32px;
animation: unspin 6s linear infinite;
}
@keyframes unspin {
0% { transform: rotateY(460deg); }
50% { transform: rotateY(280deg); }
100% { transform: rotateY(100deg); }
}
.cube {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
/* transform: translateZ(-20px); */
animation: spin 6s linear infinite;
}
@keyframes spin {
0% { transform: translateY(0px) rotateY( 80deg); }
50% { transform: translateY(5px) rotateY(260deg); }
100% { transform: translateY(0px) rotateY(440deg); }
}
.cube__face {
position: absolute;
width: 32px;
height: 32px;
/* background: rgba(204, 204, 204, 0.5); */
}
.edge {
border-radius: 3px;
}
.cube__face--front {
transform: rotateY(0deg) translateZ(16px);
}
.cube__face--right {
transform: rotateY(90deg) translateZ(16px);
}
.cube__face--back {
transform: rotateY(180deg) translateZ(16px);
}
.cube__face--left {
transform: rotateY(-90deg) translateZ(16px);
}
.cube__face--top {
transform: rotateX(90deg) translateZ(16px);
}
.cube__face--bottom {
transform: rotateX(-90deg) translateZ(16px);
}
</style>

View file

@ -1,11 +1,39 @@
{{ template "head.html" .}}
<main>
<div id="top_img">
<video src='/public/braille_xr.webm' autoplay loop muted
style="
width: 100%;
height: 100%;
object-fit: cover;
object-position: bottom;
"
>
</video>
<div
style="
position: absolute;
top: 66.66%; left: 0; right: 0; bottom: 0;
background: linear-gradient(in oklab to top, #FFFFFFFF, #FFFFFF00);
mix-blend-mode: color;
"
></div>
</div>
<h1>braille_xr</h1>
<video src='/public/braille_xr.webm' width='100%' autoplay loop muted></video>
<!-- <div style="height: calc(44px + 12px);"></div> -->
<div style='height: 64px; display: block; width: 100%;'></div>
<div
style="
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
"
>
{{ template "title_desc.html" .}}
</div>
<!-- <div style='height: 1024px;'></div> -->
<h2>problem</h2>
<ul>
@ -17,7 +45,7 @@
</ul>
<img src='/public/img/brailliant_bi_40x.webp' width='60%'>
<div style='height: 64px; display: block; width: 100%;'></div>
<div style='height: 64px;'></div>
<h2>progress</h2>
<p style='margin-top: 0;'>code, hardware, software and project files: <a href='https://git.dof.dev/dofdev/braille_xr'>git repo</a></p>
@ -29,11 +57,9 @@
</ul>
<img src='/public/img/hack.webp' width='60%'>
<div style='height: 64px; display: block; width: 100%;'></div>
<div style='height: 64px;'></div>
<h2>support</h2>
<p style='margin-top: 0;'>have some resources or experience to throw our way?<br>contact us on our discord server: <a href=''>invite/quick link</a></p>
<div style='height: 128px; display: block; width: 100%;'></div>
</main>
<div style='height: 128px;'>&nbsp;</div>

66
tem/html/pages/game.html Normal file
View file

@ -0,0 +1,66 @@
{{ template "head.html" .}}
<div id="top_img">
<!-- <div
style="
background-image: url(/public/img/hack.jpg);
background-position: bottom;
background-size: cover;
height: 100vh;
position: relative;
"
></div> -->
<video src='/public/games/{{ .Data.Hash }}.webm' autoplay loop muted
style="
width: 100%;
height: 100%;
object-fit: cover;
object-position: bottom;
"
>
</video>
<div
style="
position: absolute;
top: 66.66%; left: 0; right: 0; bottom: 0;
background: linear-gradient(in oklab to top, #FFFFFFFF, #FFFFFF00);
mix-blend-mode: color;
"
></div>
</div>
<div
style="
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-flow: column;
"
>
<h1 style='width: 100%; word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
<p>
{{ .Desc }}
</p>
</h1>
<!-- {{ template "title_desc.html" .}} -->
<!-- <img src='https://media.dof.dev/kit/logotype.svg?v22' width='66.6%'>
<div
style="
color: var(--col-01);
background-color: #ffffff80;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
padding: 6px 12px;
border-radius: 24px;
margin-top: -32px;
"
>degrees of freedom development</div> -->
</div>
<h2>notes</h2>
<pre>{{ .Data.Game.Notes }}</pre>
<div style='height: 44px; width: 100%;'></div>

27
tem/html/pages/games.html Normal file
View file

@ -0,0 +1,27 @@
{{ template "head.html" .}}
<div style='height: 44px; width: 100%;'></div>
<div
style="
display: flex;
align-items: baseline;
width: 100%;
justify-content: left;
padding-left: 12px;
"
>
<h1 style='word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
</h1>
<p>{{ .Desc }}</p>
</div>
{{ range $hash, $game := .Data.Games }}
<div>
<a href="/game/{{ $hash }}">
<h2>{{ $game.Name }}</h2>
</a>
</div>
{{ end }}

162
tem/html/pages/mono.html Normal file
View file

@ -0,0 +1,162 @@
{{ template "head.html" .}}
<div id="top_img">
<!-- <div
style="
background-image: url(/public/img/hack.jpg);
background-position: bottom;
background-size: cover;
height: 100vh;
position: relative;
"
></div> -->
<video src='/public/games/{{ .Data.TopHash }}.webm' autoplay loop muted
style="
width: 100%;
height: 100%;
object-fit: cover;
object-position: bottom;
"
>
</video>
<div
style="
position: absolute;
top: 66.66%; left: 0; right: 0; bottom: 0;
background: linear-gradient(in oklab to top, #FFFFFFFF, #FFFFFF00);
mix-blend-mode: color;
"
></div>
</div>
<!-- space below nav -->
<!-- <div style="height: calc(44px + 12px);"></div> -->
<div
style="
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-flow: column;
"
>
{{ $top_thing := index .Data.Games .Data.TopHash }}
<h1 style='width: 100%; word-wrap: break-word; hyphens: auto;'>
{{ $top_thing.Name }}
<p>
{{ $top_thing.Desc }}
<br><br>
<a href="/game/{{ .Data.TopHash }}">see more</a>
</p>
</h1>
<!-- {{ template "title_desc.html" .}} -->
<!-- <img src='https://media.dof.dev/kit/logotype.svg?v22' width='66.6%'>
<div
style="
color: var(--col-01);
background-color: #ffffff80;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
padding: 6px 12px;
border-radius: 24px;
margin-top: -32px;
"
>degrees of freedom development</div> -->
</div>
<h2>moves</h2>
<div
style="
width: 100%;
display: flex;
gap: 6px;
overflow-x: auto;
"
>
{{ range $hash, $move := .Data.Moves }}
<div
style="
width: 400px;
background-color: #00000080;
"
>
<div>
<video autoplay muted
style="
width: 100%;
height: 100%;
object-fit: cover;
padding: 0;
margin: 0;
"
>
<source src="/public/moves/{{ $hash }}.webm" type="video/webm" />
</video>
</div>
<div>{{ $move.Name }}</div>
<a href="/move/{{ $hash }}">see more</a>
</div>
{{ end }}
</div>
<h2>games</h2>
<div
style="
width: 100%;
display: flex;
gap: 6px;
overflow-x: auto;
"
>
{{ range $hash, $game := .Data.Games }}
<div
style="
width: 400px;
background-color: #00000080;
"
>
<div>
<video autoplay muted
style="
width: 100%;
height: 100%;
object-fit: cover;
padding: 0;
margin: 0;
"
>
<source src="/public/games/{{ $hash }}.webm" type="video/webm" />
</video>
</div>
<div>{{ $game.Name }}</div>
<a href="/game/{{ $hash }}">see more</a>
</div>
{{ end }}
</div>
<h2>projects</h2>
<div
style="
width: 100%;
display: flex;
gap: 6px;
overflow-x: auto;
"
>
{{ range $hash, $project := .Data.Projects }}
<div
style="
width: 400px;
background-color: #00000080;
"
>
<div>{{ $project.Name }}</div>
<a href="/project/{{ $hash }}">see more</a>
</div>
{{ end }}
</div>
<div style='height: 128px; width: 100%;'></div>

64
tem/html/pages/move.html Normal file
View file

@ -0,0 +1,64 @@
{{ template "head.html" .}}
<div id="top_img">
<!-- <div
style="
background-image: url(/public/img/hack.jpg);
background-position: bottom;
background-size: cover;
height: 100vh;
position: relative;
"
></div> -->
<video src='/public/moves/{{ .Data.Hash }}.webm' autoplay loop muted
style="
width: 100%;
height: 100%;
object-fit: cover;
object-position: bottom;
"
>
</video>
<div
style="
position: absolute;
top: 66.66%; left: 0; right: 0; bottom: 0;
background: linear-gradient(in oklab to top, #FFFFFFFF, #FFFFFF00);
mix-blend-mode: color;
"
></div>
</div>
<div
style="
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-flow: column;
"
>
<h1 style='width: 100%; word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
<p>
{{ .Desc }}
</p>
</h1>
<!-- {{ template "title_desc.html" .}} -->
<!-- <img src='https://media.dof.dev/kit/logotype.svg?v22' width='66.6%'>
<div
style="
color: var(--col-01);
background-color: #ffffff80;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
padding: 6px 12px;
border-radius: 24px;
margin-top: -32px;
"
>degrees of freedom development</div> -->
</div>
<div style='height: 44px; width: 100%;'></div>

27
tem/html/pages/moves.html Normal file
View file

@ -0,0 +1,27 @@
{{ template "head.html" .}}
<div style='height: 44px; width: 100%;'></div>
<div
style="
display: flex;
align-items: baseline;
width: 100%;
justify-content: left;
padding-left: 12px;
"
>
<h1 style='word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
</h1>
<p>{{ .Desc }}</p>
</div>
{{ range $hash, $move := .Data.Moves }}
<div>
<a href="/move/{{ $hash }}">
<h2>{{ $move.Name }}</h2>
</a>
</div>
{{ end }}

View file

@ -0,0 +1,18 @@
{{ template "head.html" .}}
<div style='height: 44px; width: 100%;'></div>
<div
style="
display: flex;
align-items: baseline;
width: 100%;
justify-content: left;
padding-left: 12px;
"
>
<h1 style='word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
</h1>
<p>{{ .Desc }}</p>
</div>

View file

@ -0,0 +1,27 @@
{{ template "head.html" .}}
<div style='height: 44px; width: 100%;'></div>
<div
style="
display: flex;
align-items: baseline;
width: 100%;
justify-content: left;
padding-left: 12px;
"
>
<h1 style='word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
</h1>
<p>{{ .Desc }}</p>
</div>
{{ range $hash, $project := .Data.Projects }}
<div>
<a href="/project/{{ $hash }}">
<h2>{{ $project.Name }}</h2>
</a>
</div>
{{ end }}

30
tem/html/pages/sc.html Normal file
View file

@ -0,0 +1,30 @@
{{ template "head.html" .}}
<div style='height: 44px; width: 100%;'></div>
<div
style="
display: flex;
align-items: baseline;
width: 100%;
justify-content: left;
padding-left: 12px;
"
>
<h1 style='word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
</h1>
<p>{{ .Desc }}</p>
</div>
<img src="/public/img/spatial.svg" width="100%" />
<div style='height: 12px; width: 100%;'></div>
<h2>spatial computing</h2>
<p>signed unbounded 3d space</p>
<h2>paper computing</h2>
<p>unsigned bounded 2d space</p>
<div style='height: 128px; width: 100%;'></div>

View file

@ -0,0 +1,30 @@
<div id='copyright' style='
padding-bottom: 16px 0;
font-family: "legible", sans-serif;
font-size: 10px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
'>
<div>
<a href='/license'>license</a>&nbsp;&nbsp;&nbsp;
<a href='/about'>about</a>
</div>
<div>
<span id='copyright_year'>&copy; 2018-_</span> <b>dofdev</b>
</div>
</div>
<script>
window.addEventListener('load', () => {
// replace _ in #copyright w/ current year
let date = new Date()
let year = date.getFullYear()
let c = elbyid('copyright_year')
c.innerHTML = c.innerHTML.replace('_', year)
})
</script>

View file

@ -0,0 +1,4 @@
<h1 style='width: 100%; word-wrap: break-word; hyphens: auto;'>
{{ .Title }}
<p>{{ .Desc }}</p>
</h1>

View file

@ -11,7 +11,8 @@ var (
)
func Load() {
Templates = template.Must(template.ParseGlob("tem/html/*.html"))
func_map := template.FuncMap{}
Templates = template.Must(template.New("").Funcs(func_map).ParseGlob("tem/html/**/*.html"))
fmt.Println("templates loaded")
}
@ -19,7 +20,6 @@ func Render(
w http.ResponseWriter,
r *http.Request,
template string,
page string,
title string,
desc string,
page_data interface{},
@ -27,21 +27,21 @@ func Render(
w.WriteHeader(http.StatusOK)
data := struct {
Host string
Page string
Title string
Desc string
Local bool
Root bool
Data interface{}
Host string
PagePath string
Title string
Desc string
Local bool
Root bool
Data interface{}
}{
Host: r.Host,
Page: page,
Title: title,
Desc: desc,
Local: true, // (os.Getenv("LOCAL") == "true"), // toggle here for flag testing
Root: true, // (os.Getenv("HOST_IDEABRELLA") == strings.ReplaceAll(r.Host, ":3000", "")),
Data: page_data,
Host: r.Host,
PagePath: r.URL.Path, // *see header canonical link
Title: title,
Desc: desc,
Local: true, // (os.Getenv("LOCAL") == "true"), // toggle here for flag testing
Root: true, // (os.Getenv("HOST_DOFDEV") == strings.ReplaceAll(r.Host, ":3000", "")),
Data: page_data,
}
err := Templates.ExecuteTemplate(w, template, data)

72
web/pages/about/about.go Normal file
View file

@ -0,0 +1,72 @@
package about
import (
"net/http"
"dofdev/tem"
)
type Project struct {
Name string
Url string
Icon string
}
type Profile struct {
Name string
Url string
Pfp string
}
type Peer struct {
Project Project
Profile Profile ``
}
var Peers = []Peer{
{
Project{
Name: "StereoKit",
Url: "https://stereokit.net",
Icon: "https://stereokit.net/img/StereoKitLogoLight.svg",
},
Profile{},
},
{
Project{
Name: "Stardust XR",
Url: "https://stardustxr.org",
Icon: "https://stardustxr.org/img/icon.gif",
},
Profile{},
},
{
Project{
Name: "Project Northstar",
Url: "https://www.projectnorthstar.org/",
Icon: "/public/img/icons/northstar.svg",
},
Profile{},
},
{
Project{
Name: "Daemon XR",
Url: "https://daemonxr.com",
Icon: "/public/img/icons/daemonxr.png",
},
Profile{},
},
}
func Handler(w http.ResponseWriter, r *http.Request) {
data := struct {
Peers []Peer
}{
Peers: Peers,
}
tem.Render(
w, r,
"about.html",
"dofdev",
"an effort to open higher degrees of spatial interaction free to the world.",
data,
)
}

View file

@ -3,7 +3,7 @@ package braillexr
import (
"net/http"
"github.com/spatialfree/dofdev/tem"
"dofdev/tem"
)
// func Handler(ctx *gin.Context) {
@ -14,7 +14,6 @@ func Handler(w http.ResponseWriter, r *http.Request) {
w, r,
"braille_xr.html",
"braille_xr",
"braille_xr",
"refreshable braille display for rendering and input with handtracking",
data,
)

89
web/pages/games/games.go Normal file
View file

@ -0,0 +1,89 @@
package games
import (
"net/http"
"dofdev/tem"
"github.com/gorilla/mux"
)
type Game struct {
Name string
Desc string
Notes string
}
var Games = map[string]Game{
"silo": {
Name: "stretch silo",
Desc: "a stretch cursor 360 missile defense game",
Notes: `start with air raid sirens
and shouted commands
shilouttes in the night
(fight or flight - adrenaline)
walk into futuristic vector battlestation
(step up buckle down)
overview of your silos and what you are protecting
missiles fly in
(take responsibility)
*ref typhon missile system`,
},
"snake": {
Name: "snake in a box",
Desc: "vr snake zencore",
Notes: `cute happy go lucky eating stuff
older and bigger
and have to deal with your past choices`,
},
"vien": {
Name: "vien",
Desc: "hordiculture",
},
}
func Handler(w http.ResponseWriter, r *http.Request) {
data := struct {
Games map[string]Game
}{
Games: Games,
}
tem.Render(
w, r,
"games.html",
"games",
"dof driven games",
data,
)
}
func GameHandler(w http.ResponseWriter, r *http.Request) {
hash := mux.Vars(r)["hash"]
game, ok := Games[hash]
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
data := struct {
Hash string
Game Game
}{
Hash: hash,
Game: game,
}
tem.Render(
w, r,
"game.html",
game.Name,
game.Desc,
data,
)
}

View file

@ -3,48 +3,29 @@ package mono
import (
"net/http"
"github.com/spatialfree/dofdev/tem"
"dofdev/tem"
"dofdev/web/pages/games"
"dofdev/web/pages/moves"
"dofdev/web/pages/projects"
)
// func Handler(ctx *gin.Context) {
func Handler(w http.ResponseWriter, r *http.Request) {
data := struct {
Projects []Project
TopHash string
Moves map[string]moves.Move
Games map[string]games.Game
Projects map[string]projects.Project
}{
Projects,
TopHash: "silo",
Moves: moves.Moves,
Games: games.Games,
Projects: projects.Projects,
}
tem.Render(
w, r,
"mono.html",
"",
"dofdev",
"an effort to open higher degrees of spatial interaction free to the world.",
data,
)
}
type Project struct {
ID int
Title string
Description string
Art string
}
// This would ideally come from a database
var Projects = []Project{
{ID: 1,
Title: "Prompt-Train",
Description: "PromptTrain, the PromptWriting Excellence Engine, is here to help you enhance your writing skills and unleash your creativity. Receive valuable feedback on your prompts, compete in creative challenges, connect with a supportive community, and embark on your journey towards writing excellence.",
Art: "/res/projects/prompt-train.png",
},
{ID: 2,
Title: "Echo AI",
Description: "With EchoAI, creating AI personas is a breeze. Define your character's name, appearance, traits, speech patterns, emotional range, and background story. Submit website and training reference documents, and specify preferred topics and custom responses. EchoAI offers a user-friendly, step-by-step process to bring your Echo AI persona to life.",
Art: "/res/projects/echo-ai.png",
},
{ID: 3,
Title: "PromptScript",
Description: "PromptScript is a web based ai prompting language that allows you to orchestrate complex systematic patterns with large language models.",
Art: "/res/projects/promptscript.png",
},
}

76
web/pages/moves/moves.go Normal file
View file

@ -0,0 +1,76 @@
package moves
import (
"dofdev/tem"
"net/http"
"github.com/gorilla/mux"
)
type Move struct {
Name string
Desc string
}
var Moves = map[string]Move{
"color_cube": {
Name: "color_cube",
Desc: "color picker & indexer xyz >>> rgb",
},
"oriel": {
Name: "oriel",
Desc: "volumetric graphical control element",
},
"stretch_cursor": {
Name: "stretch_cursor",
Desc: "spatial control using hand distance",
},
"orbital_view": {
Name: "orbital_view",
Desc: "inversely viewed point of interest",
},
"fullstick": {
Name: "fullstick",
Desc: "joystick with full range of motion",
},
}
func Handler(w http.ResponseWriter, r *http.Request) {
data := struct {
Moves map[string]Move
}{
Moves: Moves,
}
tem.Render(
w, r,
"moves.html",
"moves",
"dof driven moves",
data,
)
}
func MoveHandler(w http.ResponseWriter, r *http.Request) {
hash := mux.Vars(r)["hash"]
move, ok := Moves[hash]
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
data := struct {
Hash string
Move Move
}{
Hash: hash,
Move: move,
}
tem.Render(
w, r,
"move.html",
move.Name,
move.Desc,
data,
)
}

View file

@ -0,0 +1,62 @@
package projects
import (
"dofdev/tem"
"net/http"
"github.com/gorilla/mux"
)
type Project struct {
Name string
Desc string
}
var Projects = map[string]Project{
"braille_xr": {
Name: "braille_xr",
Desc: "refreshable braille display for rendering and input with handtracking",
},
"tungtap": {
Name: "tungtap",
Desc: "easily augment your system's keyboard",
},
}
func Handler(w http.ResponseWriter, r *http.Request) {
data := struct {
Projects map[string]Project
}{
Projects: Projects,
}
tem.Render(
w, r,
"projects.html",
"projects",
"dof driven projects",
data,
)
}
func ProjectHandler(w http.ResponseWriter, r *http.Request) {
hash := mux.Vars(r)["hash"]
project, ok := Projects[hash]
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
data := struct {
Project Project
}{
Project: project,
}
tem.Render(
w, r,
"project.html",
project.Name,
project.Desc,
data,
)
}

20
web/pages/sc/sc.go Normal file
View file

@ -0,0 +1,20 @@
package sc
import (
"net/http"
"dofdev/tem"
)
// func Handler(ctx *gin.Context) {
func Handler(w http.ResponseWriter, r *http.Request) {
data := struct {
}{}
tem.Render(
w, r,
"sc.html",
"sc",
"spatial computing vs paper computing",
data,
)
}

BIN
web/public/img/dofdev_logo.svg (Stored with Git LFS)

Binary file not shown.

BIN
web/public/img/icons/community.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/daemonxr.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/discord.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/dofs.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/games.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/home.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/menu.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/placeholder.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/projects.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/search.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/icons/settings.svg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
web/public/img/logo.svg (Stored with Git LFS)

Binary file not shown.

BIN
web/public/img/spatial.svg (Stored with Git LFS) Normal file

Binary file not shown.

84
web/public/js/mono.js Normal file
View file

@ -0,0 +1,84 @@
elbyid = (id) => document.getElementById(id);
clamp = (num, min, max) => Math.min(Math.max(num, min), max);
clamp01 = (num) => clamp(num, 0, 1);
sign = (num) => (num === 0 ? 0 : num > 0 ? 1 : -1);
within = (num, min, max) => num >= min && num <= max;
lerp = (a, b, t) => a + t * (b - a);
document.addEventListener("DOMContentLoaded", () => {
let side_open = localStorage.getItem("side_open") ? true : false;
const nav_el = elbyid("nav");
const nav_border_el = elbyid("nav_border");
const nav_side_el = elbyid("nav_side");
const side_el = elbyid("side");
const side_border_el = elbyid("side_border");
const main_el = elbyid("main");
const top_img_el = elbyid("top_img");
nav_fade = () => {
if (window.scrollY == 0) {
if (!side_open) {
side_el.style.backgroundColor = side_border_el.style.backgroundColor =
"#80808000";
} else {
side_el.style.backgroundColor = "#808080FF";
side_border_el.style.backgroundColor = "#777777FF";
}
nav_el.style.backgroundColor = nav_border_el.style.backgroundColor =
"#80808000";
} else {
nav_el.style.backgroundColor = side_el.style.backgroundColor =
"#808080FF";
nav_border_el.style.backgroundColor =
side_border_el.style.backgroundColor = "#777777FF";
}
};
nav_fade();
nav_el.style.transition =
nav_border_el.style.transition =
side_el.style.transition =
side_border_el.style.transition =
"background-color 0.166s";
window.addEventListener("scroll", (event) => {
nav_fade();
});
open_side = () => {
side_open = true;
localStorage.setItem("side_open", "open");
nav_side_el.style.width = "240px";
side_el.style.width = "240px";
side_el.classList.add("open");
side_border_el.style.left = "240px";
main_el.style.paddingLeft = "240px";
};
close_side = () => {
side_open = false;
localStorage.removeItem("side_open");
nav_side_el.style.width = "auto";
side_el.style.width = "64px";
side_el.classList.remove("open");
side_border_el.style.left = "64px";
main_el.style.paddingLeft = "64px";
};
update_side = () => {
if (side_open) {
open_side();
} else {
close_side();
}
nav_fade();
};
update_side();
toggle_side = () => {
side_open = !side_open;
update_side();
};
});
window.addEventListener("load", () => {});

View file

@ -1,45 +1,242 @@
@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Nanum+Myeongjo&display=swap');
html {
height: 100dvh;
margin: 0 auto;
max-width: 600px;
@font-face {
font-family: "mono";
src: url("/public/fonts/HurmitNerdFontMono-Regular.otf");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "mono";
src: url("/public/fonts/HurmitNerdFontMono-Italic.otf");
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: "mono";
src: url("/public/fonts/HurmitNerdFontMono-Bold.otf");
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "legible";
src: url("/public/fonts/AtkinsonHyperlegible-Regular.ttf");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "brand";
src: url("/public/fonts/HelveticaNeueMedium.otf");
font-weight: normal;
font-style: normal;
font-display: swap;
}
:root {
--col-11: #fff;
--col-10: #eee;
--col-06: #999;
--col-05: #808080;
--col-04: #777;
--col-01: #111;
--col-00: #000;
}
* {
all: unset;
display: block;
box-sizing: border-box;
flex-shrink: 0;
text-wrap: balance;
font-family: 'Atkinson Hyperlegible', sans-serif;
font-family: "mono", monospace;
font-size: 14px;
text-rendering: optimizeLegibility;
text-wrap: balance;
color: var(--col-01);
}
title, style, script {
*::-webkit-scrollbar {
background-color: #80808000;
width: 5px;
height: 8px;
}
*::-webkit-scrollbar-thumb {
background: #ccc;
}
*::placeholder {
color: var(--col-06);
}
title,
style,
script {
display: none;
}
html {
background-color: var(--col-05);
height: 100dvh;
}
body {
height: 100dvh;
margin: 0 auto; padding: 0;
line-height: 1.5;
background-color: #808080;
color: #000;
}
main {
#nav {
position: fixed;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
padding: 6px 12px;
width: 100%;
background-color: #80808000;
z-index: 5;
user-select: none;
}
#nav_border {
position: fixed;
left: 0;
right: 0;
top: 42px;
height: 2px;
width: 100%;
z-index: 5;
}
#side {
background-color: #80808000;
z-index: 4;
width: auto;
position: fixed;
left: 0;
top: 0;
height: 100vh;
padding: 6px;
padding-top: calc(44px + 6px);
display: flex;
flex-flow: column;
justify-content: space-between;
gap: 6px;
> div > a {
display: flex;
align-items: center;
text-decoration: none;
/* background-color: #11111166; */
border-radius: 6px;
padding: 6px;
user-select: none;
flex-flow: column;
width: 52px;
gap: 0px;
font-family: "legible";
font-size: 11px;
color: var(--col-10);
> img {
margin: 0;
}
}
> a.onpage {
background-color: #11111166;
}
> #support {
display: none;
}
> #foot {
display: none;
}
}
#side a:hover {
background-color: #11111166;
transition: 0.166s;
}
#side.open {
> div > a {
flex-flow: row;
width: auto;
gap: 12px;
font-family: "mono";
font-size: 14px;
color: var(--col-01);
}
> #support {
display: flex;
width: 100%;
justify-content: center;
}
> #foot {
display: block;
}
}
#side_border {
z-index: 4;
width: 2px;
position: fixed;
left: 0;
top: 0;
height: 100vh;
transform: translateX(-2px);
}
#main {
height: 100dvh;
width: 100%;
margin: 0 auto;
/* padding-top: 64px; */
display: flex;
flex-flow: column;
align-items: center;
/* max-width: 1024px; */
padding-left: 58px;
}
h1, h2 {
letter-spacing: 2px;
#top_img {
position: absolute;
z-index: -1;
left: 0;
right: 0;
height: 100vh;
}
h1 {
color: #fff;
font-family: "mono";
font-weight: normal;
font-size: 64px;
text-align: center;
margin: 12px 6px;
color: var(--col-10);
text-shadow: 1px 1px 1px var(--col-05);
> p {
font-family: "legible";
font-size: 16px;
text-shadow: none;
color: var(--col-01);
background-color: #ffffff80;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
min-height: 28px;
width: fit-content;
max-width: 420px;
margin: 6px auto;
padding: 12px 21px;
line-height: 22px;
border-radius: 6px;
}
}
a, b, i, code, span {
h2 {
font-family: "mono";
font-weight: normal;
font-size: 32px;
text-align: center;
margin: 12px 6px;
color: var(--col-10);
}
div,
input {
font-family: inherit;
font-size: inherit;
color: inherit;
}
a,
b,
i,
code,
span {
display: inline;
font-family: inherit;
font-size: inherit;
@ -52,12 +249,19 @@ a {
a:focus {
filter: brightness(1.333);
}
b { font-weight: bold; }
i { font-style: italic; }
b {
font-weight: bold;
}
i {
font-style: italic;
}
pre {
white-space: pre-wrap;
}
code {
font-family: 'DM Mono', monospace;
font-family: "DM Mono", monospace;
font-weight: 500;
color: #0000FF;
color: #0000ff;
}
ul {
all: revert;
@ -68,38 +272,21 @@ ul {
li {
all: revert;
}
img, video, canvas {
img,
video,
canvas {
overflow: hidden;
}
img {
all: revert-layer;
display: block;
margin: 0 auto;
border-radius: 6px;
}
video {
border-radius: 6px;
}
.t_symbol {
margin: 2rem auto;
font-family: "Nanum Myeongjo", serif;
text-align: center;
font-size: 64px;
/* font-weight: bold; */
color: #666;
}
footer {
margin-top: 128px;
height: 64px;
line-height: 64px;
letter-spacing: 0.5px;
font-size: 0.75em;
}
input {
outline: none;
border: none;
padding: 8px 16px;
border-radius: 32px;
letter-spacing: 1px;
font-size: 16px;
/* keep this at the end */
.disabled {
filter: grayscale(100%);
opacity: 0.666;
cursor: not-allowed;
pointer-events: none;
user-select: none;
}