feat: add matrix page

This commit is contained in:
Youwen Wu 2025-06-11 22:59:57 -07:00
parent d44cd0c39c
commit 0d8e1a7d47
Signed by: youwen
GPG key ID: 865658ED1FE61EC3
8 changed files with 463 additions and 2 deletions

View file

@ -1 +0,0 @@
{"m.server":{"base_url":"https://matrix.functor.systems.com"},"m.homeserver":{"base_url":"https://matrix.functor.system"},"org.matrix.msc3575.proxy":{"url":"https://matrix.functor.systems"}}

View file

@ -1 +0,0 @@
{"m.server":"matrix.functor.systems:443"}

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/leaves.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

194
public/matrix.html Normal file
View file

@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>functor.systems >> Matrix</title>
<meta name="description" content="a matrix homeserver for functor.systems members">
<meta name="author" content="Youwen Wu <youwen@functor.systems>">
<meta property="og:title" content="functor.systems >> Home">
<meta property="og:type" content="website">
<meta property="og:url" content="https://functor.systems/matrix">
<meta property="og:description" content="a matrix homeserver for functor.systems members">
<link rel="stylesheet" href="/sunlit.css">
<!-- <link rel="icon" href="/favicon.ico"> -->
<!-- <link rel="icon" href="/favicon.svg" type="image/svg+xml"> -->
<!-- <link rel="apple-touch-icon" href="/apple-touch-icon.png"> -->
<style>
@font-face {
font-family: "Redaction";
font-style: normal;
font-display: swap;
font-weight: regular;
src: url("/fonts/redaction.woff2") format("woff2");
}
@font-face {
font-family: "Redaction";
font-style: italic;
font-display: swap;
font-weight: regular;
src: url("/fonts/redaction-italic.woff2") format("woff2");
}
@font-face {
font-family: "Redaction 20";
font-style: italic;
font-display: swap;
font-weight: regular;
src: url("/fonts/redaction-20-italic.woff2") format("woff2");
}
body.dark #lightswitch {
color: #fff;
}
#lightswitch:hover {
text-decoration: underline;
}
.hover-link {
text-decoration: none;
}
.hover-link:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="dappled-light">
<div id="glow"></div>
<div id="glow-bounce"></div>
<div class="perspective">
<div id="leaves">
<svg style="width: 0; height: 0; position: absolute;">
<defs>
<filter id="wind" x="-20%" y="-20%" width="140%" height="140%">
<feTurbulence type="fractalNoise" numOctaves="2" seed="1">
<animate attributeName="baseFrequency" dur="16s" keyTimes="0;0.33;0.66;1"
values="0.005 0.003;0.01 0.009;0.008 0.004;0.005 0.003" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap in="SourceGraphic">
<animate attributeName="scale" dur="20s" keyTimes="0;0.25;0.5;0.75;1" values="45;55;75;55;45"
repeatCount="indefinite" />
</feDisplacementMap>
</filter>
</defs>
</svg>
</div>
<div id="blinds">
<div class="shutters">
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
<div class="shutter"></div>
</div>
<div class="vertical">
<div class="bar"></div>
<div class="bar"></div>
</div>
</div>
</div>
<div id="progressive-blur">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<article style="font-family: 'Redaction';">
<h1 style="font-family: 'Redaction 20'; font-style: italic; font-size: 3.8rem;">matrix.functor.systems</h1>
<p style="font-size: 1.5rem;">
A <a href="https://matrix.org">matrix</a> homeserver operated by <a href="/">functor.systems</a>.
</p>
<p style="font-size: 1.5rem; margin-top: 1em; margin-bottom: 1em;">
Matrix is an open, federated, and end-to-end encrypted messaging protocol.
<span style="font-style: italic;">matrix.functor.systems</span> is our very
own homeserver, running the <a
href="https://github.com/matrix-construct/tuwunel">tuwunel</a> Matrix
server implementation.
</p>
<p style="font-size: 1.5rem; margin-top: 1em; margin-bottom: 1em;">
Registration is currently restricted to friends of the functor.systems
community. However, you can make an account on any other Matrix homeserver,
and interact with any account on matrix.functor.systems without any
downside. This is what is meant when we say Matrix is <em>federated</em>.
The official <a href="https://element.io/">matrix.org</a> free public homeserver is
a good place to make your first account.
</p>
<button
id="lightswitch"
style="
border: 1px solid #ccc;
border-radius: 4px;
cursor: pointer;
font-size: 1.2rem;
background: none;
border: none;
padding: 0px 0px 0px 0px;
font-family: 'Redaction';
"
></button>
<a style="font-size: 1.2rem; margin-left: 20px;" class="hover-link" href="https://matrix.to/#/#vect:functor.systems">[register for an account]</a>
<a style="font-size: 1.2rem; margin-left: 20px;" class="hover-link" href="/">[functor.systems]</a>
</article>
<script>
function toggle() {
document.body.classList.add('animation-ready');
document.body.classList.toggle('dark');
}
document.addEventListener('keydown', function(event) {
if (event.keyCode === 32) {
toggle();
}
});
const darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
const btn = document.getElementById('lightswitch');
const applyTheme = isDark => {
toggle();
btn.textContent = isDark
? '[lights on]'
: '[lights out]';
};
applyTheme(darkQuery.matches);
darkQuery.addEventListener('change', e => {
applyTheme(e.matches);
});
btn.addEventListener('click', () => {
const isCurrentlyDark = document.body.classList.contains('dark');
applyTheme(!isCurrentlyDark);
});
</script>
</body>
</html>

269
public/sunlit.css Normal file
View file

@ -0,0 +1,269 @@
article {
margin: 0 auto;
max-width: 800px;
padding: 25vh 12px;
color: var(--dark);
isolation: isolate;
}
article a {
color: var(--dark);
}
body {
--day: #fffdfa;
--evening: #fccc83;
--dusk: #db7a2a;
--night: #0f131c;
--dawn: #16132b;
--morning: #9fb3bf;
--light: var(--day);
--dark: var(--night);
--shadow: #1a1917;
--bounce-light: #f5d7a6;
--timing-fn: cubic-bezier(0.455, 0.190, 0.000, 0.985);
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background-color: var(--light);
animation-duration: 0s;
animation-fill-mode: forwards;
animation-timing-function: linear;
}
body.animation-ready {
animation-play-state: running;
animation-duration: 1s;
animation-name: sunrise;
}
body.animation-ready.dark {
animation-duration: 1.7s;
animation-name: sunset;
}
body.dark {
--light: var(--night);
--dark: var(--day);
--shadow: #030307;
--bounce-light: #1b293f;
}
@keyframes sunrise {
0% {
background-color: var(--night);
}
10% {
background-color: var(--dawn);
}
35% {
background-color: var(--morning);
}
100% {
background-color: var(--day);
}
}
@keyframes sunset {
0% {
background-color: var(--day);
}
30% {
background-color: var(--evening);
}
60% {
background-color: var(--dusk);
}
90% {
background-color: var(--dawn);
}
100% {
background-color: var(--night);
}
}
#dappled-light {
pointer-events: none;
position: fixed;
height: 100vh;
width: 100vw;
}
#progressive-blur {
position: absolute;
height: 100%;
width: 100%;
}
#progressive-blur>div {
position: absolute;
height: 100%;
width: 100%;
inset: 0;
backdrop-filter: blur(var(--blur-amount));
mask-image: linear-gradient(252deg, transparent, transparent var(--stop1), black var(--stop2), black);
}
#progressive-blur>div:nth-child(1) {
--blur-amount: 6px;
--stop1: 0%;
--stop2: 0%;
}
#progressive-blur>div:nth-child(2) {
--blur-amount: 12px;
--stop1: 40%;
--stop2: 80%;
}
#progressive-blur>div:nth-child(3) {
--blur-amount: 48px;
--stop1: 40%;
--stop2: 70%;
}
#progressive-blur>div:nth-child(4) {
--blur-amount: 96px;
--stop1: 70%;
--stop2: 80%;
}
#glow {
position: absolute;
background: linear-gradient(309deg, var(--bounce-light), var(--bounce-light) 20%, transparent);
transition: background 1.0s var(--timing-fn);
height: 100%;
width: 100%;
opacity: 0.5;
}
#glow-bounce {
content: "";
position: absolute;
background: linear-gradient(355deg, var(--bounce-light) 0%, transparent 30%, transparent 100%);
transition: background 1.0s var(--timing-fn);
opacity: 0.5;
height: 100%;
width: 100%;
bottom: 0;
}
.perspective {
position: absolute;
transition: transform 1.7s var(--timing-fn), opacity 4s ease;
top: -30vh;
right: 0;
width: 80vw;
height: 130vh;
opacity: 0.07;
background-blend-mode: darken;
transform-origin: top right;
transform-style: preserve-3d;
transform: matrix3d(0.7500, -0.0625, 0.0000, 0.0008,
0.0000, 1.0000, 0.0000, 0.0000,
0.0000, 0.0000, 1.0000, 0.0000,
0.0000, 0.0000, 0.0000, 1.0000);
}
.dark .perspective {
opacity: 0.3;
transform: matrix3d(0.8333, 0.0833, 0.0000, 0.0003,
0.0000, 1.0000, 0.0000, 0.0000,
0.0000, 0.0000, 1.0000, 0.0000,
0.0000, 0.0000, 0.0000, 1.0000);
}
#leaves {
position: absolute;
background-size: cover;
background-repeat: no-repeat;
bottom: -20px;
right: -700px;
width: 1600px;
height: 1400px;
background-image: url("./leaves.png");
filter: url(#wind);
animation: billow 8s ease-in-out infinite;
}
#blinds {
position: relative;
width: 100%;
}
#blinds .shutter,
#blinds .bar {
background-color: var(--shadow);
}
#blinds>.shutters {
display: flex;
flex-direction: column;
align-items: end;
gap: 60px;
transition: gap 1.0s var(--timing-fn);
}
.dark #blinds>.shutters {
gap: 20px;
}
#blinds>.vertical {
top: 0;
position: absolute;
height: 100%;
width: 100%;
display: flex;
justify-content: space-around;
}
.vertical>.bar {
width: 5;
height: 100%;
}
.shutter {
width: 100%;
height: 40px;
transition: height 1.0s var(--timing-fn);
}
.dark .shutter {
height: 80px;
}
@keyframes billow {
0% {
transform: perspective(400px) rotateX(0deg) rotateY(0deg) scale(1);
}
25% {
transform: perspective(400px) rotateX(1deg) rotateY(2deg) scale(1.02);
}
50% {
transform: perspective(400px) rotateX(-4deg) rotateY(-2deg) scale(0.97);
}
75% {
transform: perspective(400px) rotateX(1deg) rotateY(-1deg) scale(1.04);
}
100% {
transform: perspective(400px) rotateX(0deg) rotateY(0deg) scale(1);
}
}