first commit! 🎉

port "ari is learning!" assets to live go backend.
some prep work for further developments for ari melody LIVE
This commit is contained in:
ari melody 2026-06-12 04:50:45 +01:00
commit 6927d54cbd
Signed by: ari
GPG key ID: 60B5F0386E3DDB7E
12 changed files with 675 additions and 0 deletions

125
learning/public/cards.css Normal file
View file

@ -0,0 +1,125 @@
:root {
--bg-0: #e0e0e0;
--on-bg-0: #303030;
--on-bg-1: #606060;
--on-bg-2: #808080;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-0: #202020;
--on-bg-0: #e0e0e0;
--on-bg-1: #c0c0c0;
--on-bg-2: #808080;
}
}
body {
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
font-family: "Inter", "Arial", sans-serif;
font-size: 32px;
color: var(--on-bg-0);
background-color: var(--bg-0);
transition: color 1s, background-color 1s;
}
#app {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.vignette {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-image: radial-gradient(transparent, black);
opacity: .1;
pointer-events: none;
}
.title {
display: flex;
flex-direction: column;
justify-content: center;
align-items: end;
}
.title h1, .title h2 {
margin: 0;
}
.title h1 {
font-size: 2em;
margin-bottom: -.2em;
}
.title h2 {
font-size: 1.25em;
color: var(--on-bg-2);
animation: pulse .5s alternate ease-in-out infinite;
}
@keyframes pulse {
from { opacity: 1; }
to { opacity: .5; }
}
header {
position: fixed;
top: 0;
}
footer {
position: fixed;
bottom: 0;
}
header,
footer {
width: calc(100vw - 2.8em);
padding: 1em 1.4em;
display: flex;
flex-direction: row;
justify-content: space-between;
color: var(--on-bg-2);
}
header h3,
footer h3 {
margin: 0;
font-family: "Monaspace Argon", monospace;
}
#time {
font-family: "Monaspace Argon", monospace;
}
#cover {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: var(--bg-0);
transition: opacity 1s ease-out;
}
#cover.hidden {
opacity: 0;
pointer-events: none;
}

51
learning/public/cards.js Normal file
View file

@ -0,0 +1,51 @@
const timeEl = document.getElementById("time");
const titleEl = document.getElementById("title");
const coverEl = document.getElementById("cover");
function render() {
const date = new Date();
const tick = (date.getMilliseconds() * 0.001 % 1.0 > 0.5) ? ":" : " ";
const hh = `${date.getUTCHours()}`.padStart(2, "0");
const mm = `${date.getUTCMinutes()}`.padStart(2, "0");
const ss = `${date.getUTCSeconds()}`.padStart(2, "0");
timeEl.innerText = `${hh}${tick}${mm}${tick}${ss}`;
requestAnimationFrame(render);
}
function ready() {
coverEl.classList.add("hidden");
requestAnimationFrame(render);
}
async function updateTitle() {
if (!titleEl) {
ready();
return;
}
const eventSource = new EventSource("/learning/sse");
eventSource.addEventListener("open", () => {
console.log("Connected.");
eventSource.addEventListener("title-update", event => {
console.log(`title updated: \"${titleEl.innerText}\" -> \"${event.data}\"`)
titleEl.innerText = event.data;
ready();
});
eventSource.addEventListener("error", () => {
eventSource.removeEventListener("error");
eventSource.close();
console.error("Connection lost, or an error has occurred.");
console.log("Attempting to reconnect...");
setTimeout(() => {
updateTitle();
}, 1000);
});
});
}
updateTitle();