Vanessa Freudenberg's Avatar

Vanessa Freudenberg

@codefrau.bsky.social

I design and implement interactive and collaborative systems: Co-founder of Croquet.io • Chief Architect Multisynq.io • Creator of Squeak.JS.org • Formerly at Alan Kay’s groups (VPRI.org, CDG Labs, YCR HARC) • Dr (EngD) • German living in Los Angeles 🏳️‍🌈

193 Followers  |  129 Following  |  25 Posts  |  Joined: 11.11.2024  |  1.8167

Latest posts by codefrau.bsky.social on Bluesky

Yes you need to allow that

04.04.2025 02:55 — 👍 2    🔁 0    💬 0    📌 0

Prompts: aistudio.google.com/prompts/1uwR...

The example app given in the first prompt: github.com/multisynq/mu...

04.04.2025 02:29 — 👍 1    🔁 0    💬 1    📌 0
Preview
Multi-player 3D Asteroids using Three.js & Croquet vibe coded by Gemini ...

I spent an afternoon vibe-coding a multiplayer game with @multisynq.bsky.social and @threejs.org using Gemini Pro 2.5 – 100% AI coded, although I had to explain how to correct the errors. Zero server code, client-side multiplayer.

Live and source on @codepen.io:
codepen.io/codefrau/ful...

04.04.2025 02:28 — 👍 2    🔁 0    💬 1    📌 0

The docs are so pretty, OMG. Congrats!

03.04.2025 17:39 — 👍 1    🔁 0    💬 0    📌 0
#version 300 es
in      ivec2 xyIdIx;          // position in upper 16 bits, id and index in lower 16 bits
uniform vec2  screenScale;     // half width/height of screen
uniform float spotSize;        // size of spot
uniform uint  colorIdx;        // start of spots in display table
out     vec3  v_color;         // color of spot

vec3 hue(float h) {
    h = mod(h, 1.0);
    float r = abs(h * 6.0 - 3.0) - 1.0;
    float g = 2.0 - abs(h * 6.0 - 2.0);
    float b = 2.0 - abs(h * 6.0 - 4.0);
    return clamp(vec3(r, g, b), 0.0, 1.0);
}

void main() {
    ivec2 pos = xyIdIx >> ivec2(16, 16);                   // sign extend 16 bits to 32
    uint idx = uint(xyIdIx.y & 65536);                     // 16 bit index
    if (idx < colorIdx) {
        float fraction = float(idx) / float(colorIdx);     // map to [0, 1)
        v_color = hue(float(idx) / float(colorIdx));       // color by table index
    } else {
        v_color = vec3(1.0);                               // default: white
    }
    gl_Position = vec4(vec2(pos) / screenScale, 0.0, 1.0);
    gl_PointSize = spotSize * 512.0 / max(screenScale.x, screenScale.y);
}

#version 300 es in ivec2 xyIdIx; // position in upper 16 bits, id and index in lower 16 bits uniform vec2 screenScale; // half width/height of screen uniform float spotSize; // size of spot uniform uint colorIdx; // start of spots in display table out vec3 v_color; // color of spot vec3 hue(float h) { h = mod(h, 1.0); float r = abs(h * 6.0 - 3.0) - 1.0; float g = 2.0 - abs(h * 6.0 - 2.0); float b = 2.0 - abs(h * 6.0 - 4.0); return clamp(vec3(r, g, b), 0.0, 1.0); } void main() { ivec2 pos = xyIdIx >> ivec2(16, 16); // sign extend 16 bits to 32 uint idx = uint(xyIdIx.y & 65536); // 16 bit index if (idx < colorIdx) { float fraction = float(idx) / float(colorIdx); // map to [0, 1) v_color = hue(float(idx) / float(colorIdx)); // color by table index } else { v_color = vec3(1.0); // default: white } gl_Position = vec4(vec2(pos) / screenScale, 0.0, 1.0); gl_PointSize = spotSize * 512.0 / max(screenScale.x, screenScale.y); }

You wouldn’t believe how long it took me to find my very obvious typo 🤦🏻‍♀️

The symptom was that the output looked red and white 🔴⚪️ when it was supposed to be rainbowey 🌈

16.03.2025 05:36 — 👍 1    🔁 0    💬 0    📌 0
In concept the edge detection problem is trivial. In terms of program time for lines and circles the problem is a small fraction of the total computational load of the system, but in terms of program debugging difficulty the problem was a lulu. For example, the computation of the intersection of a circle with any of the edges of the scope is easy, but computation of the intersection of a circle with all four edges may result in as many as eight intersections, same pairs of which maybe identical, the scope corners. Now which of these intersections are actually to be used as starts of circle arcs?

In concept the edge detection problem is trivial. In terms of program time for lines and circles the problem is a small fraction of the total computational load of the system, but in terms of program debugging difficulty the problem was a lulu. For example, the computation of the intersection of a circle with any of the edges of the scope is easy, but computation of the intersection of a circle with all four edges may result in as many as eight intersections, same pairs of which maybe identical, the scope corners. Now which of these intersections are actually to be used as starts of circle arcs?

“in terms of program debugging difficulty the problem
was a lulu.”
— Ivan Sutherland (1963!), “Sketchpad,” pg. 76

12.03.2025 03:53 — 👍 1    🔁 0    💬 0    📌 0
#canvas {
    width: auto;
    height: 100%;
}
@media (max-aspect-ratio: 4/3) {
    #canvas {
        width: 100%;
        height: auto;
    }
}

#canvas { width: auto; height: 100%; } @media (max-aspect-ratio: 4/3) { #canvas { width: 100%; height: auto; } }

I figured out how to keep my fixed-aspect canvas centered but as-large-as-possible in pure CSS 🥳

(I didn’t want to use object-fit because it distorts JS event positions)

Try it here (resize the window or turn your phone) codefrau.github.io/Smalltalk78/...

06.03.2025 19:35 — 👍 1    🔁 0    💬 0    📌 0

Thank you

04.03.2025 08:27 — 👍 0    🔁 0    💬 0    📌 0

𝗖𝗼𝗱𝗲𝗳𝗿𝗮𝘂
𝘾𝙤𝙙𝙚𝙛𝙧𝙖𝙪
𝘊𝘰𝘥𝘦𝘧𝘳𝘢𝘶
CODEFRAU
ᴄᴏᴅᴇꜰʀᴀᴜ
ᶜᵒᵈᵉᶠʳᵃᵘ
ℭ𝔬𝔡𝔢𝔣𝔯𝔞𝔲
𝕮𝖔𝖉𝖊𝖋𝖗𝖆𝖚
𝙲𝙾𝙳𝙴𝙵𝚁𝙰𝚄
ᑕOᗪEᖴᖇᗩᑌ
𝓒𝓞𝓓𝓔𝓕𝓡𝓐𝓤

🅒🅞🅓🅔🅕🅡🅐🅤

🅲🅾🅳🅴🅵🆁🅰🆄

ⒸⓄⒹⒺⒻⓇⒶⓊ

🄲🄾🄳🄴🄵🅁🄰🅄

25.02.2025 00:41 — 👍 2    🔁 0    💬 0    📌 0

I see we had the same idea. Nice!

18.02.2025 23:25 — 👍 2    🔁 0    💬 0    📌 0

In a way I like this best because it’s straightforward to explain:
* No damage? Nice, shield doesn’t break
* This attack breaks the shield? Okay, return the number of this attack
* Otherwise, this attack does damage, and we look at the next attack

I’ll admit that “straightforward” is … subjective 😇

18.02.2025 23:19 — 👍 1    🔁 0    💬 0    📌 0
findShieldBreak = (dmgs, shld, pos=0) =>
    dmgs.length == 0 ? -1
    : shld <= dmgs[0] ? pos
    : findShieldBreak(dmgs.slice(1), shld - dmgs[0], pos + 1)

findShieldBreak = (dmgs, shld, pos=0) => dmgs.length == 0 ? -1 : shld <= dmgs[0] ? pos : findShieldBreak(dmgs.slice(1), shld - dmgs[0], pos + 1)

Played a bit more – recursion is fun!

👸🏻🛡️
🐢🐢🐢
🐢🐢
🐢
💃🏻

codepen.io/codefrau/pen...

18.02.2025 06:31 — 👍 1    🔁 0    💬 1    📌 0
findShieldBreak = (dmgs, shld) => 
    dmgs.findIndex(dmg => (shld -= dmg) < 0)

findShieldBreak = (dmgs, shld) => dmgs.findIndex(dmg => (shld -= dmg) < 0)

findShieldBreak = (dmgs, shld) =>
dmgs.findIndex(dmg => (shld -= dmg) < 0)

👸🏻🛡️🔥🔥🔥🐉

codepen.io/codefrau/pen...

17.02.2025 10:02 — 👍 4    🔁 0    💬 2    📌 0

Especially using single digit numbers to avoid having to tokenize was brilliant. It let us focus on the actual problem instead of incidental complexity

10.02.2025 21:15 — 👍 1    🔁 0    💬 0    📌 0

It’s not very readable, admittedly, even though it’s very succinct. But whittling it down to almost a one-liner was a fun exercise. Thank you for the prompt!

10.02.2025 21:12 — 👍 2    🔁 0    💬 1    📌 0

Okay now that I’ve seen all the other submissions I wonder if an actual interviewer would object to my use of `eval()`. Then again, the `splice(-2)` is neat to get the operands in the right order for sub/div. They should appreciate that

10.02.2025 06:38 — 👍 2    🔁 0    💬 2    📌 0

It’s been a while, yes, but I’m still reading your letter every week. One of the few highlights right now 💜

04.02.2025 22:57 — 👍 1    🔁 0    💬 0    📌 0
Preview
Reverse Polish notation - Wikipedia

It’s how you combine subexpressions in RPN (see en.m.wikipedia.org/wiki/Reverse...)

Try this:

evaluatePostfix('123*+123++*')

04.02.2025 20:28 — 👍 3    🔁 0    💬 0    📌 0

Clever! But evaluatePostfix('123++') should be 6 🤓

04.02.2025 20:13 — 👍 2    🔁 0    💬 1    📌 0
Screenshot of the codepen and its output

Screenshot of the codepen and its output

That was fun!

function evaluatePostfix(s) {
let a = []
for (let c of s)
a.push(isNaN(+c) ? eval(a.splice(-2).join(c)) : c);
return a.pop()
}

My CodePen does the infix conversion first and evals at the end:

codepen.io/codefrau/pen...

04.02.2025 19:49 — 👍 5    🔁 0    💬 2    📌 0
JWT.IO JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

When I work with JWTs this is incredibly helpful: jwt.io

30.01.2025 09:19 — 👍 1    🔁 0    💬 0    📌 0

This is one of the many awesome projects you can play with at squeak.js.org/etoys/ which has the 2005 version of Etoys running on my virtual machine.

It’s in the Project Gallery (3rd row, 3rd item)

28.01.2025 21:01 — 👍 3    🔁 0    💬 0    📌 0
Selfie of me smiling into the camera with asymmetric, purple hair, matching purple lipstick and glasses, in a navy summer dress with small flower ornaments, a golden necklace with a V pendant sitting on a bench in front of an ivy-covered wall

Selfie of me smiling into the camera with asymmetric, purple hair, matching purple lipstick and glasses, in a navy summer dress with small flower ornaments, a golden necklace with a V pendant sitting on a bench in front of an ivy-covered wall

Trying a new profile picture

www.instagram.com/p/CvqRxdlPGsg/

28.11.2024 23:37 — 👍 2    🔁 0    💬 0    📌 0

Ohhhhh amazing list 😍

28.11.2024 18:02 — 👍 2    🔁 0    💬 1    📌 0

Thank you for this Award, and congrats to my co-authors! It’s been an incredible 10 years.

Check out SqueakJS at squeak.js.org

14.11.2024 00:42 — 👍 11    🔁 2    💬 0    📌 0

@codefrau is following 20 prominent accounts