Jessica Carter, J.D. — I build reliable systems, solve ugly problems, and communicate clearly with both technical teams and business stakeholders. My background spans advanced technical support, infrastructure and operations, and legal/organizational leadership.
Solutions Engineer · Sales Engineer · Technical Account Manager · Customer Success Engineering · Implementation / Onboarding · Technical Program Management
J.D., Thomas R. Kline School of Law at Drexel University · B.A. Philosophy (minor: Classics), Central Washington University
Email: Jess@JessCarter.me · LinkedIn: jesscartertech
I’m a systems-level thinker with a bias toward shipping. I like clear specs, explicit tradeoffs, and reliability over vibes.
Collaboration + vibe coding. This background renderer was designed and shipped through tight collaboration between Jess (requirements, constraints, taste, and product direction) and Oracle — an AI agent running via Jess’s custom OpenClaw setup (implementation). It’s a concrete example of “vibe coding” done responsibly: rapid iteration with a strong feedback loop and explicit robustness constraints so the result behaves like a production UI element, not a novelty demo.
The idea. Render a calm, atmospheric background that supports the product rather than competing with it: fixed-position clouds that drift slowly, feel natural, and never react to pointer/scroll in a way that makes the page feel unstable.
Why It Matters. This is UI systems design: performance budgeting (simple canvas ops, requestAnimationFrame), accessibility (pointerEvents disabled; decorative canvas is aria-hidden), and product reliability (remove mouse/scroll coupling so the visual layer doesn’t create user-perceived “bugs”).
position: fixed canvas (so it feels anchored).requestAnimationFrame) — no mouse/scroll coupling.pointerEvents: "none" and aria-hidden.Jess: “Let’s keep tidying up the gateway. This needs a lot of work. The current background is shifting when I scroll or move the mouse pointer. I need that to stop.”
Jess: “I also want to get the clouds to look more natural, be larger, and move more slowly. They also need less glow, and no shadow.”
Oracle: “Remove mouse parallax… Make clouds larger, slower, more natural… Remove glow and shadow… Keep gentle drift only.”
Oracle: “Done — removed mouse tracking and parallax; made clouds ~2x larger and ~5x slower; removed shadow layer + bright glow; softened blur.”
Jess: “I'm seeing the new look. I just need them a bit brighter to stand out against the background.”
Oracle: “Done — brightened them slightly without bringing back glow or shadows.”
Problem. The background “swam” (parallax-like shifting) and the clouds read as synthetic (too small, too fast, too glowy).
Constraints. Keep it calm and anchored; don’t steal focus; don’t block clicks; keep the rendering model simple and performant.
Solution in code. The renderer below is intentionally built from a few stable primitives: a fixed canvas, a time-driven animation loop (requestAnimationFrame), slow drift + gentle turbulence, and blurred radial gradients for soft volumetric clouds — with no mouse/scroll coupling.
Outcome. The UI feels quieter and more “designed,” and the implementation is tunable (speeds/scales/opacity) without reintroducing instability.
// ---
// Gateway UI proof-of-work: Animated background (cloud drift)
//
// Key design points:
// - No mouse/scroll parallax (background should feel anchored, not “swim”)
// - Organic motion: slow drift + gentle turbulence (sine/cos), not jitter
// - Soft volumetric look: blurred radial gradients, no glow/shadow hacks
// ---
function initClouds(w: number, h: number): Cloud[] {
// A handful of “cloud actors” with different speeds/scales so motion feels layered.
return [
{ x: w * 0.05, y: h * 0.10, vx: 8, vy: 0.8, scale: 2.2, opacity: 0.40, turbFX: 0.06, turbFY: 0.04, turbAX: 12, turbAY: 6, turbPX: 0.0, turbPY: 1.2 },
{ x: w * 0.45, y: h * 0.22, vx: 5, vy: -0.5, scale: 1.8, opacity: 0.34, turbFX: 0.07, turbFY: 0.05, turbAX: 10, turbAY: 5, turbPX: 2.2, turbPY: 0.5 },
{ x: w * 0.75, y: h * 0.38, vx: 9, vy: 1.0, scale: 2.4, opacity: 0.36, turbFX: 0.05, turbFY: 0.03, turbAX: 14, turbAY: 7, turbPX: 1.4, turbPY: 2.6 },
{ x: w * 0.20, y: h * 0.58, vx: 4, vy: -0.4, scale: 1.6, opacity: 0.30, turbFX: 0.08, turbFY: 0.06, turbAX: 8, turbAY: 4, turbPX: 3.8, turbPY: 1.6 },
{ x: w * 0.90, y: h * 0.68, vx: 6, vy: 0.6, scale: 2.0, opacity: 0.33, turbFX: 0.06, turbFY: 0.04, turbAX: 11, turbAY: 5, turbPX: 1.0, turbPY: 3.5 },
];
}
function drawCloud(
ctx: CanvasRenderingContext2D,
cx: number, cy: number,
scale: number, opacity: number,
isDark: boolean,
) {
// Cloud “sprite” dimensions (scaled per cloud).
const W = 420 * scale;
const H = 220 * scale;
// Slightly brighter cloud body so it reads against the dark glass background.
// Note: this is *not* a glow; it’s just the base color of the gradients.
const [br, bg, bb] = isDark ? [120, 190, 255] : [105, 175, 245];
ctx.save();
ctx.globalAlpha = opacity;
// Soft volumetric look via blurred radial gradients (no shadows).
// Each puff is a gradient “blob” with alpha that fades to 0.
// Body: left puff
ctx.filter = "blur(28px)";
const left = ctx.createRadialGradient(cx - W * 0.22, cy, 0, cx - W * 0.22, cy, W * 0.38);
left.addColorStop(0.0, `rgba(${br},${bg},${bb},0.60)`);
left.addColorStop(0.5, `rgba(${br},${bg},${bb},0.24)`);
left.addColorStop(1.0, `rgba(${br},${bg},${bb},0.00)`);
ctx.fillStyle = left;
ctx.beginPath();
ctx.arc(cx - W * 0.22, cy, W * 0.38, 0, Math.PI * 2);
ctx.fill();
// Body: right puff
const right = ctx.createRadialGradient(cx + W * 0.20, cy + H * 0.03, 0, cx + W * 0.20, cy + H * 0.03, W * 0.34);
right.addColorStop(0.0, `rgba(${br},${bg},${bb},0.54)`);
right.addColorStop(0.5, `rgba(${br},${bg},${bb},0.22)`);
right.addColorStop(1.0, `rgba(${br},${bg},${bb},0.00)`);
ctx.fillStyle = right;
ctx.beginPath();
ctx.arc(cx + W * 0.20, cy + H * 0.03, W * 0.34, 0, Math.PI * 2);
ctx.fill();
// Body: centre mass
ctx.filter = "blur(22px)";
const centre = ctx.createRadialGradient(cx, cy + H * 0.04, 0, cx, cy + H * 0.04, W * 0.44);
const [lr, lg, lb] = isDark ? [150, 215, 255] : [135, 205, 250];
centre.addColorStop(0.0, `rgba(${lr},${lg},${lb},0.50)`);
centre.addColorStop(0.5, `rgba(${lr},${lg},${lb},0.20)`);
centre.addColorStop(1.0, `rgba(${lr},${lg},${lb},0.00)`);
ctx.fillStyle = centre;
ctx.beginPath();
ctx.arc(cx, cy + H * 0.04, W * 0.44, 0, Math.PI * 2);
ctx.fill();
// Soft highlight: upper
ctx.filter = "blur(18px)";
const hl = ctx.createRadialGradient(cx - W * 0.06, cy - H * 0.16, 0, cx - W * 0.06, cy - H * 0.16, W * 0.28);
hl.addColorStop(0.0, "rgba(235,245,255,0.42)");
hl.addColorStop(0.5, "rgba(220,238,255,0.18)");
hl.addColorStop(1.0, "rgba(200,220,245,0.00)");
ctx.fillStyle = hl;
ctx.beginPath();
ctx.arc(cx - W * 0.06, cy - H * 0.16, W * 0.28, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
This contrasted with my other major social experience growing up — hanging out with our local Star Trek club. Your Oma met your Papa in that club, started dating (the first movie they saw together was James Bond: Goldeneye), and she decided to stay with him because he was the Captain (it also helped that he was always a very kind and gentle soul). In the club, we would watch whatever episode of whatever Star Trek series had just been released that week (your Papa actually bought a very large satellite dish for the house so that he could record them early — before public release — so that the club could watch them on Saturday). We would hold meetings at members’ homes, and eventually, at larger meeting places when the group got too big to host everyone. After the episode, we would have spaghetti (a family tradition that your Urgroßvater on your Oma’s side started), or do a potluck. We would play games, have fun, and engage in lively discussion about the issues raised by the episode we had watched and analogize them to the issues of the day.
Speckled with blood, and marred in mire,