Compare commits

4 Commits

Author SHA1 Message Date
349102301c 🔥 rm duplicate files 2025-08-07 02:35:54 +02:00
e618664f7c update 2025-08-07 02:32:35 +02:00
9ad44ff033 🚀 deploy static files 2025-04-06 19:35:33 +02:00
Lucielle Rosalia Hoerner
30adc7145d Merge pull request 'release 2.0.0' (#5) from develop into release
Reviewed-on: https://git.gay/luciel/web_luciel/pulls/5
2025-03-19 01:08:25 +00:00
54 changed files with 1245 additions and 2003 deletions

6
.gitignore vendored
View File

@@ -1,6 +0,0 @@
.idea/
dist/
pkg/
target/
Cargo.lock
static/

1
CNAME
View File

@@ -1 +0,0 @@
lunary.celesteflare.cc

View File

@@ -1,37 +0,0 @@
[package]
name = "web_iouring"
version = "0.0.0-develop"
authors = ["iouring"]
license = "Apache-2.0"
edition = "2024"
rust-version = "1.91"
publish = false
[dependencies]
js-sys = "0.3"
yew = { git = "https://github.com/yewstack/yew.git", rev = "21f373b", features = [
"csr",
] }
yew-router = { git = "https://github.com/yewstack/yew.git", rev = "21f373b" }
wasm-bindgen = { version = "0.2" }
log = { version = "0.4" }
wasm-logger = { version = "0.2" }
serde = { version = "1.0" }
wasm-bindgen-futures = "0.4.50"
serde_json = "1.0.143"
lsp-types = "0.97"
chrono = "0.4"
yew-markdown = { git = "https://git.celesteflare.cc/i0uring/page_md.git", rev = "1e9840" }
yew-hooks = "0.3"
[patch.crates-io]
yew = { git = "https://github.com/yewstack/yew.git", rev = "21f373b", features = [
"csr",
], optional = false }
[dependencies.web-sys]
version = "0.3"
features = ["HtmlCanvasElement", "WebGlBuffer", "WebGlProgram", "WebGlRenderingContext", "WebGl2RenderingContext", "WebGlShader", "WebGlUniformLocation", "Navigator", "Clipboard"]

24
LICENSE
View File

@@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View File

@@ -1,2 +0,0 @@
[tools]
wasm_opt = "version_122"

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,41 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="theme-dark">
<head>
<meta charset="UTF-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<title>i0ur.ing ~ welcome</title>
<link data-trunk rel="copy-file" href="public/misc/favicon.ico" />
<link data-trunk rel="copy-file" href="public/misc/404.png" />
<link data-trunk rel="copy-file" href="public/misc/profile.avif" />
<link data-trunk rel="copy-file" href="public/misc/oneko.gif" />
<link data-trunk rel="copy-file" href="public/misc/freemono.ttf" />
<link data-trunk rel="copy-file" href="public/misc/monocraft.ttf" />
<link data-trunk rel="copy-file" href="public/blog/testimage.jpg" />
<link data-trunk rel="copy-file" href="public/shaders/post.bloom.svg" />
<link rel="stylesheet" href="/main-5f0876a079f6ac58.css" integrity="sha384-Sa1ZWpdYJVb1uRRURVr4pvhoJEjjsLIMS2kyltK9FZdLGYa55YVhC47tdfBRErb+"/>
<script type="module">
import init, * as bindings from '/web_iouring-8ac0645919329a76.js';
const wasm = await init({ module_or_path: '/web_iouring-8ac0645919329a76_bg.wasm' });
<link data-trunk rel="copy-file" href="public/buttons/iouring.png" />
<link data-trunk rel="copy-file" href="public/buttons/wasm.png" />
<link data-trunk rel="copy-file" href="public/buttons/dataforest.png" />
<link data-trunk rel="copy-file" href="public/buttons/servfail.png" />
<link data-trunk rel="copy-file" href="public/buttons/rust.png" />
<link data-trunk rel="copy-file" href="public/buttons/csharp.png" />
<link data-trunk rel="copy-file" href="public/buttons/kotlin.png" />
<link data-trunk rel="copy-file" href="public/buttons/java.png" />
<link data-trunk rel="copy-file" href="public/buttons/fedora.png" />
<link data-trunk rel="copy-file" href="public/buttons/artix.png" />
<link data-trunk rel="copy-file" href="public/buttons/nixos.png" />
<link data-trunk rel="copy-file" href="public/buttons/chimera.png" />
<link data-trunk rel="copy-file" href="public/buttons/void.png" />
<link data-trunk rel="copy-file" href="public/buttons/aqueer.png" />
<link data-trunk rel="sass" href="main.scss" />
<link data-trunk rel="rust" />
<base data-trunk-public-url />
</head>
window.wasmBindings = bindings;
dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));
</script>
<base href="/" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma/css/bulma.min.css" />
<link rel="modulepreload" href="/web_iouring-8ac0645919329a76.js" crossorigin="anonymous" integrity="sha384-KPFxJ5+Aa+ZaSfSE63zjwFcXMH3E+vHNFH4J/VsMxr1NE1pixe0oIzXatlghxyv6"><link rel="preload" href="/web_iouring-8ac0645919329a76_bg.wasm" crossorigin="anonymous" integrity="sha384-NOiLI21zp8RPEUB76WCpoBPABF5V2fkwSiFS7VhnzEbvHeALjfZEWKWN59UWzI71" as="fetch" type="application/wasm"></head>
</html>

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env just --justfile
setup:
rustup target add wasm32-unknown-unknown
install:
cargo install --locked wasm-pack trunk --force
debug:
trunk serve
build:
trunk build --release

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

70
main-5f0876a079f6ac58.css Normal file
View File

@@ -0,0 +1,70 @@
@font-face {
font-family: monocraft;
src: url("monocraft.ttf");
}
html * {
font-family: monocraft, monospace !important;
scrollbar-color: hsla(232, 97%, 85%, 0.5) hsla(240, 21.05%, 14.9%, 0.7) !important;
scrollbar-width: thin !important;
scroll-behavior: smooth !important;
}
::-webkit-scrollbar {
display: none;
}
.textarea {
-ms-overflow-style: none !important;
scrollbar-width: none !important;
}
.textarea::-webkit-scrollbar {
display: none !important;
}
.box {
backdrop-filter: blur(4px) !important;
--bulma-box-background-color: #1E1E2E80 !important;
--bulma-shadow-h: 232 !important;
--bulma-shadow-s: 97% !important;
--bulma-shadow-l: 85% !important;
--bulma-shadow: 0 0.5em 1em -0.125em hsla(var(--bulma-shadow-h),
var(--bulma-shadow-s),
var(--bulma-shadow-l),
0.3), 0 0px 0 1px hsla(var(--bulma-shadow-h),
var(--bulma-shadow-s),
var(--bulma-shadow-l),
0.02) !important;
}
.input,
.select select,
.textarea {
backdrop-filter: blur(4px);
--bulma-input-h: 232 !important;
--bulma-input-s: 97% !important;
--bulma-input-l: 85% !important;
--bulma-input-background-h: var(--bulma-input-h) !important;
--bulma-input-background-s: var(--bulma-input-s) !important;
--bulma-input-background-l: var(--bulma-input-l) !important;
background-color: hsla(var(--bulma-input-h), var(--bulma-input-s), var(--bulma-input-background-l), 0.213125) !important;
border-color: hsl(var(--bulma-input-h), var(--bulma-input-s), var(--bulma-input-l)) !important;
}
a.navbar-item,
a.navbar-item:hover {
background-color: transparent !important;
}
::-moz-selection {
background: hsla(232, 97%, 85%, 0.4125) !important;
}
::selection {
background: hsla(232, 97%, 85%, 0.4125) !important;
}
a:hover {
text-decoration: underline !important;
filter: url("post.bloom.svg#process") !important;
}

View File

@@ -1,81 +0,0 @@
@charset "UTF-8";
@font-face {
font-family: freemono;
src: url("freemono.ttf");
}
@font-face {
font-family: monocraft;
src: url("monocraft.ttf");
}
html * {
font-family: freemono, monocraft, monospace !important;
scrollbar-color: hsla(232, 97%, 85%, 0.5) hsla(240, 21.05%, 14.9%, 0.7) !important;
scrollbar-width: thin !important;
scroll-behavior: smooth !important;
}
::-webkit-scrollbar {
display: none;
}
.textarea {
-ms-overflow-style: none !important;
scrollbar-width: none !important;
}
.textarea::-webkit-scrollbar {
display: none !important;
}
.box {
backdrop-filter: blur(4px) !important;
}
.card {
backdrop-filter: blur(4px) !important;
}
.input,
.select select,
.textarea {
backdrop-filter: blur(4px);
background-color: white, 0.213125 !important;
border-color: white !important;
}
a.navbar-item,
a.navbar-item:hover {
background-color: transparent !important;
}
::-moz-selection {
background: #F5C2E740 !important;
}
::selection {
background: #F5C2E740 !important;
}
a {
color: #F5C2E7FF !important;
text-decoration: none !important;
}
a:hover {
text-decoration: underline !important;
filter: url("post.bloom.svg#process") !important;
}
button {
background-color: transparent !important;
border-color: transparent !important;
color: white !important;
}
button:hover {
text-decoration: underline !important;
filter: url("post.bloom.svg#process") !important;
}

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 315 B

View File

Before

Width:  |  Height:  |  Size: 691 B

After

Width:  |  Height:  |  Size: 691 B

BIN
profile.avif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

View File

@@ -1,179 +0,0 @@
#version 300 es
precision highp float;
const float CAM_FAR = 20.0;
const vec3 BACKGROUND = vec3(0.0, 0.0, 0.0);
uniform float time;
uniform vec2 resolution;
uniform bool layer_snow;
in vec4 vColor;
layout (location = 0) out vec4 fragColor;
vec3 artifactOffset;
mat3 artifactRotation;
vec3 artifactAxis;
vec3 camFwd;
vec3 camUp;
float rand(float n) {
return fract(sin(n) * 43758.5453);
}
float noise(float x) {
float i = floor(x);
float f = fract(x);
return mix(rand(i), rand(i + 1.0), f * f * (3.0 - 2.0 * f));
}
mat4 viewMatrix(vec3 dir, vec3 up) {
vec3 f = normalize(dir);
vec3 s = normalize(cross(f, up));
vec3 u = cross(s, f);
return mat4(
vec4(s, 0.0),
vec4(u, 0.0),
vec4(-f, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
}
mat3 rotationAlign(vec3 d, vec3 z) {
vec3 v = cross(z, d);
float c = dot(z, d);
float k = 1.0 / (1.0 + c);
float k_vx = v.x * k;
float k_vy = v.y * k;
float k_vz = v.z * k;
return mat3(
k_vx * v.x + c, k_vx * v.y - v.z, k_vx * v.z + v.y,
k_vy * v.x + v.z, k_vy * v.y + c, k_vy * v.z - v.x,
k_vz * v.x - v.y, k_vz * v.y + v.x, k_vz * v.z + c
);
}
float intersectPlane(vec3 origin, vec3 direction, vec3 point, vec3 normal) {
return clamp(dot(point - origin, normal) / dot(direction, normal), -1.0, 9991999.0);
}
vec3 calcRay(vec2 uv, float fov, float aspect) {
uv = uv * 2.0 - 1.0;
float d = 1.0 / tan(radians(fov) * 0.5);
return normalize(vec3(aspect * uv.x, uv.y, d));
}
float octahedron(vec3 p, float s) {
const float factor = 0.57735027;
p = abs(p);
return (p.x + p.y + p.z - s) * factor;
}
void artifact(vec3 p, inout float currDist, inout vec3 glowColor, inout int id) {
p -= artifactOffset;
p = artifactRotation * p;
float dist = octahedron(p, 0.8);
const float glowDist = 4.8;
if (dist < glowDist) {
float d = dist + rand(dist) * 1.7;
glowColor += vec3(0.75, 0.55, 0.45) * clamp(1.0 - pow((d * (1.0 / glowDist)), 5.0), 0.0, 1.0) * 0.035;
}
if (dist < currDist) {
currDist = dist;
id = 1;
}
}
float objects(vec3 p, inout vec3 glowColor, inout int objId) {
float dist = CAM_FAR;
artifact(p, dist, glowColor, objId);
return dist;
}
float artifactDist(vec3 p) {
p -= artifactOffset;
p = artifactRotation * p;
return octahedron(p, 1.2);
}
vec3 objectsNormal(vec3 p, float eps) {
vec2 h = vec2(eps, 0);
return normalize(vec3(artifactDist(p + h.xyy) - artifactDist(p - h.xyy), eps * 2.0, artifactDist(p + h.yyx) - artifactDist(p - h.yyx)));
}
vec3 objectsColor(int id, vec3 normal, vec3 ray) {
return id == 1 ? vec3(0.85, 0.65, 0.55) * mix(0.8, 1.5, dot(normal, normalize(vec3(0.0, 1.0, 0.5))) * 0.5 + 0.5) :
id == 2 ? vec3(0.85, 0.65, 0.55) * 1.5 :
vec3(1.0, 1.0, 0.0);
}
void marchObjects(vec3 eye, vec3 ray, float wDepth, inout vec4 color) {
float dist = 0.0;
int id;
vec3 rayPos = eye;
float depth = CAM_FAR;
for (int i = 0; i < 30; i++) {
dist = objects(rayPos, color.rgb, id);
depth = distance(rayPos, eye);
if (depth > wDepth || dist < 0.01) break;
rayPos += ray * dist;
}
color = dist < 0.01 ? vec4(objectsColor(id, objectsNormal(rayPos, 0.01), ray), depth) : color;
}
vec3 march(vec2 uv, vec3 camPos) {
mat4 vm = viewMatrix(camFwd, camUp);
vec3 ray = (vm * vec4(calcRay(uv, 80.0, resolution.x / resolution.y), 1.0)).xyz;
vec4 color = vec4(BACKGROUND, CAM_FAR);
marchObjects(camPos, ray, color.w, color);
return color.rgb;
}
float snow(vec2 uv, float scale) {
float w = smoothstep(1.0, 0.0, -uv.y * (scale * 0.01));
if (w < 0.1) return 0.0;
float timeScale = time / scale;
uv += vec2(timeScale, timeScale);
uv.x += sin(uv.y + time * 0.125) / scale;
uv *= scale;
vec2 s = floor(uv);
vec2 f = fract(uv);
float sinValueX = sin((s.x + scale) * 7.0) * 5.0;
float sinValueY = sin((s.y + scale) * 5.0) * 5.0;
float combinedSinValue = sinValueX + sinValueY;
float lengthValue = length(0.5 + 0.5 * sin(11.0 * fract(combinedSinValue)) - f);
return smoothstep(0.0, min(lengthValue, 3.0), sin(f.x + f.y) * 0.01) * w;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / resolution.xy;
float s = sin(time);
float c = cos(time);
artifactRotation = mat3(c, 0, s, 0, 1, 0, -s, 0, c) * rotationAlign(vec3(0.0, 1.0, 0.0), vec3(s * 0.2, 1.0, c * 0.2 + 0.3));
artifactOffset = vec3(s * 0.4, c * 0.3 - 1.7, -6.0);
camFwd = vec3(0.0, 0.7 + noise(time * 0.8 + 4.0) * 0.08 - 0.04, 1.0);
camUp = vec3(noise(time * 1.2) * 0.02 - 0.01, 1.0, 0.0);
fragColor = vec4(march(uv, vec3(0.0, 1.9, 1.0)) - (length(uv - 0.5) - 0.3) * 0.05, 1.0);
if (layer_snow) {
vec2 uvSnow = (fragCoord * 2.0 - resolution.xy) / min(resolution.x, resolution.y);
fragColor += vec4(vec3(snow(uvSnow, 4.0)), 0.5) * 0.7;
}
}
void main() {
fragColor = vColor;
mainImage(fragColor, gl_FragCoord.xy);
}

View File

@@ -1,11 +0,0 @@
#version 300 es
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
uniform mat4 model;
out vec4 vColor;
void main(void) {
vColor = color;
gl_Position = model * vec4(position, 1.0);
}

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

View File

@@ -1,480 +0,0 @@
#![feature(iter_intersperse)]
extern crate core;
use js_sys::Float32Array;
use log::{info, warn};
use std::cell::RefCell;
use std::sync::Arc;
use wasm_bindgen::JsCast;
use wasm_bindgen::prelude::*;
use web_sys::{HtmlCanvasElement, WebGl2RenderingContext as GL2, window};
use yew::prelude::*;
use yew_router::prelude::*;
mod pages;
use crate::pages::about::About;
use crate::pages::blog::author::Author;
use crate::pages::blog::authors::Authors;
use crate::pages::blog::entries::Entries;
use crate::pages::blog::entry::Entry;
use crate::pages::findme::FindMe;
use crate::pages::projects::projects::Projects;
use pages::not_found::PageNotFound;
#[derive(Routable, PartialEq, Eq, Clone, Debug)]
pub enum Route {
#[at("/")]
About,
#[at("/blog/entries/:id")]
Entry { id: u8 },
#[at("/blog/entries")]
Entries,
#[at("/blog/authors/:id")]
Author { id: u8 },
#[at("/blog/authors")]
Authors,
#[at("/projects")]
Projects,
#[at("/findme")]
FindMe,
#[not_found]
#[at("/404")]
NotFound,
}
pub struct App {
node_ref: NodeRef,
}
impl Component for App {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
node_ref: NodeRef::default(),
}
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
<>
<canvas width="100%" height="100%" style="
background-color: black !important;
position: fixed !important;
left: 0 !important;
top: 0 !important;
width: 100vw !important;
height: 100vh !important;
z-index: 0 !important;
" ref={self.node_ref.clone()} />
<BrowserRouter>
<header style="
z-index: 2 !important;
display: flex !important;
color: white !important;
flex-direction: row !important;
align-items: center !important;
justify-content: center !important;
max-width: 100vw !important;
min-height: 20px !important;
height: 20px !important;
max-height: 20px !important;
filter: url(post.bloom.svg) !important;
">
<h3>{r"»[ "}</h3>
<h3><Link<Route> to={Route::About}>{r"about"}</Link<Route>></h3>
<h3>{r"|"}</h3>
<h3><Link<Route> to={Route::Entries}>{r"blog"}</Link<Route>></h3>
<h3>{r"|"}</h3>
<h3><Link<Route> to={Route::FindMe}>{r"findme"}</Link<Route>></h3>
<h3>{r"|"}</h3>
<h3><Link<Route> to={Route::Projects}>{r"projects"}</Link<Route>></h3>
<h3>{r" ]«"}</h3>
</header>
<main style="
z-index: 1 !important;
background-color: transparent !important;
color: white !important;
display: flex !important;
flex-direction: column !important;
min-width: fit-content !important;
width: calc(100vw - 18 px) !important;
flex-wrap: nowrap !important;
justify-content: space-between !important;
align-items: center !important;
justify-content: center !important;
align-self: center !important;
margin-left: auto !important;
margin-right: auto !important;
overflow-x: hidden !important;
overflow-y: auto !important;
height: fit-content !important;
max-height: calc(100vh - 42px) !important;
">
/*
min-height: 70vh !important;
height: 80vw !important;
*/
<div style="
background-color: rgba(0, 0, 0, 0.3125) !important;
backdrop-filter: blur(6px) !important;
padding: 4px 0px 0px 4px !important;
border-radius: 1.0rem !important;
border-style: solid !important;
border-color: black !important;
border-width: 1px !important;
z-index: 1 !important;
overflow-x: hidden !important;
overflow-y: auto !important;
min-width: 70vw !important;
width: 70vh !important;
max-width: calc(100vw - 18px) !important;
height: 100% !important;
margin-top: auto !important;
margin-bottom: auto !important;
scrollbar-width: thin !important;
scrollbar-color: transparent transparent !important;
"><Switch<Route> render={switch} />
{self.view_buttons()}
</div>
</main>
</BrowserRouter>
</>
}
}
fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
if first_render {
self.view_canvas();
}
}
}
fn switch(routes: Route) -> Html {
match routes {
Route::About => {
html! { <About /> }
}
Route::Entries => {
html! { <Entries /> }
}
Route::Entry { id } => {
html! { <Entry id={id as u8} /> }
}
Route::Authors => {
html! { <Authors /> }
}
Route::Author { id } => {
html! { <Author id={id as u8} /> }
}
Route::FindMe => {
html! { <FindMe /> }
}
Route::Projects => {
html! { <Projects /> }
}
Route::NotFound => {
html! { <PageNotFound /> }
}
}
}
impl App {
fn view_buttons(&self) -> Html {
html! {
<div style="
z-index: 1 !important;
display: flex !important;
flex-wrap: wrap !important;
flex-direction: row !important;
justify-content: center !important;
min-width: 70vw !important;
width: 70vh !important;
max-width: calc(100vw - 18px) !important;
height: fit-content !important;
overflow: hidden !important;
margin-right: auto !important;
margin-left: auto !important;
">
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://i0ur.ing/"><img loading="eager" alt="iouring" src="iouring.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://webassembly.org/"><img loading="eager" alt="wasm" src="wasm.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://beta.servfail.network/"><img loading="eager" alt="servfail" src="servfail.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://www.dataforest.net/en/"><img loading="eager" alt="dataforest" src="dataforest.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://fedoraproject.org/"><img loading="eager" alt="fedora" src="fedora.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://artixlinux.org/"><img loading="eager" alt="artix" src="artix.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://nixos.org/"><img loading="eager" alt="nixos" src="nixos.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://chimera-linux.org/"><img loading="eager" alt="void" src="chimera.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://voidlinux.org/"><img loading="eager" alt="void" src="void.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://www.rust-lang.org/"><img loading="eager" alt="rust" src="rust.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://dotnet.microsoft.com/en-us/"><img loading="eager" alt="csharp" src="csharp.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://kotlinlang.org/"><img loading="eager" alt="kotlin" src="kotlin.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://www.java.com/"><img loading="eager" alt="java" src="java.png" /></a>
<a style="
width: 88px !important;
height: 31px !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
"><img loading="eager" alt="aqueer" src="aqueer.png" /></a>
</div>
}
}
fn view_canvas(&self) {
let canvas = self.node_ref.cast::<HtmlCanvasElement>().unwrap();
let gl = canvas
.get_context("webgl2")
.unwrap_or(canvas.get_context("webgl").unwrap())
.unwrap()
.dyn_into::<GL2>()
.unwrap();
let vertex_buffer = gl.create_buffer().unwrap();
gl.bind_buffer(GL2::ARRAY_BUFFER, Some(&vertex_buffer));
gl.buffer_data_with_array_buffer_view(
GL2::ARRAY_BUFFER,
&Float32Array::from(
vec![
-1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0,
]
.as_slice(),
),
GL2::STATIC_DRAW,
);
let color_buffer = gl.create_buffer().unwrap();
gl.bind_buffer(GL2::ARRAY_BUFFER, Some(&color_buffer));
gl.buffer_data_with_array_buffer_view(
GL2::ARRAY_BUFFER,
&Float32Array::from(
vec![
1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,
]
.as_slice(),
),
GL2::STATIC_DRAW,
);
let element_buffer = gl.create_buffer().unwrap();
gl.bind_buffer(GL2::ELEMENT_ARRAY_BUFFER, Some(&element_buffer));
let element_indices = vec![3, 2, 1, 3, 1, 0];
gl.buffer_data_with_array_buffer_view(
GL2::ELEMENT_ARRAY_BUFFER,
&js_sys::Uint16Array::from(element_indices.as_slice()),
GL2::STATIC_DRAW,
);
let vertex_shader_code = include_str!("../public/shaders/es3/bg.vert");
// info!("{}", vertex_shader_code);
let vertex_shader = gl.create_shader(GL2::VERTEX_SHADER).unwrap();
gl.shader_source(&vertex_shader, vertex_shader_code);
gl.compile_shader(&vertex_shader);
let vertex_shader_log = gl.get_shader_info_log(&vertex_shader);
if !vertex_shader_log.as_ref().unwrap().is_empty() {
info!("{}", vertex_shader_log.as_ref().unwrap());
}
let fragment_shader_code = include_str!("../public/shaders/es3/bg.frag");
let fragment_shader = gl.create_shader(GL2::FRAGMENT_SHADER).unwrap();
gl.shader_source(&fragment_shader, fragment_shader_code);
gl.compile_shader(&fragment_shader);
let fragment_shader_log = gl.get_shader_info_log(&fragment_shader);
if !fragment_shader_log.as_ref().unwrap().is_empty() {
info!("{}", vertex_shader_log.as_ref().unwrap());
}
let shader_program = gl.create_program().unwrap();
gl.attach_shader(&shader_program, &vertex_shader);
gl.attach_shader(&shader_program, &fragment_shader);
gl.link_program(&shader_program);
if !gl
.get_program_parameter(&shader_program, GL2::LINK_STATUS)
.as_bool()
.unwrap()
{
warn!("shader couldn't be linked!");
}
gl.use_program(Some(&shader_program));
let position = gl.get_attrib_location(&shader_program, "position") as u32;
gl.enable_vertex_attrib_array(position);
gl.bind_buffer(GL2::ARRAY_BUFFER, Some(&vertex_buffer));
gl.vertex_attrib_pointer_with_i32(position, 3, GL2::FLOAT, false, 0, 0);
let color = gl.get_attrib_location(&shader_program, "color") as u32;
gl.enable_vertex_attrib_array(color);
gl.bind_buffer(GL2::ARRAY_BUFFER, Some(&color_buffer));
gl.vertex_attrib_pointer_with_i32(color, 4, GL2::FLOAT, false, 0, 0);
gl.bind_buffer(GL2::ELEMENT_ARRAY_BUFFER, Some(&element_buffer));
gl.enable(GL2::DEPTH_TEST);
gl.clear_color(0.0, 0.0, 0.0, 1.0);
gl.clear(GL2::COLOR_BUFFER_BIT | GL2::DEPTH_BUFFER_BIT);
let default_matrix = vec![
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
];
let unim_matrix = gl.get_uniform_location(&shader_program, "model");
let unim_time = gl.get_uniform_location(&shader_program, "time");
let unim_res = gl.get_uniform_location(&shader_program, "resolution");
let unim_overlay_time = gl.get_uniform_location(&shader_program, "layer_snow");
let mut timestamp = 0.0;
gl.uniform1f(unim_time.as_ref(), timestamp / 2000.0);
gl.draw_elements_with_i32(
GL2::TRIANGLES,
element_indices.len() as i32,
GL2::UNSIGNED_SHORT,
0,
);
fn request_animation_frame(f: &Closure<dyn FnMut()>) {
window()
.unwrap()
.request_animation_frame(f.as_ref().unchecked_ref())
.expect("should register `requestAnimationFrame` OK");
}
let cb = Arc::new(RefCell::new(None));
*cb.borrow_mut() = Some(Closure::wrap(Box::new({
let cb = cb.clone();
move || {
timestamp += 20.0;
canvas.set_width(window().unwrap().inner_width().unwrap().as_f64().unwrap() as u32);
canvas.set_height(window().unwrap().inner_height().unwrap().as_f64().unwrap() as u32);
gl.uniform_matrix4fv_with_f32_array(unim_matrix.as_ref(), false, default_matrix.as_slice());
gl.uniform1f(unim_time.as_ref(), timestamp / 2000.0);
gl.uniform2fv_with_f32_array(
unim_res.as_ref(),
vec![canvas.width() as f32, canvas.height() as f32].as_slice(),
);
gl.uniform1i(unim_overlay_time.as_ref(), 0); // TODO: ... | add is xmas check
gl.viewport(0, 0, canvas.width() as i32, canvas.height() as i32);
gl.clear(GL2::COLOR_BUFFER_BIT | GL2::DEPTH_BUFFER_BIT);
gl.draw_elements_with_i32(
GL2::TRIANGLES,
element_indices.len() as i32,
GL2::UNSIGNED_SHORT,
0,
);
request_animation_frame(cb.borrow().as_ref().unwrap());
}
}) as Box<dyn FnMut()>));
request_animation_frame(cb.borrow().as_ref().unwrap());
}
}
fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
yew::Renderer::<App>::new().render();
}

View File

@@ -1,95 +0,0 @@
use yew::prelude::*;
pub struct About;
impl Component for About {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
<>
<div>
<img alt="insert pfp here" style="
float: left !important;
margin-right: 10px !important;
border-radius: 0.5rem !important;
" loading="eager" width="96px" height="96px" src="profile.avif" />
<div style="
display: flex !important;
flex-direction: column !important;
max-height: 96px !important;
">
<p style="
display: flex !important;
color: transparent !important;
flex-direction: row !important;
align-items: center !important;
width: fit-content !important;
background-clip: text !important;
background-image: linear-gradient(45deg, #5BCEFAFF, #F5A9B8FF, #FFFFFFFF) !important;
-webkit-background-clip: text !important;
margin: unset !important;
filter: url(post.bloom.svg#process) !important;
">
<img loading="eager" alt="ket" src="oneko.gif" />{r" lia · they/she · transfemby"}</p>
<p style="margin: unset !important;">
<p style="margin: unset !important;">{r"certified catgirl™"}</p>
<p style="margin: unset !important;">{r"software engineer"}</p>
<p style="margin: unset !important;">{r"professional yapper"}</p>
<p style="margin: unset !important;">{r"neurospicy and disabled"}</p>
</p>
</div>
<p style="
font-weight: bold !important;
font-style: italic !important;
font-size: xx-large !important;
">{r">intro_"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
">{r#"
name's lia or lucy. we are creating.
trying to provide a safe space in the internet.
our goal's to make this world a better ~ less trashy ~ place.
may sound naive as fuck but fuck it we ball.
audhd (certified) and probably bpd or ptsd. i'm not a psychologist tho.
interact with caution, may bite.
political view's prolly very obvious. should be enough to mention i'm social.
figure it yourself. use your brain.
"#}</p>{r">hobbies_"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
">{r#"
watching anime, designing something kewl, playing games, starting a new project or just yapping with friends, nearly everything's included.
i especially enjoy cooking or even baking if enough spoons are to avail.
which anime? has to be very specific, i'm really picky and judgy regarding them.
i uh - design stuff when enough creativity is there. nothing specific. maybe just a button, banner, icon or just anything.
has to be something i can somewhat imagine in my fucky-wucky head.
gaymes? gay! no uhh - i play ranging from minecraft and stardew, to puzzly metroidvanias like hollow knight and pseudoregalia, or challenging platformers like celeste, nearly anything.
i also enjoy playing rhythm games like osu! or muse dash. returning to terraria sometimes and also some old-ish games.
projects? you can find public ones in my projects tab.
"#}/*</p>{r"hobbies"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
">{r#"
watching anime, designing something kewl, playing games, starting a new project or just yapping/meeting up with friends, nearly everything's included.
i especially enjoy cooking or even baking if enough spoons are to avail.
which anime? has to be very specific, i'm really picky and judgy regarding them.
i uh - design stuff when enough creativity is there. nothing specific. maybe just a button, banner, icon or just anything.
has to be something i can somewhat imagine in my fucky-wucky head.
gaymes? gay! no uhh - i play ranging from minecraft and stardew, to puzzly metroidvanias like hollow knight and pseudoregalia, or challenging platformers like celeste, nearly anything.
i also enjoy playing rhythm games like osu! or muse dash. returning to terraria sometimes and also some old-ish games.
projects? you can find public ones in my projects tab.
"#}*/</p>
</p>
</div>
</>
}
}
}

View File

@@ -1,71 +0,0 @@
use crate::pages::blog::content;
use crate::pages::blog::content::{BlogEntry, Post};
use yew::prelude::*;
use crate::pages::blog::authorcard::AuthorCard;
use crate::pages::blog::entrycard::EntryCard;
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
pub struct Props {
pub id: u8,
}
pub struct Author {
author: content::Author,
}
impl Component for Author {
type Message = ();
type Properties = Props;
fn create(ctx: &Context<Self>) -> Self {
Self {
author: content::Author::from_id(ctx.props().id),
}
}
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
self.author = content::Author::from_id(ctx.props().id);
true
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let Self { author } = self;
let id = author.id;
let cards: Vec<_> = (0..Post::POSTS.len()) // TODO: ... | add var
.filter(|&id_offset| {
Post::from_id(id_offset as u8)
.authors
.iter()
.any(|id1| *id1 == id)
})
.map(|id_offset| html! {<EntryCard id={id_offset as u8} />})
.collect();
html! {
<div style="
display: flex !important;
width: 100% !important;
flex-direction: column !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-bottom: 2rem !important;
">
<h2 style="text-align: center !important;">{ "about me" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-bottom: 1rem !important;
"><AuthorCard {id} /></div>
<h2 style="text-align: center !important;">{ "my posts" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
">{ for cards }</div>
</div>
}
}
}

View File

@@ -1,72 +0,0 @@
use yew::prelude::*;
use yew_router::components::Link;
use crate::pages::blog::content::Author;
use crate::pages::blog::content::BlogEntry;
use crate::Route;
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
pub struct PropsAuthorCard {
pub id: u8,
}
pub struct AuthorCard {
author: Author,
}
impl Component for AuthorCard {
type Message = ();
type Properties = PropsAuthorCard;
fn create(ctx: &Context<Self>) -> Self {
Self {
author: Author::from_id(ctx.props().id),
}
}
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
self.author = Author::from_id(ctx.props().id);
true
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let Self { author } = self;
let keywords = author.keywords.iter().map(|keyword| html! {
<p style="margin: unset !important;">{*keyword}</p>
}).collect::<Html>();
html! {
<div style="
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
background-color: #ECBEE130 !important;
border-radius: 0.5rem !important;
width: fit-content !important;
height: fit-content !important;
text-align: left !important;
margin: 1rem 1rem 0 0 !important;
">
<img style="
float: left !important;
margin-right: 0.3rem !important;
border-radius: 0.5rem !important;
" alt="insert pfp here" width="96" height="96" src={author.image_url} />
<div style="
display: flex !important;
flex-direction: column !important;
flex-wrap: wrap !important;
margin-top: 0.3rem !important;
margin-right: 0.3rem !important;
">
<h3 style="margin: unset !important;">
<Link<Route> to={Route::Author { id: author.id }}>
{ &*author.name }
</Link<Route>>
</h3>
{ keywords }
</div>
</div>
}
}
}

View File

@@ -1,31 +0,0 @@
use yew::prelude::*;
use crate::pages::blog::authorcard::AuthorCard;
use crate::pages::blog::content::{Author, BlogEntry};
pub struct Authors;
impl Component for Authors {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _: &Context<Self>) -> Html {
html! {
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-top: 2rem !important;
margin-bottom: 2rem !important;
">{ for Author::AUTHORS.map(|author| {
let id = author.id;
html! { <AuthorCard {id} /> }
}) }</div>
}
}
}

View File

@@ -1,299 +0,0 @@
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Author {
pub id: u8,
pub image_url: &'static str,
pub name: &'static str,
pub keywords: &'static [&'static str],
pub about: &'static str,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Post {
pub id: u8,
pub authors: &'static [u8],
pub title: &'static str,
pub utcdate: &'static str,
pub content: &'static str,
}
impl BlogEntry for Author {
fn from_entry(entry: &mut Entry) -> Self {
*Self::AUTHORS
.get(entry.id as usize)
.cloned()
.unwrap_or(&Self {
id: u8::MAX,
image_url: "",
name: "not found",
keywords: [].as_slice(),
about: "",
})
}
}
impl BlogEntry for Post {
fn from_entry(entry: &mut Entry) -> Self {
*Self::POSTS
.get(entry.id as usize)
.cloned()
.unwrap_or(&Self {
id: u8::MAX,
authors: &[u8::MAX],
title: "not found",
utcdate: "1970-01-01",
content: "",
})
}
}
pub struct Entry {
pub id: u8,
}
impl Entry {
pub fn from_id(seed: u8) -> Self {
Self { id: seed }
}
}
pub trait BlogEntry: Sized {
fn from_entry(entry: &mut Entry) -> Self;
fn from_id(id: u8) -> Self {
Self::from_entry(&mut Entry::from_id(id))
}
const AUTHORS: [&'static Author; 2] = [
&Author {
id: 0,
image_url: "profile.avif",
name: "lia",
keywords: &[
"certified catgirl™",
"software engineer",
"professional yapper",
"neurospicy and disabled",
],
about: "",
},
&Author {
id: 1,
image_url: "",
name: "mreowww",
keywords: &["meow", "mrrp", "mew"],
about: "",
},
];
const POSTS: [&'static Post; 2] = [
&Post {
id: 0,
authors: &[0],
title: "haj, world!",
utcdate: "2025-08-24",
content: r#"
### my first blogpost
haj! and welcome to my first blogpost.
this blogpost won't have that much content.
fun fact: this post becomes html from markdown :3
pretty cool, ain't it? we think so too.
it's for including images, formatted text, code and content much easier.
i also added a too overcomplicated blog backend that allows authors and posts by u8::MAX, cause why not.
won't post that much either way, so why bother with higher values.
nonetheless... have a great day, evening, whatever daytime it's for you rn and stay safe. ♡
you may take a look at my other blogposts. this one was basically practially just a test.
"#,
},
&Post {
id: 1,
authors: &[0],
title: "sweet little poison",
utcdate: "2025-08-25",
content: r#"
### > setting up iocaine with docker and caddy. ~
sup, today we're going to give ya a crash course on how to homebrew poison for ai. ^.^
we'll be utilizing docker for containerization and caddy as a reverse-proxy.
#### > preparing docker and files ~
first, we're going to create a new external network and recreate our file struct.
in this example we're going to name it "caddy". very creative, i know.
we achieve this by running following pile of commands:
```sh
docker network create caddy && \
mkdir -p ./caddy/pages/example.com ./iocaine ./socks && \
touch ./docker-compose.yml ./caddy/proxy ./iocaine/config.toml && \
touch ./caddy/pages/example.com/index.html && \
printf '<html><body><h1>hellow body consisting of blood and flesh</h1></body></html>' \
> ./caddy/pages/example.com/index.html
```
after running that we should be set and ready for the next few steps.
if you're curious, this is how it should look like right now:
```sh
Documents/example » tree .
.
├── caddy
│   ├── pages
│   │   └── example.com
│   │   └── index.html
│   └── proxy
├── docker-compose.yml
├── iocaine
│   └── config.toml
└── socks
```
#### > downloading data and configuring iocaine ~
next things next: we're going to download a robots.json, some markov-chain-stuffies and a words.txt.
for now, we will be using the default stuff from the official docs cause why not:
```sh
curl --proto '=https' --tlsv1.3 \
-L https://archive.org/download/GeorgeOrwells1984/1984_djvu.txt \
-o ./iocaine/1984.txt && \
curl --proto '=https' --tlsv1.3 \
-L https://archive.org/download/ost-english-brave_new_world_aldous_huxley/Brave_New_World_Aldous_Huxley_djvu.txt \
-o ./iocaine/brave-new-world.txt && \
curl --proto '=https' --tlsv1.2 \
-L https://git.savannah.gnu.org/cgit/miscfiles.git/plain/web2 \
-o ./iocaine/words.txt && \
curl --proto '=https' --tlsv1.3 \
-L https://github.com/ai-robots-txt/ai.robots.txt/raw/refs/heads/main/robots.json \
-o ./iocaine/robots.json
```
most importantly, we have to scrape nam-shub-of-enki from gergely's git.
here's a way to curl and extract it automatically in the correct folder:
```sh
curl --proto '=https' --tlsv1.3 \
-L https://git.madhouse-project.org/api/packages/iocaine/generic/nam-shub-of-enki/20250711.0/nam-shub-of-enki-20250711.0.tar.zst \
-o ./iocaine/nam-shub-of-enki.tar.zst && \
sudo tar -xvf ./iocaine/nam-shub-of-enki.tar.zst -C ./iocaine
```
now, we're going to prepare our iocaine/config.toml like this:
```sh
cat > ./iocaine/config.toml <<'YAML'
[server]
bind = "/run/iocaine/waow.socket"
unix_listen_access = "everybody"
[server.control]
bind = "/run/iocaine/listen.socket"
unix_listen_access = "owner"
[server.request-handler]
path = "/data"
language = "roto"
[sources]
words = "/data/words.txt"
markov = [ "/data/1984.txt", "/data/brave-new-world.txt" ]
[metrics]
enable = false
YAML
```
#### > cooking up our docker compose file for deployment ~
i have fucked around with docker a little while to make this somehow work.
here's a command which will insert needed content into our docker-compose.yml:
```sh
cat > ./docker-compose.yml <<'YAML'
services:
caddy:
image: caddy:alpine
container_name: proxy.caddy
hostname: proxy.caddy
restart: unless-stopped
cap_add:
- NET_ADMIN
ports:
- "80:80"
- "443:443"
- "443:443/udp"
networks:
- caddy
volumes:
- ./socks:/run/iocaine:ro
- ./caddy/pages:/var/www/html
- ./caddy/data:/data
- ./caddy/config:/config
- ./caddy/proxy:/etc/caddy/Caddyfile:ro
depends_on:
- iocaine
iocaine:
image: git.madhouse-project.org/iocaine/iocaine:2
container_name: proxy.iocaine
hostname: proxy.iocaine
restart: unless-stopped
ports:
- "127.0.0.1:42069:42069"
networks:
- caddy
volumes:
- ./socks:/run/iocaine:rw
- ./iocaine:/data
environment:
- IOCAINE__SERVER__BIND="/run/iocaine/waow.socket"
- IOCAINE__SERVER__UNIX_LISTEN_ACCESS="everybody"
- IOCAINE__SERVER__REQUEST_HANDLER__PATH="/data"
- IOCAINE__SERVER__REQUEST_HANDLER__LANGUAGE="roto"
- IOCAINE__SERVER__CONTROL__BIND="/run/iocaine/listen.socket"
- IOCAINE__SERVER__CONTROL__UNIX_LISTEN_ACCESS="owner"
- IOCAINE__SOURCES__WORDS="/data/words.txt"
- IOCAINE__SOURCES__MARKOV=["/data/1984.txt", "/data/brave-new-world.txt"]
- IOCAINE__METRICS__ENABLE=false
- NSOE__AI_ROBOTS_TXT_PATH=/data/robots.json
command: --config-file /data/config.toml start
networks:
caddy:
external: true
YAML
```
#### > finishing up with caddy and deploying ~
our caddyfile needs some love to work.
here's what i ripped from the official docs:
```sh
cat > ./iocaine/proxy <<'TXT'
(iocaine) {
@read method GET HEAD
@not-read not {
method GET HEAD
}
reverse_proxy @read unix//run/iocaine/waow.socket {
#reverse_proxy @read proxy.iocaine:42069 {
@fallback status 421
handle_response @fallback {
{blocks.handler}
}
}
handle @not-read {
{blocks.default}
}
}
example.com {
import iocaine {
handler {
reverse_proxy http://example:8080
}
default {
# this is the behaviour if neither a GET nor HEAD request comes in
reverse_proxy http://example:8080
}
}
}
TXT
```
now the last thing that's left is a plain and simple:
`docker compose up -d`
and we should be good to go!
i hope this post made it easier/helped you with setting up iocaine on your own server. ♡
it's good to have this set up just to fuck around with fucking parisitic generative ai stealing your things.
gatekeep your stuff from big corpos that are trying to make their business from your experience and skills.
"#,
},
];
}

View File

@@ -1,55 +0,0 @@
use yew::prelude::*;
use crate::pages::blog::content::BlogEntry;
use crate::pages::blog::content::Post;
use crate::pages::blog::entrycard::EntryCard;
pub struct Entries {}
impl Component for Entries {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {}
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div>
<h1 style="margin: unset !important;">{ "entries" }</h1>
<h2 style="
margin: unset !important;
margin-bottom: 1rem !important;
">{ "here are some things i yapped about" }</h2>
{ self.view_posts(ctx) }
</div>
}
}
}
impl Entries {
fn view_posts(&self, _ctx: &Context<Self>) -> Html {
let cards: Vec<_> = (0..Post::POSTS.len()) // TODO: ... | add var
.filter(|&id_offset| {
Post::from_id(id_offset as u8)
.authors
.iter()
.all(|id| *id != u8::MAX)
})
.map(|id_offset| html! {<EntryCard id={id_offset as u8} />})
.collect();
html! {
<div style="
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin: unset !important;
margin-bottom: 1rem !important;
width: 100% !important;
">
{ for cards }
</div>
}
}
}

View File

@@ -1,77 +0,0 @@
use std::rc::Rc;
use yew::prelude::*;
use yew_markdown::Markdown;
use yew_router::prelude::*;
use crate::pages::blog::content;
use crate::pages::blog::content::{Author, BlogEntry};
use crate::Route;
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
pub struct Props {
pub id: u8,
}
#[derive(PartialEq, Eq, Debug)]
pub struct PostState {
pub inner: content::Post,
}
impl Reducible for PostState {
type Action = u8;
fn reduce(self: Rc<Self>, action: u8) -> Rc<Self> {
Self {
inner: content::Post::from_id(action.into()),
}
.into()
}
}
#[function_component]
pub fn Entry(props: &Props) -> Html {
let id = props.id;
let post = use_reducer(|| PostState {
inner: content::Post::from_id(id.into()),
});
{
let post_dispatcher = post.dispatcher();
use_effect_with(id, move |id| {
post_dispatcher.dispatch(*id);
|| {}
});
}
let post = &post.inner;
html! {
<>
<h1 style="
color: #F5C2E7FF !important;
margin: unset !important;
filter: url(post.bloom.svg#process) !important;
">{ &*post.title }</h1>
<div style="flex-direction: column !important;">
<h2 style="margin: unset !important;">
{ "written by " } {
post.authors.iter().map(|id| {
let author = Author::from_id(*id);
html! {
<Link<Route> to={crate::Route::Author { id: author.id }}>
{ &*author.name }
</Link<Route>>
}
}).intersperse(html! { ", " }).collect::<Html>()
} { format!(" on {}", &post.utcdate) }
</h2>
</div>
<Markdown
src={post.content}
hard_line_breaks={true}
send_debug_info={Callback::noop()}
/>
</>
}
}

View File

@@ -1,98 +0,0 @@
use std::rc::Rc;
use yew::prelude::*;
use yew_router::components::Link;
use crate::pages::blog::content::{Author, BlogEntry, Post};
use crate::Route;
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
pub struct PropsEntryCard {
pub id: u8,
}
#[derive(PartialEq, Eq, Debug)]
pub struct PostState {
inner: Post,
}
impl Reducible for PostState {
type Action = u8;
fn reduce(self: Rc<Self>, action: u8) -> Rc<Self> {
Self {
inner: Post::from_id(action.into()),
}
.into()
}
}
#[function_component]
pub fn EntryCard(props: &PropsEntryCard) -> Html {
let id = props.id;
let post = use_reducer_eq(|| PostState {
inner: Post::from_id(id.into()),
});
{
let post_dispatcher = post.dispatcher();
use_effect_with(id, move |id| {
post_dispatcher.dispatch(*id);
|| {}
});
}
let post = &post.inner;
html! {
<div style="
display: flex !important;
flex-direction: column !important;
flex-wrap: wrap !important;
background-color: #ECBEE130 !important;
border-radius: 0.5rem !important;
width: fit-content !important;
height: fit-content !important;
text-align: left !important;
margin: 1rem 1rem 0 0 !important;
">
<Link<Route> to={Route::Entry { id: post.id }}>
<h2 style="
margin: unset !important;
margin-top: 0.3rem !important;
margin-left: 0.3rem !important;
margin-right: 0.3rem !important;
">{ &*post.title }</h2>
</Link<Route>>
<h3 style="
margin: unset !important;
margin-left: 0.3rem !important;
margin-right: 0.3rem !important;
">
{ format!("published {}", post.utcdate) }
</h3>
<div style="flex-direction: column !important;">
<h3 style="
margin: unset !important;
margin-left: 0.3rem !important;
margin-right: 0.3rem !important;
margin-bottom: 0.3rem !important;
">
{ "written by " }
{
post.authors.iter().map(|id| {
let author = Author::from_id(*id);
html! {
<Link<Route> to={crate::Route::Author { id: author.id }}>
{ &*author.name }
</Link<Route>>
}
}).intersperse(html! { ", " }).collect::<Html>()
}
</h3>
</div>
</div>
}
}

View File

@@ -1,7 +0,0 @@
pub mod author;
pub mod authorcard;
pub mod authors;
pub mod content;
pub mod entries;
pub mod entry;
pub mod entrycard;

View File

@@ -1,138 +0,0 @@
use web_sys::window;
use yew::prelude::*;
pub struct FindMe;
impl Component for FindMe {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let clipboard = window().expect("meow").navigator().clipboard();
let handle_copy_matrix = {
let clipboard = clipboard.clone();
Callback::from(move |_| {
let _ = clipboard.write_text(&*"@iouring:hi.stellaris.fyi".to_string());
})
};
let handle_copy_telegram = {
let clipboard = clipboard.clone();
Callback::from(move |_| {
let _ = clipboard.write_text(&*"@luc1ell3".to_string());
})
};
let handle_copy_discord = {
let clipboard = clipboard.clone();
Callback::from(move |_| {
let _ = clipboard.write_text(&*"@donotusedisc0rdkthxbye".to_string());
})
};
html! {
<div style="
display: flex !important;
flex-direction: row !mportant;
flex-wrap: wrap !important;
justify-content: center !important;
width: 100% !important;
">
<div style="
width: fit-content !important;
height: fit-content !important;
margin: 1rem 1rem 1rem 1rem !important;
">
<p style="
font-weight: bold !important;
font-style: normal !important;
font-size: xx-large !important;
text-align: center !important;
margin: unset !important;
">{r"follow us"}</p>
<p style="
font-weight: normal !important;
font-style: normal !important;
font-size: large !important;
">{" × "}<a style="
color: #F5C2E7FF !important;
" href="https://ice.stellaris.fyi/@iouring">{r"fediverse"}</a><br />
{" × "}<a style="
color: #B4BEFEFF !important;
" href="https://bsky.app/profile/i0ur.ing">{r"bluesky"}</a><br />
</p>
</div>
<div style="
width: fit-content !important;
height: fit-content !important;
margin: 1rem 1rem 1rem 1rem !important;
">
<p style="
font-weight: bold !important;
font-style: normal !important;
font-size: xx-large !important;
text-align: center !important;
margin: unset !important;
">{r"write us"}</p>
<p style="
font-weight: normal !important;
font-style: normal !important;
font-size: large !important;
">
{"× "}
<button style="
color: #94E2D5FF !important;
font-size: large !important;
" onclick={handle_copy_matrix}>{r"matrix"}</button>
<br />
{"× "}
<button style="
color: #B4BEFEFF !important;
font-size: large !important;
" onclick={handle_copy_telegram}>{r"telegr"}</button>
<br />
{"× "}
<button style="
color: #F38BA8FF !important;
font-size: large !important;
" onclick={handle_copy_discord}>{r"ewcord"}</button>
</p>
</div>
<div style="
width: fit-content !important;
height: fit-content !important;
margin: 1rem 1rem 1rem 1rem !important;
">
<p style="
font-weight: bold !important;
font-style: normal !important;
font-size: xx-large !important;
text-align: center !important;
margin: unset !important;
">{r"git gud"}</p>
<p style="
font-weight: normal !important;
font-style: normal !important;
font-size: large !important;
">{" × "}<a style="
color: #F5C2E7FF !important;
" href="https://git.celesteflare.cc/i0uring">{r"my own!!!"}</a><br />
{" × "}<a style="
color: #CBA6F7FF !important;
" href="https://git.gay/luciel">{r"the gay one"}</a><br />
{" × "}<a style="
color: #B4BEFEFF !important;
" href="https://git.rimuru.club/i0uring">{r"git of fren"}</a><br />
{" × "}<a style="
color: #89B4FAFF !important;
" href="https://codeberg.org/i0uring">{r"a mountain what"}</a>
</p>
</div>
</div>
}
}
}

View File

@@ -1,6 +0,0 @@
pub mod about;
pub mod blog;
pub mod findme;
pub mod projects;
pub mod not_found;

View File

@@ -1,31 +0,0 @@
use yew::prelude::*;
pub struct PageNotFound;
impl Component for PageNotFound {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
<div style="
display: flex !important;
text-align: center !important;
flex-direction: row !important;
align-items: center !important;
flex-wrap: wrap !important;
justify-content: center !important;
">
<img loading="eager" alt="huh" style="
width: 96px !important;
height: 96px !important;
" width="96" height="96" src="404.png" />
<h1>{ "what" }</h1>
</div>
}
}
}

View File

@@ -1,51 +0,0 @@
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Project {
pub url: &'static str,
pub name: &'static str,
pub desc: &'static str,
}
impl ProjectEntry for Project {}
pub trait ProjectEntry: Sized {
const PROJECTS_ONGOING: [&'static Project; 3] = [
&Project {
url: "https://git.celesteflare.cc/stellaris/mod_headsup",
name: "headsup mod",
desc: "extensible hud mc mod",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/app_catnip",
name: "catnip",
desc: "all-rounder ide in the making",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/app_nekochat",
name: "neko chat",
desc: "my planned matrix client",
},
];
const PROJECTS_FINISHED: [&'static Project; 4] = [
&Project {
url: "https://git.celesteflare.cc/i0uring/lib_tinyevents",
name: "tiny events",
desc: "a java 21+ event-sys",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/dotfiles",
name: "dotfiles",
desc: "personal set of configurations",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/lib_swingify",
name: "tiny events",
desc: "simplifies java swing window creation",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/dotfiles",
name: "modern netty",
desc: "adds experimental netty handlers to mc",
},
];
}

View File

@@ -1,3 +0,0 @@
pub mod content;
pub mod projectcard;
pub mod projects;

View File

@@ -1,54 +0,0 @@
use yew::prelude::*;
use crate::pages::projects::content::Project;
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
pub struct PropsAuthorCard {
pub project: Project,
}
pub struct ProjectCard {
project: Project,
}
impl Component for ProjectCard {
type Message = ();
type Properties = PropsAuthorCard;
fn create(ctx: &Context<Self>) -> Self {
Self {
project: ctx.props().project,
}
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let Self { project } = self;
html! {
<div style="
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
background-color: #ECBEE130 !important;
border-radius: 0.5rem !important;
width: fit-content !important;
height: fit-content !important;
text-align: left !important;
margin: 1rem 1rem 0 0 !important;
">
<div style="
display: flex !important;
flex-direction: column !important;
flex-wrap: wrap !important;
margin: 0.3rem 0.3rem 0.3rem 0.3rem !important;
">
<h2 style="margin: unset !important;">
<a href={project.url}>{ &*project.name }</a>
</h2>
<h3 style="margin: unset !important;">
{ &*project.desc }
</h3>
</div>
</div>
}
}
}

View File

@@ -1,54 +0,0 @@
use crate::pages::projects::content::{Project, ProjectEntry};
use crate::pages::projects::projectcard::ProjectCard;
use yew::prelude::*;
pub struct Projects;
impl Component for Projects {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let projects_ongoing = Project::PROJECTS_ONGOING.map(|project| {
let project = *project;
html! { <ProjectCard {project} /> }
});
let projects_finished = Project::PROJECTS_FINISHED.map(|project| {
let project = *project;
html! { <ProjectCard {project} /> }
});
html! {
<div style="
display: flex !important;
width: 100% !important;
flex-direction: column !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-bottom: 2rem !important;
">
<h2 style="text-align: center !important;">{ "ongoing projects" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: flex-start !important;
margin-bottom: 1rem !important;
">{ for projects_ongoing }</div>
<h2 style="text-align: center !important;">{ "finished projects" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: flex-start !important;
">{ for projects_finished }</div>
</div>
}
}
}

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.