<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Laura Norwood</title>
    <description>The latest articles on DEV Community by Laura Norwood (@lanthanum89).</description>
    <link>https://dev.to/lanthanum89</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3223395%2F09743f6b-a550-4bd5-9133-ba974e7003c9.jpg</url>
      <title>DEV Community: Laura Norwood</title>
      <link>https://dev.to/lanthanum89</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lanthanum89"/>
    <language>en</language>
    <item>
      <title>👻 Ghost in the House 🎃</title>
      <dc:creator>Laura Norwood</dc:creator>
      <pubDate>Wed, 28 Oct 2026 18:21:44 +0000</pubDate>
      <link>https://dev.to/lanthanum89/ghost-in-the-house-312j</link>
      <guid>https://dev.to/lanthanum89/ghost-in-the-house-312j</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Ghost in the House takes a night of smart home sensor events, picks the strangest with plain code, and asks an open-weight model running on your own machine to explain them as a short ghost story.&lt;/p&gt;

&lt;p&gt;The page is a surveyor's plan of a quiet house. A floor plan and a chart of the whole night sit beside the story. Every time the story names a moment ("01:58"), the plan and chart jump to it and show the house as the sensors recorded it: lamps, open doors, movement, the spare room turning cold. The raw record sits underneath, so you can check the story against the evidence line by line. A guided walkthrough takes first-time visitors through the four events, and a panel beside the plan says what changed, what the sensors recorded beforehand, and what remains unknown, all derived from the data.&lt;/p&gt;

&lt;p&gt;The night is fictional sample data shaped like Home Assistant history: 205 sensor readings, with four events nothing explains. A spare room light comes on with no motion recorded in the room. The hallway sensor fires while every tracked phone is home. The spare room drops 6 degrees in ten minutes. The back door opens with no motion recorded before it.&lt;/p&gt;

&lt;p&gt;I tried to keep three kinds of claim apart, and the page labels them: what the sensors &lt;strong&gt;recorded&lt;/strong&gt;, what my six rules &lt;strong&gt;assume&lt;/strong&gt;, and what the &lt;strong&gt;model&lt;/strong&gt; interpreted. A phone being at home does not prove anyone is asleep, and no recorded motion does not prove nobody moved, so the page says "no motion recorded" and nothing stronger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmkdp9yr4pnz47g1e1yb8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmkdp9yr4pnz47g1e1yb8.jpg" alt=" " width="800" height="1247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvbkvpqspjyvzyb5l5tfc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvbkvpqspjyvzyb5l5tfc.jpg" alt=" " width="800" height="1379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Live page: &lt;a href="https://lanthanum89.github.io/Ghost-in-the-Machine/" rel="noopener noreferrer"&gt;https://lanthanum89.github.io/Ghost-in-the-Machine/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It opens with a recorded story that plays straight away, so nothing needs installing. The Live mode asks your own Ollama model for a fresh story and checks that Ollama is running before you press anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Lanthanum89" rel="noopener noreferrer"&gt;
        Lanthanum89
      &lt;/a&gt; / &lt;a href="https://github.com/Lanthanum89/Ghost-in-the-Machine" rel="noopener noreferrer"&gt;
        Ghost-in-the-Machine
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Ghost in the House&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A night of smart home sensor events goes in. A short ghost story comes out, written by an open-weight model running on your own machine.&lt;/p&gt;
&lt;p&gt;Built for the Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine.&lt;/p&gt;
&lt;p&gt;The page is a surveyor's plan of the house. The story streams in beside a floor plan and a chart of the whole night, and every time the story names a moment ("01:58") the plan and chart move to it, showing the lamps, doors, movement and temperatures as they were. The four marked events are numbered and linked in time order (the link shows sequence, not a tracked route), and the raw sensor record sits underneath.&lt;/p&gt;
&lt;p&gt;The page opens on the quiet house just after lights out. A guided &lt;strong&gt;walkthrough&lt;/strong&gt; takes you through the four marked events one at a time. A panel beside the plan says what…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Lanthanum89/Ghost-in-the-Machine" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The rule I started with: the model never sees raw logs and never decides what is spooky.&lt;/p&gt;

&lt;p&gt;Plain TypeScript filters the night's events, scores them with six explainable rules (night-time, no motion recorded before it, phones at home, rarity, sudden change, routine chatter) and picks about 20. Each point has a stated reason, and the page lists the rules. The model only narrates that short, pre-selected timeline, written as plain English with no scores or rule names. Choosing those events still shapes the story, and the page says so.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; a small open-weight instruct model through Ollama, &lt;code&gt;llama3.1:8b&lt;/code&gt; by default and one setting to change. Low-ish temperature, capped length, and a system prompt fixing a dry, understated British voice that tells it to say "no motion was recorded" rather than claim nobody was there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inference:&lt;/strong&gt; Ollama's streaming &lt;code&gt;/api/chat&lt;/code&gt;, called straight from the browser. No cloud AI calls anywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The plan and chart:&lt;/strong&gt; a replay of the sensor history, computed in code. A small parser finds times like &lt;code&gt;01:58&lt;/code&gt; in the story as it streams and moves the chart to the matching moment. The model decides nothing visual.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App:&lt;/strong&gt; TypeScript, React, Vite, Tailwind and Vitest, as an installable PWA that opens offline. The type is IM Fell Double Pica for titles, Atkinson Hyperlegible for reading and IBM Plex Mono for data, all bundled open-licensed files, so nothing loads from a CDN.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Home Assistant:&lt;/strong&gt; &lt;code&gt;src/data/ha-client.ts&lt;/code&gt; is a stub for the real history API. It has never been run against a real Home Assistant, and the README and code both say so.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Sensor data shows when a house is empty and when people are likely asleep. That should not go to someone else's server.&lt;/p&gt;

&lt;p&gt;An open-weight model on your own network means the data never leaves the house, the tool works with the internet off, and it keeps working if a hosted service changes or disappears. The model is a setting you can swap. And because the selection step is ordinary code, you can read why each event was chosen, which makes it easier to see where the story comes from and where it does not.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>halloween</category>
      <category>ai</category>
    </item>
    <item>
      <title>Woof Are You, Really? A Dog Personality Quiz Built in a Weekend</title>
      <dc:creator>Laura Norwood</dc:creator>
      <pubDate>Fri, 14 Aug 2026 19:14:03 +0000</pubDate>
      <link>https://dev.to/lanthanum89/woof-are-you-really-a-dog-personality-quiz-built-in-a-weekend-4ep6</link>
      <guid>https://dev.to/lanthanum89/woof-are-you-really-a-dog-personality-quiz-built-in-a-weekend-4ep6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-08-13"&gt;Weekend Challenge: Dog Days Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Which Dog Are You Today?&lt;/strong&gt; — a tiny, silly personality quiz. Five daft questions about your Saturday mornings, your feelings on doorbells, and your ideal compliment, and you get crowned as one of five dog breeds: Golden Retriever, Corgi, Greyhound, Border Collie, or Pug. The goal was pure low-stakes fun with no login, no backend, no tracking — just open it, answer five questions, and get told which dog you are today. (Not forever. Today. Check back tomorrow — you might be a different dog.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://lanthanum89.github.io/dev.to-weekend-doggos/"&gt;Live demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🐾 The lineup:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Breed&lt;/th&gt;
&lt;th&gt;You are...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🟡 Golden Retriever&lt;/td&gt;
&lt;td&gt;Boundless joy, zero impulse control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟠 Corgi&lt;/td&gt;
&lt;td&gt;Short legs, tall opinions, runs the house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔵 Greyhound&lt;/td&gt;
&lt;td&gt;Capable of 40mph, choosing 0mph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟢 Border Collie&lt;/td&gt;
&lt;td&gt;Rest is a bug, not a feature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟣 Pug&lt;/td&gt;
&lt;td&gt;Didn't ask to be this glamorous, happened anyway&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Lanthanum89" rel="noopener noreferrer"&gt;
        Lanthanum89
      &lt;/a&gt; / &lt;a href="https://github.com/Lanthanum89/dev.to-weekend-doggos"&gt;
        dev.to-weekend-doggos
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Five daft questions. One inevitable truth about your energy levels.  This is a tiny, silly personality quiz built for the DEV.to Weekend Doggos challenge. Answer questions about your Saturday mornings, your feelings on doorbells, and your ideal compliment — and find out which dog breed you truly are today. (Not forever. Today.) 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🐶 Which Dog Are You Today?&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Five daft questions. One inevitable truth about your energy levels.&lt;/p&gt;
&lt;p&gt;This is a tiny, silly personality quiz built for the &lt;a href="https://dev.to/" rel="nofollow"&gt;DEV.to Weekend Doggos challenge&lt;/a&gt;. Answer questions about your Saturday mornings, your feelings on doorbells, and your ideal compliment — and find out which dog breed you truly are today. (Not forever. Today. Check back tomorrow, you might be a different dog.)&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🐾 The lineup&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Breed&lt;/th&gt;
&lt;th&gt;You are...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🟡 Golden Retriever&lt;/td&gt;
&lt;td&gt;Boundless joy, zero impulse control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟠 Corgi&lt;/td&gt;
&lt;td&gt;Short legs, tall opinions, runs the house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔵 Greyhound&lt;/td&gt;
&lt;td&gt;Capable of 40mph, choosing 0mph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟢 Border Collie&lt;/td&gt;
&lt;td&gt;Rest is a bug, not a feature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟣 Pug&lt;/td&gt;
&lt;td&gt;Didn't ask to be this glamorous, happened anyway&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Answer 5 questions, scores tally up behind the scenes, and whichever dog you matched hardest with gets crowned your spirit animal (ties broken at random, because chaos is thematically appropriate here).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🛠&lt;/h2&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Lanthanum89/dev.to-weekend-doggos"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The stack is deliberately small: &lt;strong&gt;React 19 + TypeScript&lt;/strong&gt;, &lt;strong&gt;Vite&lt;/strong&gt; for dev/build, and &lt;strong&gt;Tailwind CSS 4&lt;/strong&gt; for the bold, hand-drawn look. Deploys happen automatically to &lt;strong&gt;GitHub Pages&lt;/strong&gt; on every push to &lt;code&gt;main&lt;/code&gt; via GitHub Actions.&lt;/p&gt;

&lt;p&gt;A few decisions worth calling out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scoring is a simple tally, not a decision tree.&lt;/strong&gt; Each answer bumps a per-breed counter (&lt;code&gt;scores[breedId]++&lt;/code&gt;), and after the last question the breed(s) with the highest score win. It's a flat array of five integers — easy to reason about and easy to extend with a new breed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ties are broken at random&lt;/strong&gt;, not by array order, because letting the "first" breed always win on a tie felt thematically wrong for a quiz about chaos and personality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No illustration library.&lt;/strong&gt; The dog faces are hand-rolled SVGs (&lt;code&gt;&amp;lt;DogFace /&amp;gt;&lt;/code&gt;) that take a &lt;code&gt;color&lt;/code&gt; and an &lt;code&gt;earStyle&lt;/code&gt; (&lt;code&gt;floppy&lt;/code&gt; | &lt;code&gt;pointy&lt;/code&gt; | &lt;code&gt;folded&lt;/code&gt; | &lt;code&gt;droop&lt;/code&gt;) as props, so each breed gets a distinct face just by composing the same component differently — mostly &lt;code&gt;transform: rotate()&lt;/code&gt; on ear paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content is fully data-driven.&lt;/strong&gt; Breeds and questions live in &lt;code&gt;src/data.ts&lt;/code&gt; as plain arrays/objects. Adding a new dog means adding a &lt;code&gt;Breed&lt;/code&gt; entry and referencing its &lt;code&gt;id&lt;/code&gt; from question options — no component changes needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Oxlint&lt;/strong&gt; for fast linting, keeping the toolchain lightweight for a weekend build.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;Not submitting to any prize categories.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>doggos</category>
      <category>dog</category>
    </item>
    <item>
      <title>My CSS Art Made Some Foodie Friends 🍙🧋🥟🍲</title>
      <dc:creator>Laura Norwood</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:59:34 +0000</pubDate>
      <link>https://dev.to/lanthanum89/my-css-art-made-some-foodie-friends-4adk</link>
      <guid>https://dev.to/lanthanum89/my-css-art-made-some-foodie-friends-4adk</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2026-07-29"&gt;Frontend Challenge - Comfort Food Edition, CSS Art&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;Comfort food isn't just one dish, so instead of picking one I built the whole spread and gave it somewhere to live: a dark, neon-lit restaurant with a digital menu display. &lt;strong&gt;Onigiri&lt;/strong&gt;, &lt;strong&gt;Boba Tea&lt;/strong&gt;, &lt;strong&gt;Gyoza&lt;/strong&gt;, and &lt;strong&gt;Hot Pot&lt;/strong&gt; double as the menu items, each with a price tag, blinking and bouncing on a glowing CRT-style screen. Underneath, a touchscreen self-order kiosk — the kind you'd find at any fast-food counter — asks "Can I take your order?" and prints out a ticket with your order number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/Laura-Norwood/embed/PwWvZBW?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Live demo: &lt;a href="https://lanthanum89.github.io/dev.to-Frontend-Challenge-Comfort-Food-Edition/"&gt;https://lanthanum89.github.io/dev.to-Frontend-Challenge-Comfort-Food-Edition/&lt;/a&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/Lanthanum89/dev.to-Frontend-Challenge-Comfort-Food-Edition"&gt;https://github.com/Lanthanum89/dev.to-Frontend-Challenge-Comfort-Food-Edition&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every character bounces on its own, blinking every few seconds — click one and it gets happy &lt;code&gt;^^&lt;/code&gt; eyes plus a burst of sparkles, right there on the menu screen. Give the kiosk below a few seconds and watch it type out its prompt, pulse its order button, and print a receipt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;Everything is &lt;code&gt;div&lt;/code&gt;s built with &lt;code&gt;clip-path&lt;/code&gt; / &lt;code&gt;border-radius&lt;/code&gt; + gradients and CSS animations, with a single small vanilla-JS click handler for the food characters (the challenge allows "a sprinkle of JavaScript," so I kept it to exactly one interaction and pushed everything else — including the kiosk's whole sequence — into pure CSS):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shared rig&lt;/strong&gt;: every character is a &lt;code&gt;.character&lt;/code&gt; wrapper with the same &lt;code&gt;.face&lt;/code&gt; / &lt;code&gt;.eye&lt;/code&gt; / &lt;code&gt;.cheek&lt;/code&gt; / &lt;code&gt;.mouth&lt;/code&gt; parts, the same infinite &lt;code&gt;float&lt;/code&gt; bounce, the same blink timing, and the same &lt;code&gt;squish&lt;/code&gt; + sparkle-burst reaction on click. Building this as one reusable system — instead of one-off pieces — is what made it possible to add multiple characters without the CSS ballooning out of control. Each character only overrides shape, color, and face position.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onigiri&lt;/strong&gt;: a &lt;code&gt;clip-path&lt;/code&gt; rounded triangle with a &lt;code&gt;radial-gradient&lt;/code&gt; dot texture for rice grains and a separate nori-band trapezoid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boba Tea&lt;/strong&gt;: a tapered cup (&lt;code&gt;clip-path&lt;/code&gt; polygon) with a striped straw, a domed lid, and tapioca pearls scattered along the bottom via absolutely-positioned circles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gyoza&lt;/strong&gt;: a squashed dome shape, seared with layered &lt;code&gt;radial-gradient&lt;/code&gt;s on the bottom half, and scalloped pleats along the top edge made from a repeating dot pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot Pot&lt;/strong&gt;: a broth bowl split red/clear with a hard-edged &lt;code&gt;linear-gradient&lt;/code&gt;, sitting in a separate metal "band" (with rivets) below it, ring handles on both sides, and a rising-steam animation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The restaurant scene&lt;/strong&gt;: a flickering neon "COMFORT FOOD" sign (layered &lt;code&gt;text-shadow&lt;/code&gt; glow + a subtle opacity &lt;code&gt;@keyframes flicker&lt;/code&gt;), a screen bezel with a &lt;code&gt;repeating-linear-gradient&lt;/code&gt; scanline overlay for that CRT feel, and a wood counter underneath.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The self-order kiosk&lt;/strong&gt;: entirely CSS-driven and timed with &lt;code&gt;animation-delay&lt;/code&gt; so it plays out like a little sequence on page load — "Can I take your order?" types itself out letter by letter using the classic &lt;code&gt;width: 0 → Nch&lt;/code&gt; + &lt;code&gt;steps(N, end)&lt;/code&gt; typewriter trick (no JS, no per-letter markup), the "TAP TO ORDER" button pulses with an expanding-ring &lt;code&gt;box-shadow&lt;/code&gt; plus a radial-gradient "ripple," and a receipt slides down and prints its order number one digit at a time, torn edge included via a repeating diagonal-gradient background.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest lesson: getting the &lt;em&gt;shared&lt;/em&gt; character mechanics right first (float, blink, squish, sparkle burst) meant each new food was mostly "draw a shape and drop it into the rig" — and having that solid meant I could spend the JS-light budget entirely on the kiosk's CSS choreography instead.&lt;/p&gt;

&lt;p&gt;Next up: I'd like the kiosk's order number to actually reflect whichever dish you last tapped, and maybe have the characters glance toward the kiosk when its button pulses.&lt;/p&gt;

&lt;p&gt;Thanks for reading — go tap the kiosk. 🍙&lt;/p&gt;

</description>
      <category>css</category>
      <category>devchallenge</category>
      <category>showdev</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>Women in Tech: Global Map 🌍💖</title>
      <dc:creator>Laura Norwood</dc:creator>
      <pubDate>Fri, 17 Apr 2026 15:11:07 +0000</pubDate>
      <link>https://dev.to/lanthanum89/women-in-tech-global-map-3f0p</link>
      <guid>https://dev.to/lanthanum89/women-in-tech-global-map-3f0p</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-04-16"&gt;Weekend Challenge: Earth Day Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Women in Tech — Global Map&lt;/strong&gt; 🌍💖&lt;/p&gt;

&lt;p&gt;An interactive, pixelated 3D globe that visualizes the percentage of the tech workforce that is female in countries around the world. The project highlights the global gender gap in technology through a beautiful pink-themed, retro-pixel aesthetic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3D Rotating Globe&lt;/strong&gt; — A low-poly, flat-shaded icosahedron globe that auto-rotates and can be dragged to explore&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;57 Country Data Points&lt;/strong&gt; — Pixelated box columns rise from each country, with height and color mapped to female tech participation rates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Tooltips&lt;/strong&gt; — Hover over any country marker to see its name, percentage, region, and a progress bar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stats Panel&lt;/strong&gt; — Live stats including global average, country count, highest (Philippines 46%), and lowest (Pakistan 9%)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pixelated Retro Style&lt;/strong&gt; — Low pixel ratio rendering, flat shading, scanline overlay, "Press Start 2P" pixel font, and crisp-edges rendering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pink Aesthetic&lt;/strong&gt; — Entire color palette in shades of pink, magenta, and rose — from the deep dark background to glowing markers and star field&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;index.html&lt;/code&gt; in any modern browser — no build step or server required!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqb5n2qe6vdborlsthrln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqb5n2qe6vdborlsthrln.png" alt="a pixelated pink globe showing percentage of females in tech jobs across different countries " width="800" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Lanthanum89/earth-day-dev-submission" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A single &lt;code&gt;index.html&lt;/code&gt; file using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Three.js&lt;/strong&gt; (v0.170) for 3D rendering via ES module imports from CDN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OrbitControls&lt;/strong&gt; for drag-to-rotate and scroll-to-zoom interaction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure CSS&lt;/strong&gt; for the pixel UI, scanline overlay, and pink theme&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline data&lt;/strong&gt; sourced from World Bank, UNESCO, Deloitte, and McKinsey reports (approximate figures)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The globe is an &lt;code&gt;IcosahedronGeometry&lt;/code&gt; with flat shading to get a low-poly, pixelated look. The renderer pixel ratio is intentionally set low (&lt;code&gt;1/3&lt;/code&gt;) so the entire canvas renders at a fraction of screen resolution and is scaled up with &lt;code&gt;image-rendering: pixelated&lt;/code&gt; — giving everything that chunky retro-pixel feel.&lt;/p&gt;

&lt;p&gt;Each country is represented by a &lt;code&gt;BoxGeometry&lt;/code&gt; column positioned on the globe surface using lat/lon → spherical coordinate conversion. Column height and color both encode the female tech workforce percentage, creating a gradient from deep magenta (low %) to bright pink (high %).&lt;/p&gt;

&lt;p&gt;A raycaster handles mouse hover detection on the 3D markers, showing a pixel-bordered tooltip with country details. The scene includes a pink star field, latitude/longitude grid lines, a glow shell, and a CSS scanline overlay for extra retro vibes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;Best Use of GitHub Copilot&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>womenintech</category>
      <category>wecoded</category>
    </item>
    <item>
      <title>Useless Enterprise App</title>
      <dc:creator>Laura Norwood</dc:creator>
      <pubDate>Tue, 07 Apr 2026 11:31:25 +0000</pubDate>
      <link>https://dev.to/lanthanum89/useless-enterprise-app-4dib</link>
      <guid>https://dev.to/lanthanum89/useless-enterprise-app-4dib</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rm70cman31ygfz5vhjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rm70cman31ygfz5vhjz.png" alt="a tacky noughties business app" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a Useless Enterprise App™ that looks dangerously close to something you’d be forced to use at work… but is entirely designed to waste your time.&lt;/p&gt;

&lt;p&gt;It’s a React-based “Business Request Alignment Interface” that simulates a full corporate workflow, complete with forms, approvals, dashboards, and system feedback. None of it actually achieves anything.&lt;/p&gt;

&lt;p&gt;&lt;b&gt; Key features (all technically functional, strategically pointless): &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Save button that runs away from you when you try to click it&lt;/li&gt;
&lt;li&gt;A form that introduces new mandatory fields after submission&lt;/li&gt;
&lt;li&gt;A fake approval process requiring an “Approval Readiness Reference Code” that never existed&lt;/li&gt;
&lt;li&gt;A progress bar that confidently tracks nothing&lt;/li&gt;
&lt;li&gt;A system status panel that cycles through corporate nonsense like “Consulting the alignment committee…”&lt;/li&gt;
&lt;li&gt;Error messages such as: “Success could not be completed successfully”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not broken. It’s just… like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Demo: Best experienced emotionally rather than functionally.&lt;/p&gt;

&lt;p&gt;&lt;b&gt; Run locally and experience: &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fill in the form like a responsible adult&lt;/li&gt;
&lt;li&gt;Try to click “Save” while it actively avoids you&lt;/li&gt;
&lt;li&gt;Discover a new required field that wasn’t there before&lt;/li&gt;
&lt;li&gt;Finally submit… and get a failure toast anyway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s basically every bad internal system distilled into one app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Lanthanum89" rel="noopener noreferrer"&gt;
        Lanthanum89
      &lt;/a&gt; / &lt;a href="https://github.com/Lanthanum89/useless-enterprise-app" rel="noopener noreferrer"&gt;
        useless-enterprise-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Submission for the DEV April Fools Challenge. A React-based “Business Request Alignment Interface” that simulates a full corporate workflow, complete with forms, approvals, dashboards, and system feedback. None of it actually achieves anything.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026" rel="nofollow"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What I Built&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;I built a Useless Enterprise App™ that looks dangerously close to something you’d be forced to use at work… but is entirely designed to waste your time.&lt;/p&gt;
&lt;a rel="noopener noreferrer" href="https://private-user-images.githubusercontent.com/204180622/574638329-f97e5d17-fbad-4832-bd43-96072072f4d0.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODY2MjAwMTcsIm5iZiI6MTc4NjYxOTcxNywicGF0aCI6Ii8yMDQxODA2MjIvNTc0NjM4MzI5LWY5N2U1ZDE3LWZiYWQtNDgzMi1iZDQzLTk2MDcyMDcyZjRkMC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwODEzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDgxM1QxMTE1MTdaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0xZTk2MTMwMzg1MDg3NmE5MDIxNDI2ODYwOGExMjk0NjRlMDViMTVhYTg1MjczNmIyNGY1ZDc1NjcwNTEzNjE0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZwbmcifQ.V07L2_4brLnnPX_5MTnIiCtE5y0fpEQ31C4nbCkeP9Q"&gt;&lt;img width="2000" height="1422" alt="image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F204180622%2F574638329-f97e5d17-fbad-4832-bd43-96072072f4d0.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODY2MjAwMTcsIm5iZiI6MTc4NjYxOTcxNywicGF0aCI6Ii8yMDQxODA2MjIvNTc0NjM4MzI5LWY5N2U1ZDE3LWZiYWQtNDgzMi1iZDQzLTk2MDcyMDcyZjRkMC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwODEzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDgxM1QxMTE1MTdaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0xZTk2MTMwMzg1MDg3NmE5MDIxNDI2ODYwOGExMjk0NjRlMDViMTVhYTg1MjczNmIyNGY1ZDc1NjcwNTEzNjE0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZwbmcifQ.V07L2_4brLnnPX_5MTnIiCtE5y0fpEQ31C4nbCkeP9Q" class="js-gh-image-fallback"&gt;&lt;/a&gt;
&lt;p&gt;It’s a React-based “Business Request Alignment Interface” that simulates a full corporate workflow, complete with forms, approvals, dashboards, and system feedback. None of it actually achieves anything.&lt;/p&gt;
&lt;p&gt;Key features (all technically functional, strategically pointless):&lt;/p&gt;
&lt;p&gt;A Save button that runs away from you when you try to click it
A form that introduces new mandatory fields after submission
A fake approval process requiring an “Approval Readiness Reference Code” that never existed
A progress bar that confidently tracks nothing
A system status panel that cycles through corporate nonsense like “Consulting the alignment committee…”
Error messages such as: “Success could not be completed successfully”&lt;/p&gt;
&lt;p&gt;It’s not broken. It’s just… like this.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Demo…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Lanthanum89/useless-enterprise-app" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Everything behaves exactly as designed, which is the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;b&gt; Tech stack: &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;React (functional components + hooks)&lt;br&gt;
Pure frontend state, no backend, no persistence, no consequences&lt;br&gt;
Tailwind for layout, plus aggressively offensive inline styling&lt;/p&gt;

&lt;p&gt;&lt;b&gt; Approach: &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Model real enterprise UX patterns (forms, approvals, dashboards), then deliberately sabotage them&lt;br&gt;
Focus on process over outcome, just like real enterprise software&lt;/p&gt;

&lt;p&gt;&lt;b&gt; Design choices were intentional: &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Comic Sans + pastel gradients to simulate “legacy system that somehow still exists”&lt;br&gt;
Overcomplicated UI hierarchy with zero payoff&lt;br&gt;
Feedback loops that sound important but do nothing&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;p&gt;Community Favourite&lt;/p&gt;

&lt;p&gt;Because nothing unites developers faster than shared trauma from systems like this.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
