added about page + fixed docker cmd / env vars

This commit is contained in:
Leon van Kammen 2026-02-20 13:18:14 +01:00
parent 9b33f916b2
commit 0fc8a7c8e0
20 changed files with 2649 additions and 204 deletions

View file

@ -18,6 +18,18 @@ $ docker run -t xrforge docker.io/coderofsalvation/xrforge:latest -v ./mnt:/mnt
> To scan all (mounted) libraries run this once: `$ docker exec xrforge /manyfold/cli/manyfold.sh scan_libraries`
# ports
By default the following services are running in the docker:
| port | HTTP PATH | info |
|-------|----------------------------------------------|
| 3214 | / | [Manyfold](https://manyfold.app) |
[ 3214 | /view | [janusweb](https://github.com/meetecho/janus-gateway) the XR viewer |
| 5566 | | [janus-server](https://github.com/janusvr/janus-server) for chat + syncing avatar positions |
| 5577 | / | [cors-anywhere](https://github.com/Rob--W/cors-anywhere) for a deep immersive browsing via janusweb |
| *6379 | | Manyfold REDIS-server (* = never expose this port) |
# Build & Run the container-image
> **NOTE**: [nix](https://nixos.org) is used to promote reproducability-over-repeatability
@ -29,7 +41,7 @@ $ docker load < $(nix-build nix/docker.nix)
$ docker run $(manyfold/cli/manyfold run) # generates a dockercmd with sane env-flags
[xrforge] podman detected..starting OCI container
+ /run/current-system/sw/bin/podman run -p 8790:3214 -p 8791:3215 --name xrforge -e SECRET_KEY_BASE=lkjwljlkwejrlkjek34k234l -e DATABASE_ADAPTER=sqlite3 -e SUDO_RUN_UNSAFELY=enabled -e MULTIUSER=enabled -e FEDERATION=enabled -e THEME=vapor -e HOMEPAGE=/models -e FEDERATE_DRIVE_CACHE=5s -v ./xrfragment/assets:/mnt/assets/xrfragment/#1 --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse xrforge
+ /usr/bin/podman run -p 8080:3214 -p 8791:3215 --name xrforge -e SECRET_KEY_BASE=lkjwljlkwejrlkjek34k234l -e DATABASE_ADAPTER=sqlite3 -e SUDO_RUN_UNSAFELY=enabled -e MULTIUSER=enabled -e FEDERATION=enabled -e THEME=vapor -e HOMEPAGE=/models -e FEDERATE_DRIVE_CACHE=5s -v ./xrfragment/assets:/mnt/assets/xrfragment/#1 --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse xrforge
[xrforge] booting...
[xrforge] applying filesystem overlay
sending incremental file list
@ -66,9 +78,11 @@ $ docker run -t xrforge docker.io/coderofsalvation/xrforge:latest -v ./config:/c
| `NO_PACKAGEALL` | `` | don't package all experiences every hour to /usr/src/app/public/experiences.zip |
| `RCLONE_REMOTE` | `` | specify **single** rclone remote name (without semicolon) to mount (default: mount all rclone remotes)|
| `UPLOAD_PATH` | `/mnt/experiences`| specify default library where user-files are uploaded (regular dir or mounted rclone path) |
| `FEDERATE_DRIVE_HOST` | `http://localhost:3215` | host adress which other hosts can use to access the federate drive |
| `FEDERATE_SERVERS` | see info | allowed servers to share remote content with |
| | | `"https://janusxr.org","https://web.janusxr.org", "https://vesta.janusxr.org", "https://xrfragment.org", "https://isvery.ninja", "https://xrhf.isvery.ninja", "https://xrforge.isvery.ninja"` |
| `FEDERATE_DRIVE_HOST` | `http://localhost:8081` | host adress which other hosts can use to access the federate drive |
| `FEDERATE_DRIVE_PATH` | `/mnt` | serve path over HTTP (so other instances can add it as a remote). Specify `0` to disable |
| `FEDERATE_DRIVE_PORT` | `3215` | specify default library where user-files are uploaded (regular dir or mounted rclone path) |
| `FEDERATE_DRIVE_PORT` | `8081` | specify port |
| `FEDERATE_DRIVE_USER` | `` | specify HTTP AUTH credentials (`user` e.g.) for restricted sharing |
| `FEDERATE_DRIVE_PW` | `` | specify HTTP AUTH credentials (`pass` e.g.) for restricted sharing |
| `FEDERATE_DRIVE_CACHE`| `1m0s` | specify interval to re-check all models/directories |
@ -94,9 +108,33 @@ It's also possible to enforce a default sqlite3 db via the `-v ./manyfold.sql:/m
The server-image will boot `manyfold/cli/manyfold.sh boot` and check for directory `/manyfold` (in the container).
When found, it uses the files in there instead (`/manyfold/usr/src/app/public/404.html` instead of `/usr/src/app/public/404.html` e.g.).
# Federated libraries
# Federation
Besides ActivitPub, XRForge allows federating manyfold libraries too, which allows manyfold libraries to:
Federation is possible on many levels:
1. Outbound: cors-anywhere
By default [cors-anywhere](https://github.com/Rob--W/cors-anywhere), so XRForge can source remote content from anywhere.
> It is running inside the docker on port 5577, and can be disabled by env-var `SERVER_CORS=''`
1. Inbound: restrict via env-var `FEDERATE_SERVERS`
This way you can only allow trusted servers to use your content (iframes e.g.):
| usecase | env-var value |
|--------------------|---------------|
| every server | `FEDERATE_SERVERS='"*"'` (default) |
| only this instance | `FEDERATE_SERVERS=':self'` |
| trusted servers | `FEDERATE_SERVERS='"https://janusxr.org", https://web.janusxr.org", "https://vesta.janusxr.org", "https://xrfragment.org", "https://isvery.ninja", "https://xrhf.isvery.ninja", "https://xrforge.isvery.ninja"' |
* ActivityPub: each author and experiences can be followed
Next experiences and authors, an '@' address is shown.<br>
You can enter these in mastodon to follow updates.
* Federating network-drives via `FEDERATE_DRIVE_HOST`
Network-drives:
* be mounted as a network drive on their desktop-machine (3D editor export-to-library)
* scale horizontally across instances:
@ -128,7 +166,7 @@ To enable rclone to mount **readonly** network drives (=remotes), the container
The quickest way is:
1. create directory `./manyfold/root/.config` outside of the container
2. add `-v ./manyfold/root/.config:/root/.config --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse` to the docker cmd
2. add `-v ./manyfold/root/.config:/root/.config --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse -p 8081:8081 -e FEDERATE_DRIVE_PORT=8081 -e FEDERATE_DRIVE_HOST=http://localhost:8081` to the docker cmd
3. now federate XRForge libraries by running `docker exec -it xrforge rclone config create myhttp http url=https://xrforgeinstanceB.com user=myuser pass=$(rclone obscure mypassword)` in a running container
4. profit!

View file

@ -9,12 +9,18 @@ test -n "$GODOT_VERSION" || export GODOT_VERSION=4.4.1-stable
test -n "$IMPORT_INSTANCES" || export IMPORT_INSTANCES=1
test -n "$SERVER_CORS" || export SERVER_CORS=http://localhost:5577
test -n "$SERVER_JANUS" || export SERVER_JANUS=http://localhost:5566
test -n "$HTTPS_ONLY" || export HTTPS_ONLY=disabled
test -n "$HTTPS_ONLY" || unsafe=1 && export HTTPS_ONLY=disabled
test -n "$SECRET_KEY_BASE" || unsafe=1 && export SECRET_KEY_BASE=j1gf2cj3gfcjhf2j34298kjk2j3h4k
test -n "$SUDO_RUN_UNSAFELY" || unsafe=1 && export SUDO_RUN_UNSAFELY=enabled
test -n "$DATABASE_ADAPTER" || export DATABASE_ADAPTER=sqlite3
test -n "$MULTIUSER" || export MULTIUSER=enabled
test -n "$FEDERATE_SERVERS" || export FEDERATE_SERVERS='"*"'
test -n "$PUBLIC_HOSTNAME" || export PUBLIC_HOSTNAME=localhost
test -n "$CADDY" && {
export HTTPS_ONLY=enabled
export SERVER_CORS=https://$CADDY:5577
export SERVER_JANUS=https://$CADDY:5566
export PUBLIC_HOSTNAME=localhost
}
db=/config/manyfold.sqlite3
@ -48,6 +54,7 @@ run(){
-e SECRET_KEY_BASE=lkjwljlkwejrlkjek34k234l \
-e DATABASE_ADAPTER=sqlite3 \
-e FEDERATE_DRIVE_HOST=http://localhost:8081 \
-e FEDERATE_DRIVE_PORT=8081 \
-e PUBLIC_HOSTNAME=$PUBLIC_HOSTNAME \
-e SERVER_JANUS=$SERVER_JANUS \
-e SERVER_CORS=$SERVER_CORS \
@ -248,14 +255,14 @@ rename_app(){
sed -i 's|File(s) uploaded succesfully|File(s) uploaded succesfully. The experience is now being (re)generated, please be patient and check back later|g' /usr/src/app/config/locales/model_files/en.yml
}
allow_csp(){
test -n "$FEDERATE_DRIVE_HOST" || return 0
# allow iframes + other federated servers
servers='"https://web.janusxr.org", "https://vesta.janusxr.org"'
sed -i "s|:self,|:self, $servers, ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'],|g" /usr/src/app/app/controllers/application_controller.rb
sed -i "s|content_security_policy.connect_src(\*origins)|content_security_policy.connect_src(\*origins);content_security_policy.connect_src( $servers, ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'])|g" /usr/src/app/app/controllers/application_controller.rb
# content_security_policy.clear_directives()
# content_security_policy.default_src '*'
federate_servers(){
# allow iframes + other federated servers by adjusting manyfold's strict CSP policies
local servers="$FEDERATE_SERVERS"
test -n "$FEDERATE_DRIVE_HOST" && servers="${servers}, \"$FEDERATE_DRIVE_HOST\""
test -n "$SERVER_CORS" && servers="${servers}, \"$SERVER_CORS\""
test -n "$SERVER_JANUS" && servers="${servers}, \"$SERVER_JANUS\""
sed -i "s|:self,|:self, $servers,|g" /usr/src/app/app/controllers/application_controller.rb
sed -i "s|content_security_policy.connect_src(\*origins)|content_security_policy.connect_src(\*origins);content_security_policy.connect_src( $servers )|g" /usr/src/app/app/controllers/application_controller.rb
}
start_syslog(){
@ -293,9 +300,14 @@ force_public(){
import_assets(){
test -n "$NO_ASSETS" && return 0 # nothing to do here
if test -n "$FEDERATE_DRIVE_HOST"; then
# mount because rclone does support symlinks outside of the served folder
mkdir /mnt/templates && mount --bind /nix/store/*-xrfragments/xrf/templates /mnt/templates
mkdir /mnt/assets && mount --bind /nix/store/*-xrfragments/xrf/assets /mnt/assets
else
ln -s /nix/store/*-xrfragments/xrf/templates /mnt/templates
ln -s /nix/store/*-xrfragments/xrf/assets /mnt/assets
fi
add_lib_to_db /mnt/assets
add_lib_to_db /mnt/templates
}
@ -348,7 +360,7 @@ boot(){
test -z "$NO_OVERLAYFS" && overlayfs
start_syslog
rename_app
allow_csp
federate_servers
set_homepage
start_hook_daemon
mount_rclone
@ -371,9 +383,10 @@ is_inside_container(){
usage(){
echocolor "Usage:" manyfold.sh "<cmd>"
echocolor "Cmds:"
echocolor " " "run [-d] " "# runs a OCI container (needs podman/docker)"
echocolor " " "run [-d] " "# prints OCI container cmd (needs podman/docker)"
exit 0
}
test "$unsafe" = 1 && echocolor "[WARNING]" "default env-vars SECRET_KEY_BASE or SUDO_RUN_UNSAFELY are used. Please check: https://codeberg.org/coderofsalvation/xrforge/src/branch/master/manyfold" && echo
test -n "$1" && "$@"
test -n "$1" || usage

View file

@ -1,167 +0,0 @@
class ApplicationController < ActionController::Base
include Pundit::Authorization
include BetterContentSecurityPolicy::HasContentSecurityPolicy
after_action :verify_authorized, except: :index, unless: -> { respond_to?(:fasp_client_controller?) }
after_action :verify_policy_scoped, only: :index, unless: -> { respond_to?(:fasp_client_controller?) }
after_action :set_content_security_policy_header, if: -> { request.format.html? }
before_action :authenticate_user!, unless: -> { SiteSettings.multiuser_enabled? || has_signed_id? }
around_action :switch_locale, if: -> { request.format.html? }
before_action :check_for_first_use
before_action :show_security_alerts
before_action :check_scan_status
before_action :remember_ordering
before_action :restore_failed_search
protect_from_forgery with: :null_session, if: :is_api_request?
rescue_from ScopedSearch::QueryNotSupported, with: -> {
flash[:alert] = t("application.search_error")
flash[:query] = params[:q]
redirect_back_or_to root_path
}
unless Rails.env.test?
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
end
def index
raise NotImplementedError
end
def authenticate_admin_user!
authenticate_user!
render plain: "401 Unauthorized", status: :unauthorized unless current_user.is_administrator?
end
def check_for_first_use
authenticate_user! if User.count == 0 # rubocop:disable Pundit/UsePolicyScope
redirect_to(edit_user_registration_path) if current_user&.reset_password_token == "first_use"
end
def check_scan_status
@scan_in_progress = Sidekiq::Queue.new("scan").size > 0
end
def remember_ordering
session["order"] ||= "name"
session["order"] = params["order"] if params["order"]
end
private
def restore_failed_search
@query ||= flash[:query]
end
def is_api_request?
request.format.manyfold_api_v0?
end
def has_signed_id?
params[:id] && ApplicationRecord.signed_id_verifier.valid_message?(params[:id])
end
def img_src
host = begin
SiteSettings.site_icon ? URI.parse(SiteSettings.site_icon).host : nil
rescue
nil
end
[
:self, "https://web.janusxr.org", "https://vesta.janusxr.org", ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'],
:data,
host,
"https://cdn.jsdelivr.net",
"https://raw.githubusercontent.com",
SiteSettings.federation_enabled? ? :https : nil
].compact
end
def frame_src
[
:self, "https://web.janusxr.org", "https://vesta.janusxr.org", ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'],
SiteSettings.federation_enabled? ? :https : nil
].compact
end
def configure_content_security_policy
return if Rails.env.test?
# Standard security policy
content_security_policy.default_src :self
content_security_policy.connect_src :self
content_security_policy.frame_ancestors :self
content_security_policy.frame_src(*frame_src)
content_security_policy.font_src :self, "https://web.janusxr.org", "https://vesta.janusxr.org", ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'], "https://cdn.jsdelivr.net", "https://fonts.gstatic.com"
content_security_policy.img_src(*img_src)
content_security_policy.object_src :none
content_security_policy.script_src :self
content_security_policy.style_src :self
content_security_policy.style_src_attr :unsafe_inline
content_security_policy.style_src_elem :self, "https://web.janusxr.org", "https://vesta.janusxr.org", ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'], "nonce-#{content_security_policy_nonce}", "https://fonts.googleapis.com"
# Add library origins
origins = Library.all.filter_map(&:storage_origin) # rubocop:disable Pundit/UsePolicyScope
content_security_policy.img_src(*origins)
content_security_policy.connect_src(*origins);content_security_policy.connect_src( "https://web.janusxr.org", "https://vesta.janusxr.org", ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS'])
# If we're using Scout DevTrace in local development, we need to allow a load
# of inline stuff, so we need to add that and NOT add the nonce
if Rails.env.development? && ENV.fetch("SCOUT_DEV_TRACE", false) === "true"
scout_csp = [:unsafe_inline, "https://apm.scoutapp.com", "https://scoutapm.com"]
content_security_policy.img_src(*scout_csp)
content_security_policy.script_src(*scout_csp)
content_security_policy.style_src(*scout_csp)
content_security_policy.connect_src(*scout_csp)
content_security_policy.frame_src(*scout_csp)
else
content_security_policy.script_src "nonce-#{content_security_policy_nonce}"
end
end
def switch_locale(&action)
locale = current_user&.interface_language || request.env["rack.locale"]
I18n.with_locale(locale.presence, &action)
end
def show_security_alerts
return unless current_user&.is_administrator?
return if ENV.fetch("SUDO_RUN_UNSAFELY", nil) === "enabled"
flash.now[:alert] = t("security.running_as_root_html") if Process.uid == 0
end
def random_delay
# Not sure how secure this is; it's used to help with timing attacks on login ID lookups
# by adding a random 0-2 second delay into the response. There is probably a better way.
sleep Random.new.rand(2.0)
end
def user_not_authorized
if current_user
raise ActiveRecord::RecordNotFound
else
redirect_to new_session_path(:user)
end
end
def set_indexable(content)
arr = Array(content)
@indexing_directives = [
("noindex" unless arr.map(&:indexable?).all?),
("noai noimageai" unless arr.map(&:ai_indexable?).all?)
].compact.join(" ")
response.headers["X-Robots-Tag"] = @indexing_directives if @indexing_directives.presence
end
def send_file_content(attachment, disposition: :attachment, derivative: nil)
head :not_found and return if attachment.nil?
# Check if we can send a direct URL
redirect_to(attachment.url, allow_other_host: true) if /https?:\/\//.match?(attachment.url)
# Otherwise provide a direct download
status, headers, body = attachment.to_rack_response(disposition: disposition)
self.status = status
self.headers.merge!(headers)
self.response_body = body
rescue Errno::ENOENT
head :internal_server_error
end
end

View file

@ -30,6 +30,12 @@
</li>
<% end %>
<% end %>
<li class="nav-item">
<a class="nav-link " href="/about">
<span><i class="bi bi-question-circle" role="img" title="About"></i></span>
<span class="d-md-none d-lg-inline">About</span>
</a>
</li>
</ul>
<ul class="navbar-nav col-auto pe-4 align-self-start justify-content-end">
<li class="nav-item">

View file

@ -16,10 +16,20 @@ Rails.application.config.after_initialize do
policy.default_src :self, :https, :http
# *** ADD THE DOMAIN(S) FOR YOUR IFRAME CONTENT HERE ***
policy.frame_src :self, ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS']
policy.script_src :self, ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS']
policy.style_src :self, ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS']
policy.connect_src :self, ENV['FEDERATE_DRIVE_HOST'], ENV['SERVER_CORS'], ENV['SERVER_JANUS']
allowed = (ENV['FEDERATE_SERVERS'] || '')
.gsub(/[" ]/,'')
.split(",")
.concat([
:self,
ENV['FEDERATE_DRIVE_HOST'],
ENV['SERVER_CORS'],
ENV['SERVER_JANUS']
])
.compact # remove potential nils
policy.frame_src *allowed
policy.script_src *allowed
policy.style_src *allowed
policy.connect_src *allowed
# ...
end

View file

@ -1,7 +1,11 @@
# always allow cors so remote XR viewers can load content
Rails.application.config.middleware.insert_after Rack::Head, Rack::Cors do
#Rails.application.config.middleware.insert_after Rack::Head, Rack::Cors do
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :options, :head]
end
File.open("/tmp/out","w") do |f|
f.write("Hello Ruby!")
end
end

View file

@ -0,0 +1,411 @@
<!doctype html>
<html lang="en" _data-theme="light">
<head>
<meta charset="utf-8">
<title>XRForge - link AR/VR experiences together 🥽</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<meta name="description" content="XRForge - link AR/VR experiences together 🥽" />
<meta name="publisher" content="XRForge - link AR/VR experiences together" />
<meta name="author" content="XRForge"/>
<link rel="stylesheet" href="/assets/themes/slate-9cc3cc7d.css" nonce="1de89072246b25ca36376d8f1cf5e051" />
<link rel="stylesheet" href="/assets/xrforge.css" />
</head>
<body>
<nav class="navbar navbar-expand-md bg-primary" data-bs-theme="dark">
<div class="container-fluid">
<a class="navbar-brand ms-2" href="/" aria-label="Homepage">
<img alt="XRForge" height="40px" class="me-2" src="/assets/roundel-1d688b1e.svg">
<span class="d-md-none">XRForge</span>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse row" id="navbar">
<ul class="navbar-nav col ps-4 ps-md-0 align-self-start">
<li class="nav-item">
<a class="nav-link active" href="/models"><span><i class="bi bi-box" role="img" title="Experiences"></i></span> <span class="d-md-none d-lg-inline">Experiences</span></a>
</li>
<li class="nav-item">
<a class="nav-link " href="/creators"><span><i class="bi bi-people" role="img" title="Creators"></i></span> <span class="d-md-none d-lg-inline">Creators</span></a>
</li>
<li class="nav-item">
<a class="nav-link " href="/collections"><span><i class="bi bi-collection" role="img" title="Collections"></i></span> <span class="d-md-none d-lg-inline">Collections</span></a>
</li>
</ul>
<ul class="navbar-nav col-auto pe-4 align-self-start justify-content-end">
<li class="nav-item">
</li>
<li class="nav-item">
</li>
<li id="nav-search" class="nav-item ms-1 me-3" data-turbo-permanent="">
<form action="/models" accept-charset="UTF-8" method="get">
<input class="form-control" placeholder="Search" aria_label="Search" aria_describedby="button-search" type="search" name="q" id="q">
</form> </li>
<li class="nav-item">
<a class="btn btn-secondary" nofollow="true" href="/users/sign_in"><span><i class="bi bi-box-arrow-in-right" role="img" title="Sign in"></i></span> <span>Sign in</span></a>
</li>
</ul>
</div>
</div>
</nav>
<header class="container">
<div style="padding:20px 10px;text-align:right">
<small>member of <a href="https://xrhf.isvery.ninja" target="_blank">XR Hypermedia Federation</a></small>
<div id="xrhf"></div>
</div>
<div id="logo"></div>
<h2>Turn files into AR/VR 🥽 experiences</h2>
<br>
<center>
<a href="https://codeberg.org/coderofsalvation/xrforge" class="btn btn-secondary">
<img src="assets/codeberg.svg" style="width:20px"/>
Check the sourcecode<br>
<small>irc.isvery.ninja port 443 via ObsidianIRC</small>
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://isvery.ninja/chat/index.html" class="btn btn-secondary" style="text-align:left">
<img src="assets/obsidian.png" style="width:20px"/>
chat with community <br>
<small>irc.isvery.ninja port 443 via ObsidianIRC</small>
</a>
<br>
</center>
<div id="badges"></div>
<br>
<div id="hint"></div>
<div class="clear"></div>
</header>
<!-- ./ Header -->
<!-- Main -->
<main class="container">
<div class="telescopic">
Publish AR/VR experiences without
<u tabindex="0">obstacles 🈚
<span>like appstores, rent-seeking, blockchain-minting etc</span>
</u>
<br>
Use existing
<u tabindex="0">ecosystems
<span>like the 2D web, or file-collections</span>
</u> within <b>AR/VR-headsets</b> via open
<u tabindex="0">xrfragments 🔌
<span>: <a href="https://en.wikipedia.org/wiki/RSS" target="_blank">RSS</a>, HTML, <a href="https://janusxr.org/docs/build/introtojml/index.html" target="_blank">JML</a>, Fediverse's <a href="https://activitypub.rocks/" target="_blank">ActivityPub</a> and <a href="https://xrfragment.org">URI's using XR Fragments</a> e.g.</span>
</u>
<br>
</div>
<br>
<h3>Why people want XRForge</h3>
<div>
The metaverse-hype has shown: people <b>like 3D</b> but <b>existing</b> 2D ecosystems are king.<br>
They're just more cost-efficient to use.<br>
Hence, XRForge promotes <b>projecting these ecosystems</b> as virtual <b>hyperlinked</b> worlds.<br>
XRForge can seed itself via local or remote
<u tabindex="0">datastores
<span>
<br>
<br>
<b>Support for datastores:</b>
<br>
<table class="table table-dark table-striped">
<tr><td>
Azure Blob <br>
Azure Files <br>
B2 <br>
Box <br>
Cloudinary <br>
Doi <br>
Drime <br>
Drive <br>
Dropbox <br>
Fichier <br>
Filefabric <br>
Filelu <br>
Filen <br>
Filescom <br>
FTP <br>
Gofile <br>
</td>
<td>
Google Cloud Storage <br>
Google Photos <br>
HDFS <br>
Hidrive <br>
HTTP <br>
Iclouddrive <br>
Imagekit <br>
Internet Archive <br>
Internxt <br>
Jottacloud <br>
Koofr <br>
Linkbox <br>
Local <br>
Mailru <br>
Mega <br>
</td>
<td>
Memory <br>
Netstorage <br>
Onedrive <br>
Opendrive <br>
Oracle Object Storage <br>
Pcloud <br>
Pikpak <br>
Pixeldrain <br>
Premiumizeme <br>
Proton Drive <br>
Putio <br>
Qingstor <br>
Quatrix <br>
S3 <br>
Seafile <br>
</td>
<td>
SFTP <br>
Shade <br>
Sharefile <br>
Sia <br>
SMB <br>
Storj <br>
Sugarsync <br>
Swift <br>
Ulozto <br>
WebDAV <br>
Yandex <br>
Zoho <br>
</td>
</tr>
</table>
</span>
</u>, making it perfect for large organisations.
<div id="xrecosystem"></div>
The
<u tabindex="0">Fediverse
<span>, a fleet of ad-free <a href="https://jointhefediverse.net/learn" target="_blank">federated platforms</a>,</span>
</u> makes an excellent backoffice for virtual <b>XR hypermedia</b> experiences.<br>
<b>Federated</b> experiences <b>allow anybody</b> to extend
<u tabindex="0">existing
<span>open-source foundations and shared data</span>
</u>
foundations to accelerate XR
<u tabindex="0">innovation
<span>, by allowing them to "remix" and expand the world </span>
</u>.<br>
<b>Byebye</b> constantly reinventing the wheel / walled gardens.<br>
<b>Hello</b> post-scarcity technology.
<br><br>
<center>
<img src="assets/xrforge_term.svg" style="border-radius:7px; border-radius: 7px; width: 100%; max-width: 450px; margin-bottom: 40px;">
</center>
</div>
<div class="spectrum">
<div></div>
<div></div>
</div>
<center>
<h3>Supporter of Open XR Hypermedia stacks</h3>
<div style="max-width:945px;">
<a href="https://coderofsalvation.github.io/janus-guide/" target="_blank">
<img src="/assets/janusxr-xrf.png"/>
</a>
<br>
</div>
</center>
<div class="spectrum">
<div></div>
<div></div>
</div>
<!--
<div id="cards">
<h3 id="howto">How to use XR Forge:&nbsp;&nbsp;</h3>
<input type="radio" id="reset" name="color"/>
<label for="reset"><kbd>#all</kbd></label>
<input type="radio" id="xrfragment" name="color" />
<label for="xrfragment"><kbd>#protocol</kbd></label>
<input type="radio" id="openlearning" name="color"/>
<label for="openlearning"><kbd>#openlearning</kbd></label>
<input type="radio" id="browser" name="color"/>
<label for="browser"><kbd>#xrbrowser</kbd></label>
<input type="radio" id="xrdiscovery" name="color"/>
<label for="xrdiscovery"><kbd>#xrdiscovery</kbd></label>
<input type="radio" id="xrtranslator" name="color"/>
<label for="xrtranslator"><kbd>#xrtranslator</kbd></label>
<input type="radio" id="worldpreservation" name="color"/>
<label for="worldpreservation"><kbd>#worldpreservation</kbd></label>
<br/>
<br/>
<div class="tile xrdiscovery">
<div id="xrforge" class="thumb"></div>
<a class="description" href="https://xrforge.isvery.ninja" target="_blank">
<b>XR Forge</b> is a selfhostable federated platform for JanusWeb/File-based XR Experiences.
#cost-efficient #collaboration #Universities #E-learning #activitpub
</a>
</div>
<div class="tile worldpreservation">
<div id="nexus" class="thumb"></div>
<a class="description" href="https://github.com/TheNexusCity/TheNexus" target="_blank">
The Nexus is an open source, community-driven, CC0 city for open virtual worlds.<br>
#3Dmodels #CreativeCommons
</a>
</div>
<div class="tile worldpreservation">
<div id="lobby" class="thumb"></div>
<a class="description" href="https://github.com/madjin/webxr-lobby" target="_blank">
Opensource Lobby models as 'startingpage' for virtual worlds.<br>
A lobby is an entry-space with doors to other spaces.<br>
</a>
</div>
<div class="tile xrfragment">
<div id="xrfragment" class="thumb"></div>
<a class="description" href="https://xrfragment.org" target="_blank">
XR (URI) Fragments is a browser-xrfragment for
spatial anchors in URLs (to 3D files).<br>
In <b>gamer language</b>: spawnpoints via URLs.
</a>
</div>
<div class="tile xrbrowser">
<div id="januswebbrowser" class="thumb"></div>
<a class="description" href="https://coderofsalvation.github.io/janus-guide/" target="_blank">
<b>JanusWeb</b> browses the XR web inside the web.<br>
Its JML syntax allows regular webpages to project a 3D version.<br>
It also supports 3D files via XR URLs/Fragments.
</a>
</div>
<div class="tile openlearning">
<div id="biggu_s_gate" class="thumb"></div>
<a class="description" href="https://git.benetou.fr/utopiah/biggu_s_gate" target="_blank">
<b>Biggu's Gate</b> is self-hostable web-software to remix simple pedagogical XR games. Learners themselves can then, together with parents and teachers.
</a>
</div>
<div class="tile xrtranslator">
<div id="translators" class="thumb"></div>
<div id="janusweb" class="thumb hue-1" style="background-position: 50% 77px"></div>
<a class="description" href="https://coderofsalvation.github.io/janus-guide/#/wiki/translators" target="_blank">
JanusWeb's <b>XR translators</b> spatialize the web, embedding webstandards like (RSS/HTML) and popular fediverse platforms (peertube/mastodon e.g.).<br>
</a>
</div>
<div class="tile worldpreservation">
<div id="archive_org" class="thumb"></div>
<div id="janusweb" class="thumb hue-2" style="background-position: 50% 77px"></div>
<a class="description" href="https://github.com/jbaicoianu/janusweb" target="_blank">
The XRForge project is currently implementating ways to prevent link / virtualworld <b>rot</b> by integrating backups to <b>archive.org</b>.
</a>
</div>
<div class="tile xrfragment">
<div id="jml" class="thumb"></div>
<div id="janusweb" class="thumb hue-3" style="background-position: 50% 77px"></div>
<a class="description" href="https://janusxr.org/docs/build/introtojml/index.html" target="_blank">
JML is a portable markup-lanuage which allows describing 3D spaces (and link them with portals).
</a>
</div>
<div class="tile xrdiscovery">
<div id="searxr" class="thumb"></div>
<a class="description" href="https://searxr.me" target="_blank">
<b>SearXR</b> is a SearX-based meta-searchengine for <b>WebXR</b> experiences.
</a>
</div>
<div class="tile xrtranslator">
<div id="xrshthumb" class="thumb"></div>
<a class="description" href="https://xrsh.isvery.ninja" target="_blank">
<b>XRSH</b> is a Linux Shell for <b>WebXR</b>, which makes the Linux ecosystem of cli-tools available in <b>WebXR</b>.
</a>
</div>
<div class="tile xrbrowser">
<div id="aframeverse" class="thumb"></div>
<a class="description" href="https://github.com/coderofsalvation/aframe-verse" target="_blank">
AFRAME-verse was a XR Hypermedia network-experiment which traverses crossdomain AFRAME XR experiences seamlessly. The learnings became the fundament for the XR (URI) Fragments.<br>
</a>
</div>
<div class="tile xrbrowser">
<div id="elfa" class="thumb"></div>
<a class="description" href="https://fosstodon.org/@elfa" target="_blank">
<b>ELFA</b> is a suite of <b>E</b>ncrypted <b>L</b>ocal<b>F</b>irst<b> A</b>pplications, an integrated Suite of Apps, integrated with VR/XR.<br>
</a>
</div>
<div class="tile xrtranslator">
<div id="peertube" class="thumb"></div>
<a class="description" href="https://codeberg.org/coderofsalvation/janus-script-peertube" target="_blank">
<b>Peertube</b> is a free and open-source platform for sharing videos.<br>This translator makes it possible to view peertube in JanusWeb.<br>
</a>
</div>
<div class="tile openlearning">
<div id="janusdialog" class="thumb"></div>
<a class="description" href="https://codeberg.org/coderofsalvation/janus-script-dialog" target="_blank">
This janusweb AR/VR dialog-component makes it possible to make spatial elearnings more dynamic.
</a>
</div>
<div class="tile xrtranslator">
<div id="janusrss" class="thumb"></div>
<a class="description" href="https://codeberg.org/coderofsalvation/janus-script-rss" target="_blank">
This janusweb AR/VR component makes it possible to read RSS-feeds, an important web-buildingblock in Janusweb.
</a>
</div>
<div class="tile xrtranslator">
<div id="janusfetch" class="thumb"></div>
<a class="description" href="https://codeberg.org/coderofsalvation/janus-script-fetch" target="_blank">
This janusweb AR/VR component makes it possible to import partial content from the web in realtime.
</a>
</div>
<div class="clear"></div>
</div>
<br>
<div class="spectrum">
<div></div>
<div></div>
</div>
<div class="footer">
<small>Jump to:</small>
<a href="#howto"><kbd>#howto</kbd></a>
<a href="#timeline"><kbd>#timeline</kbd></a>
<a href="#faq"><kbd>#getfunding</kbd></a>
<a href="#faq"><kbd>#faq</kbd></a>
</div>
-->
</main>
<script>
// telescopic text:
// a JS cheat whicht allows persisting unfolds
// uncomment this if you really want this
([...document.querySelectorAll('u')]).map( (u) => {
u.addEventListener('click', e => e.target.className = 'show' )
});
</script>
</body>
</html>

View file

@ -0,0 +1,994 @@
:root {
--pico-line-height: 2;
--pico-primary-background: #77F !important;
}
.container{
}
main{
margin-bottom:120px;
}
small{
color: var(--pico-contrast-underline);
}
.hue-1{ filter: hue-rotate(45deg); }
.hue-2{ filter: hue-rotate(90deg); }
.hue-3{ filter: hue-rotate(135deg); }
.hue-4{ filter: hue-rotate(180deg); }
a,
a:active{
color: #95F;
}
a:visited{
color: #888;
}
header > .spectrum,
div#logo{
width:290px;
}
/* images (hidden for html2text browsers like lynx) */
div#logo{
background: url(../img/xrh-full.svg);
height:112px;
display:inline-block;
background-size:cover;
}
div#lvk{
background: url(../img/lvk.jpg);
height:100px;
width:100px;
background-size:cover;
display:inline-block;
border-radius:50%;
float:left;
margin-right:25px;
}
div#jin{
background: url(../img/madjin.png);
height:100px;
width:100px;
background-size:cover;
display:inline-block;
border-radius:50%;
float:left;
margin-right:25px;
}
div#fabien{
background: url(../img/fabien.jpg);
height:100px;
width:100px;
background-size:cover;
display:inline-block;
border-radius:50%;
float:left;
margin-right:25px;
}
button,
.btn{
box-shadow: 0px 0px 15px #77F7;
}
.btn{
-webkit-appearance: button;
--pico-background-color: var(--pico-primary-background);
--pico-border-color: var(--pico-primary-border);
--pico-color: var(--pico-primary-inverse);
--pico-box-shadow: var(--pico-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
border: var(--pico-border-width) solid var(--pico-border-color);
border-radius: var(--pico-border-radius);
outline: 0;
background-color: var(--pico-background-color);
box-shadow: var(--pico-box-shadow);
color: var(--pico-color);
font-weight: var(--pico-font-weight);
font-size: 1rem;
line-height: var(--pico-line-height);
text-align: center;
text-decoration: none;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
transition: background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition);
}
div.banner,
div#banner {
overflow:hidden;
height: 40vh;
max-height:200px;
width: 100%;
margin:30px 0px;
border-radius:7px;
}
div#banner{
background: url(../img/banner.jpg);
background-size: 10%;
background-position: center;
-webkit-animation: scrolly 20s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
animation: scrolly 20s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}
div#hint{
float:right;
background: url(../img/blinkhint.svg);
height: 129px;
background-size: cover;
display:inline-block;
width: 200px;
}
div#xrecosystem{
background: #000 url(../img/xrecosystem.png);
background-repeat: no-repeat;
height: 200px;
background-size: cover;
width: 100%;
border-radius:7px;
background-size: contain;
background-position: center;
margin:30px 0px;
}
div#translators{
background: url(../img/translators.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: contain;
width: 100%;
border-radius:7px;
margin:15px 0px;
position:absolute;
z-index:100;
}
div#archive_org{
background: url(../img/archive.org.jpg);
height: 153px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
margin:15px 0px;
position:absolute;
z-index:100;
}
div#xrfragment{
background: url(../img/xrfragments.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#badges{
background: url(../img/badges.png);
height: 90px;
background-repeat:no-repeat;
background-size: contain;
background-position:bottom;
width: 100%;
max-width:535px;
display:inline-block;
}
div#peertube{
background: url(../img/peertube-app.webp);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
background-position:center;
width: 100%;
}
div#jml{
background: url(../img/jml.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: contain;
width: 100%;
border-radius:7px;
margin:15px 0px;
position:absolute;
z-index:100;
}
div#janusdialog{
background: url(../img/janus-script-dialog.webp);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
background-position:center;
width: 100%;
}
div#janusrss{
background: url(../img/janus-script-rss.png);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
background-position:center;
width: 100%;
}
div#janusfetch{
background: url(../img/janus-script-fetch.png);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
background-position:center;
width: 100%;
}
div#xrshthumb{
background: url(../img/xrsh-thumb.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
background-position:center;
width: 100%;
}
div#janusweb{
background: url(../img/janusweb.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#janus1{
background: url(../img/janus1.jpg);
height: 100px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
border-radius:7px;
}
div#xrflogo{
background: url(../img/xrf.svg);
height: 46px;
background-repeat:no-repeat;
background-size: cover;
width: 120px;
border-radius:7px;
}
div#hanlogo{
background: url(../img/han.jpg);
height: 46px;
background-repeat:no-repeat;
background-size: cover;
width: 88px;
border-radius:7px;
}
div#searxrlogo{
background: url(../img/searxr.jpg);
height: 23px;
background-repeat:no-repeat;
background-size: cover;
width: 100px;
border-radius:7px;
}
div#aframeverse{
height: 400px;
background: url(../img/aframe-verse.gif);
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#elfa{
height: 400px;
background: url(../img/elfa.jpg);
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#xrsh{
background: url(../img/xrsh.webp);
height: 200px;
background-repeat:no-repeat;
background-size: cover;
width: 250px;
border-radius:7px;
}
div#janusxrlogo{
background: url(../img/janusxr-logo.png);
height: 71px;
filter: brightness(0.66);
background-repeat:no-repeat;
background-size: cover;
width: 200px;
border-radius:7px;
}
div#xrforge{
background: url(../img/xrforge-thumb.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#nexus{
background: url(../img/nexus.jpg);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#lobby{
background: url(../img/lobby.png);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#biggu_s_gate{
background: url(../img/biggu.webp);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#searxr{
background: url(../img/searxr.gif);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#januswebbrowser{
background: url(../img/janusoasis.webp);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#euvalues{
background: url(../img/EUvalues.webp);
height: 400px;
background-size: cover;
width: 100%;
border-radius:7px;
margin:15px 0px;
background-position:center;
}
.spectrum{
margin-top:10px;
box-shadow: 0px 0px 5px #F0F;
margin-bottom:50px;
}
.spectrum > div,
.ruler{
margin:3px 0px;
clear:both;
background:linear-gradient(90deg, #F07, #77F, #F07);
height:2px;
}
/* sticky footer */
.footer {
position: fixed;
bottom: 0;
/* Optional: Add background, padding, etc. */
background: linear-gradient( 0deg, var(--pico-background-color) 66%, #0000);
padding: 1rem;
width:100%;
z-index: 1000; /* Ensures it stays above other content */
}
.clear{
clear:both;
}
/* telescopic text */
u {
cursor: pointer;
display: inline;
text-decoration:none;
white-space:nowrap;
font-weight:bold;
padding:0;
}
u > u,
u > span{
display: none;
}
u:focus-within > u,
u:focus-within > span {
display: inline;
}
u span{
font-weight:normal;
white-space: normal;
background:none;
}
/* underline settings */
.telescopic u:nth-child(odd)::before,
.telescopic u:nth-child(even)::before{
border-bottom:4px solid #F0F;
content:' ';
display:inline-block;
margin-right:5px;
width:23px;
height:32px;
position: absolute;
animation:fade 1000ms infinite;
-webkit-animation:fade 1000ms infinite;
}
.telescopic u:nth-child(odd)::before{
border-bottom:4px solid #77F;
}
.vertical u:focus-within > u::after,
.vertical u:focus-within > span::after {
content:' ';
display:block;
}
.show > u,
.show > span{
display:inline;
}
.telescopic u.show::before,
.telescopic u.show::after{
display:none;
}
/* bg mode */
.bg > u,
.bg u:focus-within > u {
background:#EEE;
border-radius:4px;
padding:4px;
}
.bg u.show {
background:#FFF;
}
@keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.3; }
to { opacity: 1.0; }
}
@-webkit-keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.3; }
to { opacity: 1.0; }
}
/* cards filter */
input[type="radio"] {
display:none;
}
label {
padding-bottom:10px;
cursor:pointer;
}
input[type="radio"][id="openlearning"]:checked ~ .protocol,
input[type="radio"][id="openlearning"]:checked ~ .xrdiscovery,
input[type="radio"][id="openlearning"]:checked ~ .xrbrowser,
input[type="radio"][id="openlearning"]:checked ~ .xrtranslator,
input[type="radio"][id="openlearning"]:checked ~ .worldpreservation,
input[type="radio"][id="protocol"]:checked ~ .openlearning,
input[type="radio"][id="protocol"]:checked ~ .xrdiscovery,
input[type="radio"][id="protocol"]:checked ~ .xrbrowser,
input[type="radio"][id="protocol"]:checked ~ .xrtranslator,
input[type="radio"][id="protocol"]:checked ~ .worldpreservation,
input[type="radio"][id="worldpreservation"]:checked ~ .openlearning,
input[type="radio"][id="worldpreservation"]:checked ~ .xrdiscovery,
input[type="radio"][id="worldpreservation"]:checked ~ .xrbrowser,
input[type="radio"][id="worldpreservation"]:checked ~ .xrtranslator,
input[type="radio"][id="worldpreservation"]:checked ~ .protocol,
input[type="radio"][id="xrdiscovery"]:checked ~ .openlearning,
input[type="radio"][id="xrdiscovery"]:checked ~ .protocol,
input[type="radio"][id="xrdiscovery"]:checked ~ .xrbrowser,
input[type="radio"][id="xrdiscovery"]:checked ~ .xrtranslator,
input[type="radio"][id="xrdiscovery"]:checked ~ .worldpreservation,
input[type="radio"][id="xrtranslator"]:checked ~ .openlearning,
input[type="radio"][id="xrtranslator"]:checked ~ .protocol,
input[type="radio"][id="xrtranslator"]:checked ~ .xrbrowser,
input[type="radio"][id="xrtranslator"]:checked ~ .xrdiscovery,
input[type="radio"][id="xrtranslator"]:checked ~ .worldpreservation,
input[type="radio"][id="browser"]:checked ~ .protocol,
input[type="radio"][id="browser"]:checked ~ .xrdiscovery,
input[type="radio"][id="browser"]:checked ~ .xrtranslator,
input[type="radio"][id="browser"]:checked ~ .worldpreservation,
input[type="radio"][id="browser"]:checked ~ .openlearning {
width:0;
height:0;
padding:0;
margin:0;
opacity:0;
}
.tile {
width:30%;
border: 1px solid #FFF2;
height:550px;
float:left;
overflow:hidden;
transition:all 0.3s;
margin:0 1% 1% 0;
background:#7773;
border-radius:7px;
position:relative;
}
@media screen and (max-width: 660px) {
.tile{
width:100%;
margin-bottom:30px;
}
}
.tile .description{
color:#888;
font-size:16px;
display:block;
text-decoration:none;
cursor:pointer;
padding:15px;
}
.tile .description:hover{
text-decoration:underline;
}
/* pulsating circle */
.pulsating-circle {
position: absolute;
left: 4px;
top: 20px;
transform: translateX(-50%) translateY(-50%);
width: 30px;
height: 30px;
z-index:-100;
opacity:0.3;
}
.pulsating-circle:before {
content: "";
position: relative;
display: block;
width: 300%;
height: 300%;
box-sizing: border-box;
margin-left: -100%;
margin-top: -100%;
border-radius: 45px;
background-color: #A4F;
-webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}
.pulsating-circle:after {
content: "";
position: absolute;
left: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
background-color: white;
border-radius: 15px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
-webkit-animation: pulse-dot 1.25s cubic-bezier(0.455, 0.03, 0.515, 0.955) -0.4s infinite;
animation: pulse-dot 1.25s cubic-bezier(0.455, 0.03, 0.515, 0.955) -0.4s infinite;
}
@-webkit-keyframes pulse-ring {
0% {
transform: scale(0.33);
}
80%, 100% {
opacity: 0;
}
}
@keyframes pulse-ring {
0% {
transform: scale(0.33);
}
80%, 100% {
opacity: 0;
}
}
@-webkit-keyframes pulse-dot {
0% {
transform: scale(0.8);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.8);
}
}
@keyframes pulse-dot {
0% {
transform: scale(0.8);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.8);
}
}
@-webkit-keyframes scrolly {
0% {
transform: scale(1);
}
50% {
transform: scale(10);
}
100% {
transform: scale(1);
}
}
@keyframes scrolly {
0% {
transform: scale(1);
}
50% {
transform: scale(10);
}
100% {
transform: scale(1);
}
}
@media (max-width: 600px) {
@-webkit-keyframes scrolly {
0% {
transform: scale(1);
}
50% {
transform: scale(27);
}
100% {
transform: scale(1);
}
}
@keyframes scrolly {
0% {
transform: scale(1);
}
50% {
transform: scale(27);
}
100% {
transform: scale(1);
}
}
}
/* ================ The Timeline ================ */
.timeline {
font-size:15px;
position: relative;
width: 660px;
margin: 0 auto;
margin-top: 20px;
padding: 1em 0;
list-style-type: none;
}
.timeline:before {
position: absolute;
left: 50%;
top: 0;
content: ' ';
display: block;
width: 6px;
height: 100%;
margin-left: -3px;
background: rgb(80,80,80);
background: -moz-linear-gradient(top, rgba(80,80,80,0) 0%, rgb(80,80,80) 8%, rgb(80,80,80) 92%, rgba(80,80,80,0) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(30,87,153,1)), color-stop(100%,rgba(125,185,232,1)));
background: -webkit-linear-gradient(top, rgba(80,80,80,0) 0%, rgb(80,80,80) 8%, rgb(80,80,80) 92%, rgba(80,80,80,0) 100%);
background: -o-linear-gradient(top, rgba(80,80,80,0) 0%, rgb(80,80,80) 8%, rgb(80,80,80) 92%, rgba(80,80,80,0) 100%);
background: -ms-linear-gradient(top, rgba(80,80,80,0) 0%, rgb(80,80,80) 8%, rgb(80,80,80) 92%, rgba(80,80,80,0) 100%);
background: linear-gradient(to bottom, rgba(80,80,80,0) 0%, rgb(80,80,80) 8%, rgb(80,80,80) 92%, rgba(80,80,80,0) 100%);
z-index: 5;
}
.timeline li {
padding: 0 0;
list-style: none;
text-decoration:none;
}
.timeline *,
.timeline *::after,
.timeline *::before{
box-sizing:content-box;
}
.timeline li:after {
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.direction-l {
position: relative;
width: 300px;
float: left;
text-align: right;
}
.direction-r {
position: relative;
width: 300px;
float: right;
}
.flag-wrapper {
position: relative;
display: inline-block;
text-align: center;
}
.flag {
color:#666;
position: relative;
display: inline;
background: rgb(248,248,248);
padding: 6px 10px;
border-radius: 5px;
font-weight: 600;
text-align: left;
}
.direction-l .flag {
-webkit-box-shadow: -1px 1px 1px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.15);
-moz-box-shadow: -1px 1px 1px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.15);
box-shadow: -1px 1px 1px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.15);
}
.direction-r .flag {
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.15);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.15);
box-shadow: 1px 1px 1px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.15);
}
.direction-l .flag:before,
.direction-r .flag:before {
position: absolute;
top: 50%;
right: -40px;
content: ' ';
display: block;
width: 12px;
height: 12px;
margin-top: -10px;
background: #fff;
border-radius: 10px;
border: 4px solid #77F;
z-index: 10;
}
.direction-r .flag:before {
left: -40px;
}
.direction-l .flag:after {
content: "";
position: absolute;
left: 100%;
top: 50%;
height: 0;
width: 0;
margin-top: -8px;
border: solid transparent;
border-left-color: rgb(248,248,248);
border-width: 8px;
pointer-events: none;
}
.direction-r .flag:after {
content: "";
position: absolute;
right: 100%;
top: 50%;
height: 0;
width: 0;
margin-top: -8px;
border: solid transparent;
border-right-color: rgb(248,248,248);
border-width: 8px;
pointer-events: none;
}
.time-wrapper {
display: inline;
line-height: 1em;
font-size: 0.96666em;
color: #07F;
vertical-align: middle;
}
.direction-l .time-wrapper {
float: left;
}
.direction-r .time-wrapper {
float: right;
}
.time {
display: inline-block;
padding: 4px 6px;
margin: 5px 15px;
background: rgb(248,248,248);
}
.desc {
margin: 1em 0.75em 0 0;
color:#888;
font-size: 1em;
font-style: italic;
line-height: 1.5em;
}
.direction-r .desc {
margin: 1em 0 0 0.75em;
}
/* ================ Timeline Media Queries ================ */
@media screen and (max-width: 660px) {
.timeline {
width: 100%;
padding: 4em 0 1em 0;
}
.timeline ul li {
padding: 2em 0;
}
.direction-l,
.direction-r {
float: none;
width: 100%;
text-align: center;
}
.flag-wrapper {
text-align: center;
}
.flag {
background: rgb(255,255,255);
z-index: 15;
}
.direction-l .flag:before,
.direction-r .flag:before {
position: absolute;
top: -30px;
left: 50%;
content: ' ';
display: block;
width: 12px;
height: 12px;
margin-left: -9px;
background: #fff;
border-radius: 10px;
border: 4px solid rgb(255,80,80);
z-index: 10;
}
.direction-l .flag:after,
.direction-r .flag:after {
content: "";
position: absolute;
left: 50%;
top: -8px;
height: 0;
width: 0;
margin-left: -8px;
border: solid transparent;
border-bottom-color: rgb(255,255,255);
border-width: 8px;
pointer-events: none;
}
.time-wrapper {
display: block;
position: relative;
margin: 4px 0 0 0;
z-index: 14;
}
.direction-l .time-wrapper {
float: none;
}
.direction-r .time-wrapper {
float: none;
}
.desc {
position: relative;
margin: 1em 0 0 0;
padding: 1em;
background: var(--pico-background-color);
-webkit-box-shadow: 0 0 1px rgba(0,0,0,0.20);
-moz-box-shadow: 0 0 1px rgba(0,0,0,0.20);
box-shadow: 0 0 5px #8887;
border-radius: 7px;
z-index: 15;
}
.direction-l .desc,
.direction-r .desc {
position: relative;
margin: 1em 1em 0 1em;
padding: 1em;
z-index: 15;
}
}
@media screen and (min-width: 400px ?? max-width: 660px) {
.direction-l .desc,
.direction-r .desc {
margin: 1em 4em 0 4em;
}
}
@media screen and (max-width: 660px) {
.timeline li{
margin: 57px 0px !important;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="16"
height="16"
viewBox="0 0 4.2333332 4.2333335"
version="1.1"
id="svg1468"
sodipodi:docname="codeberg-logo_icon_white.svg"
inkscape:version="1.2-alpha1 (b6a15bb, 2022-02-23)"
inkscape:export-filename="/home/robert/Documents/Codeberg/Logo-Kit/svg/Codeberg-favicon_64px.png"
inkscape:export-xdpi="384"
inkscape:export-ydpi="384"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<title
id="title16">Codeberg logo</title>
<defs
id="defs1462">
<linearGradient
xlink:href="#linearGradient6924"
id="linearGradient6918"
x1="42519.285"
y1="-7078.7891"
x2="42575.336"
y2="-6966.9307"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient6924">
<stop
style="stop-color:#2185d0;stop-opacity:0"
offset="0"
id="stop6920" />
<stop
id="stop6926"
offset="0.49517274"
style="stop-color:#2185d0;stop-opacity:0.48923996" />
<stop
style="stop-color:#2185d0;stop-opacity:0.63279623"
offset="1"
id="stop6922" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient6924-6"
id="linearGradient6918-3"
x1="42519.285"
y1="-7078.7891"
x2="42575.336"
y2="-6966.9307"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient6924-6">
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop6920-7" />
<stop
id="stop6926-5"
offset="0.49517274"
style="stop-color:#ffffff;stop-opacity:0.30000001;" />
<stop
style="stop-color:#ffffff;stop-opacity:0.30000001;"
offset="1"
id="stop6922-3" />
</linearGradient>
</defs>
<sodipodi:namedview
showborder="false"
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="2.8505242"
inkscape:cy="18.274291"
inkscape:document-units="px"
inkscape:current-layer="svg1468"
inkscape:document-rotation="0"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
units="px"
inkscape:snap-global="false"
inkscape:snap-page="true"
showguides="false"
inkscape:window-width="1531"
inkscape:window-height="873"
inkscape:window-x="69"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid2067" />
</sodipodi:namedview>
<metadata
id="metadata1465">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Codeberg logo</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Robert Martinez</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>Codeberg and the Codeberg Logo are trademarks of Codeberg e.V.</dc:title>
</cc:Agent>
</dc:rights>
<dc:date>2020-04-09</dc:date>
<dc:publisher>
<cc:Agent>
<dc:title>Codeberg e.V.</dc:title>
</cc:Agent>
</dc:publisher>
<dc:source>codeberg.org</dc:source>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="g370484"
inkscape:label="logo"
transform="matrix(0.06551432,0,0,0.06551432,-2.232417,-1.431776)">
<path
id="path6733-5"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6918-3);fill-opacity:1;stroke:none;stroke-width:3.67846;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill;stop-color:#000000;stop-opacity:1"
d="m 42519.285,-7078.7891 a 0.76086879,0.56791688 0 0 0 -0.738,0.6739 l 33.586,125.8886 a 87.182358,87.182358 0 0 0 39.381,-33.7636 l -71.565,-92.5196 a 0.76086879,0.56791688 0 0 0 -0.664,-0.2793 z"
transform="matrix(0.37058478,0,0,0.37058478,-15690.065,2662.0533)"
inkscape:label="berg" />
<path
id="path360787"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:17.0055;paint-order:markers fill stroke;stop-color:#000000"
d="m 11249.461,-1883.6961 c -12.74,0 -23.067,10.3275 -23.067,23.0671 0,4.3335 1.22,8.5795 3.522,12.2514 l 19.232,-24.8636 c 0.138,-0.1796 0.486,-0.1796 0.624,0 l 19.233,24.8646 c 2.302,-3.6721 3.523,-7.9185 3.523,-12.2524 0,-12.7396 -10.327,-23.0671 -23.067,-23.0671 z"
sodipodi:nodetypes="sccccccs"
inkscape:label="sky"
transform="matrix(1.4006354,0,0,1.4006354,-15690.065,2662.0533)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

View file

@ -82,3 +82,414 @@ article {
margin-top: 37px;
display:inline-block;
}
/*
* styling for pages in /public/*
*/
header,
main,
.footer{
font-size:1.2em;
line-height:2em;
}
small{
font-size:0.7em;
}
.footer a {
text-decoration:none !important;
}
header{
margin-bottom:50px;
background: url(/assets/backdrop.jpg);
background-repeat:no-repeat;
background-size: cover;
background-position:center;
border-radius: 10px;
text-align:center;
}
main{
margin-bottom:120px;
}
.hue-1{ filter: hue-rotate(45deg); }
.hue-2{ filter: hue-rotate(90deg); }
.hue-3{ filter: hue-rotate(135deg); }
.hue-4{ filter: hue-rotate(180deg); }
header > .spectrum,
div#logo{
width:290px;
}
div#logo{
background: url(/assets/roundel-1d688b1e.svg);
height:333px;
display:inline-block;
background-size:cover;
display: inline-block;
background-size: contain;
background-repeat: no-repeat;
margin-top: 20px;
margin-left: 20px;
width: 100%;
background-position: center;
}
div#xrhf{
background: url(/assets/xrh-full.svg);
height: 33px;
width:78px;
background-repeat:no-repeat;
background-size: contain;
background-position:top;
display:inline-block;
}
div#hint{
float:right;
background: url(/assets/blinkhint.svg);
height: 129px;
background-size: cover;
display:inline-block;
width: 200px;
}
div#badges{
background: url(/assets/badges.png);
height: 90px;
background-repeat:no-repeat;
background-size: contain;
background-position:bottom;
width: 100%;
max-width:677px;
display:inline-block;
}
div#xrecosystem{
background: #000 url(/assets/xrecosystem.png);
background-repeat: no-repeat;
height: 200px;
background-size: cover;
width: 100%;
border-radius:7px;
background-size: contain;
background-position: center;
margin:30px 0px;
}
div#xrflogo{
background: url(/assets/xrf.svg);
height: 46px;
background-repeat:no-repeat;
background-size: cover;
width: 120px;
border-radius:7px;
}
div#janusxrlogo{
background: url(/assets/janusxr-logo.png);
height: 71px;
filter: brightness(0.66);
background-repeat:no-repeat;
background-size: cover;
width: 200px;
border-radius:7px;
}
div#januswebbrowser{
background: url(/assets/janusoasis.webp);
height: 400px;
background-repeat:no-repeat;
background-size: cover;
width: 100%;
}
div#euvalues{
background: url(/assets/EUvalues.webp);
height: 400px;
background-size: cover;
width: 100%;
border-radius:7px;
margin:15px 0px;
background-position:center;
}
.spectrum{
margin-top:10px;
box-shadow: 0px 0px 5px #F0F;
margin-bottom:50px;
}
.spectrum > div,
.ruler{
margin:3px 0px;
clear:both;
background:linear-gradient(90deg, #F07, #77F, #F07);
height:2px;
}
/* sticky footer */
.footer {
position: fixed;
bottom: 0;
/* Optional: Add background, padding, etc. */
background: linear-gradient( 0deg, var(--bs-body-bg) 66%, #0000);
padding: 1rem;
width:100%;
z-index: 1000; /* Ensures it stays above other content */
}
.clear{
clear:both;
}
/* telescopic text */
u {
cursor: pointer;
display: inline;
text-decoration:none;
white-space:nowrap;
font-weight:bold;
padding:0;
}
u > u,
u > span{
display: none;
}
u:focus-within > u,
u:focus-within > span {
display: inline;
}
u span{
font-weight:normal;
white-space: normal;
background:none;
}
/* underline settings */
.telescopic u:nth-child(odd)::before,
.telescopic u:nth-child(even)::before{
border-bottom:4px solid #F0F;
content:' ';
display:inline-block;
margin-right:5px;
width:23px;
height:32px;
position: absolute;
animation:fade 1000ms infinite;
-webkit-animation:fade 1000ms infinite;
}
.telescopic u:nth-child(odd)::before{
border-bottom:4px solid #77F;
}
.vertical u:focus-within > u::after,
.vertical u:focus-within > span::after {
content:' ';
display:block;
}
.show > u,
.show > span{
display:inline;
}
.telescopic u.show::before,
.telescopic u.show::after{
display:none;
}
/* bg mode */
.bg > u,
.bg u:focus-within > u {
background:#EEE;
border-radius:4px;
padding:4px;
}
.bg u.show {
background:#FFF;
}
@keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.3; }
to { opacity: 1.0; }
}
@-webkit-keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.3; }
to { opacity: 1.0; }
}
/* cards filter */
input[type="radio"] {
display:none;
}
label {
padding-bottom:10px;
cursor:pointer;
}
input[type="radio"][id="openlearning"]:checked ~ .protocol,
input[type="radio"][id="openlearning"]:checked ~ .xrdiscovery,
input[type="radio"][id="openlearning"]:checked ~ .xrbrowser,
input[type="radio"][id="openlearning"]:checked ~ .xrtranslator,
input[type="radio"][id="openlearning"]:checked ~ .worldpreservation,
input[type="radio"][id="protocol"]:checked ~ .openlearning,
input[type="radio"][id="protocol"]:checked ~ .xrdiscovery,
input[type="radio"][id="protocol"]:checked ~ .xrbrowser,
input[type="radio"][id="protocol"]:checked ~ .xrtranslator,
input[type="radio"][id="protocol"]:checked ~ .worldpreservation,
input[type="radio"][id="worldpreservation"]:checked ~ .openlearning,
input[type="radio"][id="worldpreservation"]:checked ~ .xrdiscovery,
input[type="radio"][id="worldpreservation"]:checked ~ .xrbrowser,
input[type="radio"][id="worldpreservation"]:checked ~ .xrtranslator,
input[type="radio"][id="worldpreservation"]:checked ~ .protocol,
input[type="radio"][id="xrdiscovery"]:checked ~ .openlearning,
input[type="radio"][id="xrdiscovery"]:checked ~ .protocol,
input[type="radio"][id="xrdiscovery"]:checked ~ .xrbrowser,
input[type="radio"][id="xrdiscovery"]:checked ~ .xrtranslator,
input[type="radio"][id="xrdiscovery"]:checked ~ .worldpreservation,
input[type="radio"][id="xrtranslator"]:checked ~ .openlearning,
input[type="radio"][id="xrtranslator"]:checked ~ .protocol,
input[type="radio"][id="xrtranslator"]:checked ~ .xrbrowser,
input[type="radio"][id="xrtranslator"]:checked ~ .xrdiscovery,
input[type="radio"][id="xrtranslator"]:checked ~ .worldpreservation,
input[type="radio"][id="browser"]:checked ~ .protocol,
input[type="radio"][id="browser"]:checked ~ .xrdiscovery,
input[type="radio"][id="browser"]:checked ~ .xrtranslator,
input[type="radio"][id="browser"]:checked ~ .worldpreservation,
input[type="radio"][id="browser"]:checked ~ .openlearning {
width:0;
height:0;
padding:0;
margin:0;
opacity:0;
}
.tile {
width:30%;
border: 1px solid #FFF2;
height:550px;
float:left;
overflow:hidden;
transition:all 0.3s;
margin:0 1% 1% 0;
background:#7773;
border-radius:7px;
position:relative;
}
@media screen and (max-width: 660px) {
.tile{
width:100%;
margin-bottom:30px;
}
}
.tile .description{
color:#888;
font-size:16px;
display:block;
text-decoration:none;
cursor:pointer;
padding:15px;
}
.tile .description:hover{
text-decoration:underline;
}
/* pulsating circle */
.pulsating-circle {
position: absolute;
left: 4px;
top: 20px;
transform: translateX(-50%) translateY(-50%);
width: 30px;
height: 30px;
z-index:-100;
opacity:0.3;
}
.pulsating-circle:before {
content: "";
position: relative;
display: block;
width: 300%;
height: 300%;
box-sizing: border-box;
margin-left: -100%;
margin-top: -100%;
border-radius: 45px;
background-color: #A4F;
-webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}
.pulsating-circle:after {
content: "";
position: absolute;
left: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
background-color: white;
border-radius: 15px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
-webkit-animation: pulse-dot 1.25s cubic-bezier(0.455, 0.03, 0.515, 0.955) -0.4s infinite;
animation: pulse-dot 1.25s cubic-bezier(0.455, 0.03, 0.515, 0.955) -0.4s infinite;
}
@-webkit-keyframes pulse-ring {
0% {
transform: scale(0.33);
}
80%, 100% {
opacity: 0;
}
}
@keyframes pulse-ring {
0% {
transform: scale(0.33);
}
80%, 100% {
opacity: 0;
}
}
@-webkit-keyframes pulse-dot {
0% {
transform: scale(0.8);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.8);
}
}
@keyframes pulse-dot {
0% {
transform: scale(0.8);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.8);
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 117 KiB

View file

@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="113.57502mm"
height="43.909458mm"
version="1.1"
viewBox="0 0 113.57502 43.90946"
xml:space="preserve"
id="svg29"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs17"><linearGradient
id="linearGradient19"><stop
style="stop-color:#53daff;stop-opacity:1;"
offset="0"
id="stop18" /><stop
style="stop-color:#52f7ff;stop-opacity:1;"
offset="1"
id="stop19" /></linearGradient><linearGradient
id="linearGradient17"><stop
style="stop-color:#c753ff;stop-opacity:1;"
offset="0"
id="stop16" /><stop
style="stop-color:#e653ff;stop-opacity:1;"
offset="1"
id="stop17" /></linearGradient><linearGradient
id="linearGradient15"><stop
style="stop-color:#298cff;stop-opacity:1;"
offset="0"
id="stop14" /><stop
style="stop-color:#ff79f7;stop-opacity:1;"
offset="1"
id="stop15" /></linearGradient><linearGradient
id="linearGradient12"><stop
style="stop-color:#29bbff;stop-opacity:1;"
offset="0"
id="stop12" /><stop
style="stop-color:#0cd9ff;stop-opacity:0;"
offset="1"
id="stop13" /></linearGradient><linearGradient
id="linearGradient9"><stop
style="stop-color:#ff3cf9;stop-opacity:1;"
offset="0"
id="stop9" /><stop
style="stop-color:#00f8f8;stop-opacity:1;"
offset="1"
id="stop8" /></linearGradient><linearGradient
id="linearGradient3"><stop
style="stop-color:#ff3cf9;stop-opacity:1;"
offset="0"
id="stop7" /><stop
style="stop-color:#00f8f8;stop-opacity:1;"
offset="1"
id="stop6" /></linearGradient><linearGradient
id="linearGradient1"><stop
style="stop-color:#003ad1;stop-opacity:1;"
offset="0"
id="stop1" /><stop
style="stop-color:#eb04bf;stop-opacity:1;"
offset="0.5"
id="stop5" /><stop
style="stop-color:#22a2af;stop-opacity:1;"
offset="1"
id="stop2" /></linearGradient><rect
x="429.14212"
y="58.686104"
width="1093.0287"
height="187.06195"
id="rect29" /><linearGradient
id="linearGradient8637"
x1="154.78"
x2="273.13"
y1="24.048"
y2="24.048"
gradientUnits="userSpaceOnUse"><stop
stop-color="#276fff"
offset="0"
id="stop3" /><stop
stop-color="#ff16bc"
offset="1"
id="stop4" /></linearGradient><linearGradient
xlink:href="#linearGradient1"
id="linearGradient2"
x1="425.34225"
y1="127.16445"
x2="1181.6075"
y2="127.16445"
gradientUnits="userSpaceOnUse" /><linearGradient
xlink:href="#linearGradient3"
id="linearGradient7"
x1="121.41179"
y1="86.926689"
x2="171.91747"
y2="86.926689"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0076142,0,0,1.0454544,-0.92445533,-4.0153177)" /><linearGradient
xlink:href="#linearGradient9"
id="linearGradient8"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0076142,0,0,0.27272726,-0.98880088,58.794164)"
x1="121.41179"
y1="86.926689"
x2="171.91747"
y2="86.926689" /><linearGradient
xlink:href="#linearGradient9"
id="linearGradient10"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0025381,0,0,0.09090907,-0.21968892,69.915444)"
x1="121.41179"
y1="86.926689"
x2="171.91747"
y2="86.926689" /><linearGradient
xlink:href="#linearGradient9"
id="linearGradient11"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0076142,0,0,0.13636362,-0.79494564,67.591196)"
x1="121.41179"
y1="86.926689"
x2="171.91747"
y2="86.926689" /><linearGradient
xlink:href="#linearGradient12"
id="linearGradient13"
x1="151.02299"
y1="83.016991"
x2="159.7397"
y2="83.016991"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.132353,0,0,1,-21.142036,4.5394395e-7)" /><linearGradient
xlink:href="#linearGradient15"
id="linearGradient14"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1.132353,0,0,1.0493827,315.49058,-4.1582868)"
x1="151.02299"
y1="83.016991"
x2="159.7397"
y2="83.016991" /><linearGradient
xlink:href="#linearGradient17"
id="linearGradient16"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1.132353,0,0,1.0493827,302.62006,-4.8206892)"
x1="151.02299"
y1="83.016991"
x2="159.7397"
y2="83.016991" /><linearGradient
xlink:href="#linearGradient19"
id="linearGradient18"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.132353,0,0,1.0493827,-7.1348208,-4.3306826)"
x1="151.02299"
y1="83.016991"
x2="159.7397"
y2="83.016991" /></defs><g
transform="translate(-58.856519,-44.496792)"
id="g29"><g
transform="matrix(2.7826,0,0,3.2096,58.857,52.964672)"
filter="url(#filter12743)"
id="g28"
style="display:inline" /><g
transform="matrix(2.7825999,0,0,3.2096001,-73.783976,-5.2700571)"
id="g27"
style="display:inline"><g
transform="scale(0.26458)"
fill="#f7f7f7"
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;display:inline"
aria-label="SEARXR"
id="g26"><path
d="m 158.52,0.12891 c -1.1293,0.010438 -2.3334,0.038083 -3.5879,0.09375 -0.30457,-0.134 -0.0547,13.736 -0.0547,13.736 2.819,0.06348 6.7944,-0.31507 8.3398,1.041 3.9748,3.094 3.1915,2.418 5.7773,5.0039 2.5859,2.5859 5.236,5.1719 7.9512,7.7578 l -21.293,18.782 c -1.2934,1.293 -2.4553,1.5706 8.4254,1.3029 9.5932,-0.08935 8.1924,0.72076 10.737,-1.1372 7.8396,-6.1216 9.6129,-7.4704 12.328,-10.185 3.0599,2.4348 5.7548,4.0928 10.435,7.2182 0,0 4.5675,2.327 9.0355,3.4666 5.1614,0.86971 19.065,0.8565 19.629,0.65998 h 4.7207 c 0,0 0.0977,-8.958 0.16992,-16.066 0.12771,-10.91 2.172,-13.092 4.7578,-15.807 2.7151,-2.7151 6.0119,-2.0723 9.8906,-2.0723 l 59.02898,0.136307 V 0.28984634 L 245.78162,0.15354 c -7.62788,-0.0176139 -14.158,2.7143 -19.588,8.1445 -5.3009,5.3009 -7.9512,11.767 -7.9512,19.395 v 9.0977 c -2.0502,0.03977 -4.1264,0.0029 -5.9297,-0.16016 -1.858,-0.1679 -4.6841,-1.3207 -8.3076,-3.0888 0,0 -4.8858,-3.0652 -7.4717,-5.7803 l 15.003,-15.778 c 1.2599,-1.325 3.9009,-4.6189 8.5281,-9.5835 1.6357,-1.7549 0.84973,-2.3113 -4.041,-2.1953 -2.4125,0.00862 -6.6915,0.017578 -8.6309,0.017578 -1.8101,0 -3.4255,0.71063 -4.8477,2.1328 l -15.709,15.709 c -2.7151,-2.5859 -5.3654,-5.1719 -7.9512,-7.7578 l -7.9512,-7.9512 c -1.4222,-1.4222 -3.0395,-2.1328 -4.8496,-2.1328 -1.4545,0 -4.1766,-0.12506 -7.5644,-0.09375 z"
fill-opacity="0.99608"
stroke="url(#linearGradient8637)"
stroke-width="3.7795"
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;display:inline;fill:#ffffff;fill-opacity:1;stroke:url(#linearGradient8637)"
id="path25"
transform="translate(27.273,60.371)" /></g></g><path
style="fill:url(#linearGradient13);stroke-width:0.988572;paint-order:markers stroke fill"
d="m 149.86931,77.825413 9.87039,10.383149 -3.19336,-0.128188 z"
id="path12" /><path
style="fill:url(#linearGradient14);stroke-width:1.01269;paint-order:markers stroke fill"
d="m 144.47923,77.510356 -9.87039,10.895897 3.19336,-0.134519 z"
id="path12-2" /><text
xml:space="preserve"
transform="matrix(0.05313799,0,0,0.05313799,104.086,62.583943)"
id="text29"
style="font-weight:600;font-size:133.333px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Semi-Bold';text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect29);display:none;opacity:1;fill:#8e8e8e;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2);stroke-width:9.48474;stroke-linejoin:miter;stroke-dasharray:none;paint-order:stroke markers fill"><tspan
x="429.14258"
y="181.23104"
id="tspan3"><tspan
style="font-weight:900;-inkscape-font-specification:'Montserrat Heavy';fill:none"
id="tspan1">federation</tspan></tspan></text><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444px;font-family:'MxPlus ToshibaSat 9x14';-inkscape-font-specification:'MxPlus ToshibaSat 9x14';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:none;fill-opacity:1;stroke:#54438e;stroke-width:0.504;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
x="178.69518"
y="61.019711"
id="text5"><tspan
id="tspan5"
style="stroke-width:0.504"
x="178.69518"
y="61.019711" /></text><path
style="fill:#818181;fill-opacity:1;stroke:none;stroke-width:0.342798;stroke-dasharray:none;stroke-opacity:1"
d="m 163.50345,74.673891 c -0.65149,-0.129167 -0.94963,-0.267244 -1.31816,-0.610486 -0.40637,-0.378499 -0.54495,-0.90499 -0.38393,-1.458847 0.15793,-0.543256 0.68179,-0.964899 1.46326,-1.1777 0.45885,-0.124953 1.57628,-0.126818 2.08376,-0.0034 0.67889,0.164988 1.19199,0.509495 1.43622,0.96428 0.16204,0.301766 0.16214,0.971773 1.8e-4,1.273869 -0.23913,0.44603 -0.72716,0.783984 -1.38342,0.957939 -0.43754,0.115976 -1.44213,0.144791 -1.89791,0.05443 z m 1.69855,-0.696146 c 0.56669,-0.147603 0.8752,-0.485371 0.87553,-0.958577 3.3e-4,-0.434413 -0.30155,-0.780338 -0.81725,-0.936456 -0.28645,-0.08672 -1.58178,-0.08672 -1.86824,0 -0.50997,0.154393 -0.81745,0.502622 -0.81745,0.925823 0,0.498108 0.33339,0.850197 0.94043,0.993131 0.34056,0.08021 1.34175,0.06601 1.68698,-0.02393 z m -43.44423,-0.979697 v -1.698489 h 2.38847 2.38853 v 0.371543 0.371547 h -1.99043 -1.99041 v 0.318466 0.318465 h 1.85771 1.85774 v 0.371546 0.371546 h -1.85774 -1.85771 v 0.636932 0.636937 h -0.39809 -0.39807 z m 5.41392,0 v -1.698489 h 2.36198 2.36195 v 0.345006 0.345003 h -1.96388 -1.96389 v 0.318468 0.31847 h 1.88427 1.88425 v 0.345003 0.345007 h -1.88425 -1.88427 v 0.345007 0.345004 h 1.96389 1.96388 v 0.345006 0.345008 h -2.36195 -2.36198 z m 5.57318,0.001 v -1.705682 l 1.89754,0.01633 1.89753,0.01633 0.29758,0.139551 c 0.29556,0.138587 0.47097,0.318988 0.66427,0.683154 0.08,0.15105 0.0986,0.30482 0.0991,0.822705 4.9e-4,0.589358 -0.009,0.659336 -0.14673,0.936831 -0.083,0.168944 -0.23149,0.364129 -0.34011,0.44699 -0.39196,0.298954 -0.46854,0.309075 -2.49823,0.330119 l -1.87101,0.01941 z m 3.69294,0.85372 c 0.28847,-0.131017 0.40968,-0.385741 0.40968,-0.861002 0,-0.450736 -0.12671,-0.713807 -0.41715,-0.866169 -0.19179,-0.100616 -0.31843,-0.111104 -1.54909,-0.128149 l -1.34023,-0.01856 v 0.987237 0.987235 l 1.34023,-0.0012 c 1.18944,-9.99e-4 1.36455,-0.01228 1.55656,-0.09941 z m 1.93329,-0.854812 v -1.698447 h 2.36198 2.36196 v 0.345008 0.345005 h -1.99041 -1.99043 v 0.318468 0.318466 h 1.91081 1.91081 v 0.345004 0.345007 h -1.91081 -1.91081 v 0.345006 0.345006 h 1.99043 1.99041 v 0.345006 0.345006 h -2.36196 -2.36198 z m 5.52011,-0.0028 v -1.70142 l 2.05677,0.01613 c 2.28294,0.0179 2.22103,0.0086 2.55022,0.383519 0.2585,0.294417 0.34012,0.72711 0.21927,1.16236 -0.0725,0.260873 -0.37675,0.597138 -0.61006,0.674144 -0.10019,0.03309 -0.18229,0.07272 -0.18229,0.08807 0,0.02271 0.40288,0.526781 0.78779,0.985602 0.0733,0.08729 0.0504,0.09288 -0.37874,0.09288 h -0.45666 l -0.40878,-0.530775 -0.40876,-0.53078 h -1.1863 -1.1863 v 0.53078 0.530775 h -0.39808 -0.39808 z m 3.96904,-0.160216 c 0.29816,-0.103934 0.32303,-0.599872 0.0366,-0.730363 -0.0938,-0.04266 -0.61445,-0.06195 -1.6727,-0.06195 h -1.53679 v 0.424624 0.424624 h 1.50479 c 0.93414,0 1.56673,-0.02159 1.66809,-0.05693 z m 1.65719,0.163084 v -1.698492 h 2.28236 2.28236 v 1.698492 1.698489 h -0.37153 -0.37156 v -0.557324 -0.557316 h -1.53927 -1.53924 v 0.557316 0.557317 h -0.37156 -0.37156 z m 3.81043,-0.570588 -0.0154,-0.464431 h -1.51271 -1.51271 l -0.0154,0.464431 -0.0154,0.46443 h 1.54338 1.54339 z m 3.39046,2.233692 c -0.0194,-0.01948 -0.0353,-0.616587 -0.0353,-1.326946 V 72.04258 h -0.98196 -0.98191 v -0.371546 -0.371546 h 2.41502 2.41504 v 0.371546 0.371546 h -0.98194 -0.98194 v 1.326944 1.326945 h -0.41577 c -0.22867,0 -0.43171,-0.01593 -0.45118,-0.0354 z m 3.52083,-1.660872 v -1.700724 h 0.4254 0.42536 l -0.0139,1.685221 -0.014,1.685223 -0.41136,0.0155 -0.41134,0.0155 z M 167.617,72.998 v -1.698492 h 0.47708 0.47707 l 1.36735,1.214685 1.3674,1.214683 0.0143,-1.214683 0.0143,-1.214685 h 0.42366 0.42362 V 72.998 74.69649 h -0.46704 -0.46707 l -1.37738,-1.223174 -1.37743,-1.223174 -0.0143,1.223174 -0.0143,1.223174 h -0.42363 -0.42366 z"
id="path5" /><rect
style="fill:url(#linearGradient7);stroke-width:0.953489;paint-order:markers stroke fill"
id="rect1"
width="50.89024"
height="2.9483016"
x="121.41179"
y="85.388451" /><rect
style="fill:url(#linearGradient8);stroke-width:0.486998;paint-order:markers stroke fill"
id="rect1-3"
width="50.89024"
height="0.76912206"
x="121.34745"
y="82.116882" /><rect
style="fill:url(#linearGradient10);stroke-width:0.28046;paint-order:markers stroke fill"
id="rect1-3-1"
width="50.633865"
height="0.25637397"
x="121.50026"
y="77.689682" /><rect
style="fill:url(#linearGradient11);stroke-width:0.34436;paint-order:markers stroke fill"
id="rect1-3-1-3"
width="50.89024"
height="0.384561"
x="121.5413"
y="79.252556" /><path
style="fill:url(#linearGradient16);stroke-width:1.01269;paint-order:markers stroke fill"
d="m 136.35163,77.87345 -14.7415,8.075783 0.75781,1.660099 z"
id="path12-2-5" /><path
style="fill:url(#linearGradient18);stroke-width:1.01269;paint-order:markers stroke fill"
d="m 158.49271,77.850708 13.45963,8.075783 0.1395,1.916473 z"
id="path12-2-5-9" /></g><path
style="fill:#808080;fill-opacity:1;stroke-width:0.5;stroke-dasharray:none"
d="m 63.006633,21.639473 v -1.621936 h 0.372844 0.372845 l 0.01393,0.661252 0.01393,0.661249 h 1.522126 1.522123 l 0.01393,-0.661249 0.01393,-0.661252 h 0.372843 0.372846 v 1.621936 1.621936 h -0.374299 -0.374293 v -0.623821 -0.623821 h -1.547077 -1.547075 v 0.623821 0.623821 h -0.374302 -0.374293 z m 7.036705,0.954941 V 21.92742 l -1.010589,-0.913735 c -0.555826,-0.502554 -1.031926,-0.932278 -1.058003,-0.954942 -0.02607,-0.02267 0.213139,-0.04121 0.531585,-0.04121 h 0.578997 l 0.516436,0.483696 c 0.284038,0.266032 0.599431,0.56135 0.700872,0.65626 l 0.18444,0.172561 0.694306,-0.656258 0.694311,-0.656259 h 0.556238 0.55624 l -1.046068,0.960684 -1.046072,0.960687 -0.002,0.661249 -0.002,0.661252 h -0.424378 -0.424199 z m 3.293778,-0.954941 v -1.621936 h 1.79415 c 1.116205,0 1.890852,0.02073 2.050069,0.05488 0.489799,0.105044 0.794821,0.514897 0.794821,1.067993 0,0.492998 -0.202384,0.820418 -0.62231,1.006785 -0.172896,0.07672 -0.399864,0.09067 -1.733544,0.106525 l -1.534601,0.01824 v 0.494726 0.494727 h -0.374292 -0.374293 z m 3.882235,-0.190133 c 0.202334,-0.183249 0.15767,-0.598766 -0.07383,-0.68678 -0.06704,-0.02548 -0.782923,-0.04634 -1.590858,-0.04634 h -1.46897 v 0.426269 0.42627 l 1.516961,-0.01456 c 1.381681,-0.01325 1.525856,-0.02261 1.616689,-0.104875 z m 1.407769,0.190133 v -1.621936 h 2.245759 2.245756 v 0.324387 0.324389 H 81.222219 79.3258 v 0.324386 0.324388 h 1.821559 1.821561 v 0.324386 0.324387 H 81.147359 79.3258 v 0.324388 0.324387 h 1.896419 1.896416 v 0.324388 0.324386 H 80.872879 78.62712 Z m 5.290008,-0.0031 v -1.625055 l 1.962816,0.01561 1.962819,0.01561 0.241635,0.149719 c 0.364119,0.225608 0.485737,0.487551 0.465144,1.00183 -0.02027,0.506376 -0.15667,0.744052 -0.535249,0.932705 l -0.251333,0.125245 0.371495,0.457546 c 0.204323,0.251647 0.384612,0.478769 0.400645,0.504709 0.01744,0.02821 -0.141616,0.04716 -0.395672,0.04716 h -0.424819 l -0.388805,-0.499126 -0.388805,-0.499057 h -1.135644 -1.135641 v 0.499057 0.499056 h -0.374295 -0.374291 z m 3.848457,-0.1383 c 0.09282,-0.0446 0.193905,-0.243837 0.193905,-0.382137 0,-0.05207 -0.05418,-0.157691 -0.120396,-0.234704 L 87.718719,20.741215 H 86.204695 84.69067 l -0.01493,0.344388 c -0.0083,0.189413 -0.0028,0.376191 0.01214,0.41506 0.02276,0.0593 0.265854,0.06789 1.5121,0.05341 0.816738,-0.0095 1.521239,-0.03469 1.565557,-0.05599 z m 1.541359,0.141444 v -1.621979 l 0.486582,0.0017 0.48658,0.0017 0.916984,1.245982 c 0.504344,0.685289 0.931039,1.244853 0.948211,1.243474 0.01717,-0.0014 0.443594,-0.562818 0.9476,-1.247643 l 0.91638,-1.245111 h 0.468505 0.468504 v 1.621926 1.621936 h -0.4242 -0.424196 v -0.948274 c 0,-0.521514 -0.01684,-0.947327 -0.03743,-0.94625 -0.02058,0.001 -0.351833,0.426889 -0.736109,0.94625 l -0.698679,0.944293 -0.48096,0.0019 -0.480959,0.0019 -0.716778,-0.957465 -0.716778,-0.957462 -0.01354,0.957462 -0.01353,0.957465 h -0.448077 -0.448072 z m 6.837085,0 v -1.621979 h 2.245756 2.245755 v 0.323786 0.323787 l -1.883939,0.01308 -1.88394,0.01308 v 0.299436 0.299433 l 1.809083,0.0131 1.809076,0.01309 v 0.323765 0.323765 h -1.821553 -1.82156 v 0.324386 0.324388 h 1.896417 1.896416 v 0.324389 0.324386 h -2.245755 -2.245756 z m 5.290001,-0.0032 v -1.625251 l 1.834,0.01579 c 1.8108,0.01559 1.83739,0.01729 2.09822,0.135154 0.31998,0.144582 0.57516,0.429253 0.69339,0.77348 0.10376,0.301938 0.11662,1.043036 0.0239,1.363287 -0.0732,0.252205 -0.32612,0.596392 -0.54864,0.746371 -0.28101,0.189359 -0.57873,0.216413 -2.38153,0.216413 h -1.71927 z m 3.63346,0.826754 c 0.23346,-0.151816 0.33409,-0.392935 0.33321,-0.798492 -9.9e-4,-0.484294 -0.10418,-0.705975 -0.39388,-0.846191 -0.1955,-0.09463 -0.30351,-0.102014 -1.49254,-0.102014 h -1.28176 v 0.92619 0.926188 l 1.35989,-0.01541 c 1.10521,-0.01253 1.3815,-0.02944 1.47508,-0.09026 z m 1.85615,-0.823445 v -1.621938 h 0.4242 0.42419 v 1.621935 1.621936 h -0.42419 -0.4242 z m 1.99621,0 v -1.621938 h 1.99623 2.34129 v 1.621935 1.621936 h -0.51973 -0.17466 v -0.524157 -0.524014 h -1.47222 -1.47223 v 0.524014 0.524009 h -0.34933 -0.34935 z m 3.64313,-0.524008 v -0.449212 h -1.47222 -1.47223 v 0.449153 0.449151 h 1.47223 1.47222 z"
id="path2" /></svg>

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View file

@ -56,8 +56,8 @@
echo ""
echo "Development:"
echo ""
echo "" $ cd xrforge-webxr && bun run build && cp dist/xrforge.html ../manyfold/usr/src/app/public/view/index.html
echo "" $ manyfold/cli/manyfold.sh run -e DEV=1 -v ./manyfold/usr/src/app/public/view:/usr/src/app/public/view
echo " $ cd xrforge-webxr && bun run build && cp dist/xrforge.html ../manyfold/usr/src/app/public/view/index.html"
echo " $ manyfold/cli/manyfold.sh run -e DEV=1 -v ./manyfold/usr/src/app/public/view:/usr/src/app/public/view"
echo ""
'';