<?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: Zara</title>
    <description>The latest articles on DEV Community by Zara (@madebyzara).</description>
    <link>https://dev.to/madebyzara</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%2F10295%2FElFTt-So.jpg</url>
      <title>DEV Community: Zara</title>
      <link>https://dev.to/madebyzara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/madebyzara"/>
    <language>en</language>
    <item>
      <title>Sloth Mode: a game you win by moving slowly</title>
      <dc:creator>Zara</dc:creator>
      <pubDate>Sun, 25 Oct 2026 09:40:04 +0000</pubDate>
      <link>https://dev.to/madebyzara/sloth-mode-a-game-you-win-by-moving-slowly-3717</link>
      <guid>https://dev.to/madebyzara/sloth-mode-a-game-you-win-by-moving-slowly-3717</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Sloth Mode is a webcam game where a sloth climbs a vine only while you move slowly and smoothly. Rush, and the sloth holds on while the vine sways. Stop, and it falls asleep. Slow and steady gets you to the treetop.&lt;/p&gt;

&lt;p&gt;I built it for Week 3 of the DEV Hacktoberfest Open-Source AI Challenge, “Slow and Steady”. Everything runs on your own machine: an open-source pose model in the browser, and Gemma, an open-weight model, through Ollama.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why slow movement
&lt;/h3&gt;

&lt;p&gt;My starting point was a simple idea: move with intention. I like exercising, and most training tells you to go faster, lift more, do one more rep. So I started reading about somatic exercises, where the point is the opposite: slow, controlled movement and paying attention to how it feels.&lt;/p&gt;

&lt;p&gt;I wanted to build something where you &lt;em&gt;have&lt;/em&gt; to move slowly. Not a timer telling you to slow down, but something that only works when you do. The hard part is that slow movement can feel like nothing is happening, so I made it a game. You watch a sloth, the slowest climber there is, and it only climbs when you match its pace.&lt;/p&gt;

&lt;p&gt;That fit the week’s theme almost too well. In Sloth Mode, laziness, or at least slowness, is how you win.&lt;/p&gt;

&lt;h3&gt;
  
  
  What a session looks like
&lt;/h3&gt;

&lt;p&gt;One session takes a few minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;How do you feel?&lt;/strong&gt; You type a few words, like “stiff shoulders after a long day at the laptop”, and choose how many minutes you have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick one of three.&lt;/strong&gt; Gemma suggests three movements from a library of twelve, such as a side arm raise, a slow squat, a roll-down or a bridge. Each card has a pace, a number of reps and one line about why it suits how you feel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch the pace once.&lt;/strong&gt; A stick figure shows the movement at the chosen speed. Then it gets out of the way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Climb.&lt;/strong&gt; The camera watches you move. A meter at the bottom of the video shows whether you’re still, at sloth pace or rushing, and the sloth climbs, clings on or naps to match. While you climb, Gemma’s cues rotate under the video (“Breathe deeply as your arms rise.”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reach the treetop.&lt;/strong&gt; The end screen shows your climbing time, how often you rushed and napped, and where in the movement you tended to rush. Gemma reads that summary and writes a short reflection with one suggestion for next time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Who gets to be lazier:&lt;/strong&gt; you. There’s no routine to plan, no reps to count and no clock to watch. You say how you feel, Gemma picks the movement and the pace, and the sloth keeps time for you: if it’s climbing, you’re doing it right.&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%2F2wlagap7xxayzb9tj8hi.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2wlagap7xxayzb9tj8hi.png" alt="A text window asking how you feel, so some exercises will be chosen for you" width="800" height="406"&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%2Fhb5poynw92ynedg2a7nc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhb5poynw92ynedg2a7nc.png" alt="Exercise chosen, shows a stick figure of how to do it and a button to start camera" width="800" height="403"&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%2Fgikntck3p1olcuq5bmpc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgikntck3p1olcuq5bmpc.png" alt="Person doing said exercise, reaching hands above head. A sloth is climbing on a vine on the right and shows percentage of completion" width="800" height="517"&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%2Flg1z0o9zbvglqajqbd6i.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flg1z0o9zbvglqajqbd6i.png" alt="Person doing thumbs up, completed exercise shows a summary of how long it took" width="800" height="407"&gt;&lt;/a&gt;&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/zarasyversen" rel="noopener noreferrer"&gt;
        zarasyversen
      &lt;/a&gt; / &lt;a href="https://github.com/zarasyversen/Sloth-Mode" rel="noopener noreferrer"&gt;
        Sloth-Mode
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Move slow and with intent, just like a sloth 
    &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;Sloth Mode 🦥&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A slow-movement exercise app. Your webcam watches you do a slow somatic movement, and a sloth climbs a vine only while you move slowly and smoothly. If you rush, it holds on and the vine sways. If you stop, it naps. Slow and steady wins the race.&lt;/p&gt;
&lt;p&gt;Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 3: “Slow and Steady”.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;MediaPipe sees, my code judges, Gemma coaches.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MediaPipe Pose&lt;/strong&gt; runs in your browser and finds body landmarks on every frame. Video never leaves the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain JavaScript&lt;/strong&gt; turns those landmarks into a joint angle and a speed, then decides whether the sloth is climbing, swaying or napping. It's deterministic and fast, with no AI call in the loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma&lt;/strong&gt; (open-weight, running locally in Ollama) picks three exercises from a fixed library based on how you feel, sets the pace and reps, writes cues, and…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/zarasyversen/Sloth-Mode" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The code is MIT-licensed on GitHub: &lt;a href="https://github.com/zarasyversen/Sloth-Mode" rel="noopener noreferrer"&gt;zarasyversen/Sloth-Mode&lt;/a&gt;. You need Node 20 or newer and &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma4:26b
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open &lt;code&gt;http://localhost:8000&lt;/code&gt;, tell the coach how you feel, and step back from the camera.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  MediaPipe sees, my code judges, Gemma coaches
&lt;/h3&gt;

&lt;p&gt;The one rule I set myself: the AI coaches, but it never judges your movement. Judging happens on every frame and has to be fast and fair, so it’s plain code.&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%2F03yoa8xfat74dqj53vh5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F03yoa8xfat74dqj53vh5.png" alt=" " width="799" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MediaPipe sees.&lt;/strong&gt; &lt;a href="https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker" rel="noopener noreferrer"&gt;MediaPipe Pose&lt;/a&gt; is open source and runs in the browser. On every video frame it returns the positions of 33 body landmarks, such as shoulders, elbows, hips and knees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My code judges.&lt;/strong&gt; Each exercise is defined by one measurement: an angle between three landmarks (shoulder, elbow, wrist for an arm raise) or the tilt of the torso. The code smooths that angle, works out its speed over the last half second, and compares it with the target speed, which is the movement’s range divided by the seconds per lift. Too slow and the sloth naps, too fast and it clings on, in between and it climbs. Short delays stop the state from flickering: rushing has to last 250 ms and napping 1.2 seconds. No model is involved, so the same movement always gets the same result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemma coaches.&lt;/strong&gt; Gemma runs in Ollama on your own computer and is used twice per session. Before it, Gemma turns how you feel into three exercise cards. After it, Gemma reads a summary like this one and writes a short reflection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exercise_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arms_overhead"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"seconds_per_lift"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"finished"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"climb_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rush_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nap_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rush_zone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the last third, near the full movement"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For that summary, Gemma wrote: “You tended to move a little too quickly as your arms reached the top of the movement.” Both calls use Ollama’s structured output with a JSON schema, and the exercise &lt;code&gt;id&lt;/code&gt; is an enum generated from the library, so Gemma can only pick movements the code knows how to measure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Honest tradeoffs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed is all it measures.&lt;/strong&gt; The game judges how fast a joint angle changes. It doesn’t yet measure smoothness, so a jerky movement at the right average speed still counts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The thresholds are tuned by feel.&lt;/strong&gt; “Rushing” starts at 1.6 times the target speed and “still” below a quarter of it. Those numbers came from testing on myself, not from a study.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Side-on movements are noisy.&lt;/strong&gt; The light pose model jitters on knees and ankles seen from the side. The slow squat can say “Too quick” while you stand still, because the jitter alone is faster than its very slow target speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 26B needs a capable machine.&lt;/strong&gt; The model is about 16 GB, and choosing three exercises takes around 16 seconds on my laptop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma can only choose, not invent.&lt;/strong&gt; The exercise &lt;code&gt;id&lt;/code&gt; in the JSON schema is an enum built from the library, and every answer is checked again in code. If an answer fails the checks, the app asks once more and then shows an error. That keeps Gemma safe, but also means it can’t suggest a movement I haven’t written measuring code for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What user feedback changed
&lt;/h3&gt;

&lt;p&gt;People who tried it said there was too much happening at once: a stick figure, a pace meter, a range bar, the sloth and sound. So I cut it down. The stick figure now shows the pace once, before you start. The pace meter moved onto the camera view and got bigger. The range bar, the sound and the pace slider are gone. Now you only have to watch yourself and the sloth.&lt;/p&gt;

&lt;p&gt;Next, I want to add a smoothness score so that jerky movement counts as rushing too, and calm down the jitter on side-on movements like the squat.&lt;/p&gt;

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

&lt;p&gt;A camera pointed at your body in your living room is about as personal as data gets. Open models let me keep all of it on your machine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your body data stays local.&lt;/strong&gt; The video never leaves the browser tab. The pose model runs in the page, and the only thing sent anywhere is a handful of numbers to Ollama on your own computer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model is swappable.&lt;/strong&gt; Gemma is one line in &lt;code&gt;coach.js&lt;/code&gt;. Any Ollama model that supports structured output can take its place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No per-use cost.&lt;/strong&gt; No API keys and no bill per session, so you can climb as often as you like.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(Almost) offline.&lt;/strong&gt; Once the page, the pose model and the fonts have loaded, the coaching runs with no internet. The first load still needs the internet to fetch the pose model and its runtime from a CDN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With a closed API, every plan and reflection would send how you feel and how your body moved to someone else’s server, cost money per call, and stop working when the network or the provider does. With Gemma in Ollama, the coach is a file on your own disk.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma.&lt;/strong&gt; Gemma 4 26B runs locally through Ollama and does all the coaching: it turns how you feel into three exercise cards with pace, reps and cues, and reflects on each session’s summary afterwards. Structured output with an enum of exercise ids keeps it to movements the code can measure.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Toado 🐸 a little garden helper for our first real garden</title>
      <dc:creator>Zara</dc:creator>
      <pubDate>Sat, 10 Oct 2026 16:40:32 +0000</pubDate>
      <link>https://dev.to/madebyzara/toado-a-little-garden-helper-for-our-first-real-garden-4de</link>
      <guid>https://dev.to/madebyzara/toado-a-little-garden-helper-for-our-first-real-garden-4de</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;This year my partner and I moved to a farm in Värmland, Sweden. The house dates from the early 1900s, and it came with our first real garden. It's a big one. There are fruit trees, bushes and beds, and a greenhouse. Quite a few of the plants were here long before us, and we honestly don't know what all of them are yet.&lt;/p&gt;

&lt;p&gt;My partner and I are both developers, so building something of our own for the farm felt like fun. &lt;strong&gt;Toado&lt;/strong&gt; is the small garden helper I built for us: me, my partner and maybe our son when he is older. I love frogs, so it got a toad.&lt;/p&gt;

&lt;p&gt;What I wanted it to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tell me what needs doing outside today.&lt;/strong&gt; It should base this on the season, the weather and what I've already done. It should remind me to open the greenhouse on a warm day, cover things on a frosty night, or water something I haven't watered for a while.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Help me understand the work.&lt;/strong&gt; I'd like a realistic picture of how much a garden this size needs, and when.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fill in what I don't know.&lt;/strong&gt; I can take a photo of a plant I don't recognise or a leaf that looks wrong, and ask about it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep a record&lt;/strong&gt; of what I've watered, pruned and harvested, and what happened to each plant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay local and mine.&lt;/strong&gt; The garden, the home and the photos stay on my own computer, and I can customise everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each morning Toado shows one card with a few jobs for today. Here's what it suggested on a windy October morning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Today in your garden&lt;/strong&gt;&lt;br&gt;
It looks like a windy and wet autumn day in Forshaga, but there is still plenty of light to get some clearing done. Grab your raincoat and let's tidy up the garden before the rain settles in!&lt;/p&gt;

&lt;p&gt;🧺 &lt;strong&gt;Harvest apples and pears.&lt;/strong&gt; Pick the pears while they are still firm and let them finish ripening indoors.&lt;br&gt;
🧹 &lt;strong&gt;Clear out the greenhouse plants.&lt;/strong&gt; Compost the healthy leaves from the finished tomatoes, squash, cucumber, radishes and mild chili so pests have nowhere to overwinter.&lt;br&gt;
🧹 &lt;strong&gt;Clear finished plants from pallet collars.&lt;/strong&gt; Compost the healthy leaves from the finished potatoes, peas, cabbage and broccoli…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I've done a job, I tick it and it goes into the log. Toado reads the log too: once I've watered something, it waits before suggesting it again.&lt;/p&gt;

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

&lt;p&gt;In this one-minute video I'm in the garden. I take a photo of the pallet collars I've just cleared and ask Gemma whether I can leave them like that over winter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/201d0daa-0c43-4d82-b76b-b93534b55aad" rel="noopener noreferrer"&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%2Fup9bcenvur21lhr0u2yr.jpg" alt="Gemma's answer about the pallet collars. Click to watch the video" width="600" height="1150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;▶️ &lt;a href="https://github.com/user-attachments/assets/fd8647ad-5136-495f-81fe-72254f2479eb" rel="noopener noreferrer"&gt;Watch the video (1 minute)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The day's plan, the same jobs all ticked off, and the log of what I did:&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%2Fqxk4c71s4r6ew230aywe.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%2Fqxk4c71s4r6ew230aywe.jpg" alt="Today's plan from Gemma" width="628" height="1200"&gt;&lt;/a&gt;&lt;br&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%2F4njo3god671cjg61cdbf.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%2F4njo3god671cjg61cdbf.jpg" alt="All of today's jobs done" width="598" height="1200"&gt;&lt;/a&gt;&lt;br&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%2Fisxjj38b8x08uwvc00ok.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%2Fisxjj38b8x08uwvc00ok.jpg" alt="The garden log" width="629" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Toado runs Gemma through Ollama on my own computer, so there's no hosted version to click through. I used it on my phone through Tailscale. If you'd like to try it, the README explains how to run it. The first screen has a &lt;strong&gt;demo garden&lt;/strong&gt; button that loads a garden like ours.&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/zarasyversen" rel="noopener noreferrer"&gt;
        zarasyversen
      &lt;/a&gt; / &lt;a href="https://github.com/zarasyversen/Toado" rel="noopener noreferrer"&gt;
        Toado
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Your little garden helper
    &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;Toado 🐸&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Your little garden helper.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Toado is a year-round garden to-do app with a toad on it. It looks at your own garden (trees, bushes, beds, greenhouse), the season and today's weather, then gives you a few short jobs to do outside. Gemma runs locally through Ollama, so your garden data stays on your machine.&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;A rainy October Saturday: Toado's plan for the day, then asking Gemma about the cleared pallet collars with a photo.&lt;/p&gt;

  
    
    &lt;span class="m-1"&gt;toado-demo.mp4&lt;/span&gt;
    
  

  

  


&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/zarasyversen/Toado/docs/images/app-today.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fzarasyversen%2FToado%2FHEAD%2Fdocs%2Fimages%2Fapp-today.jpg" alt="Today's plan" width="240"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/zarasyversen/Toado/docs/images/gemma-pallet-answer.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fzarasyversen%2FToado%2FHEAD%2Fdocs%2Fimages%2Fgemma-pallet-answer.jpg" alt="Gemma answering a photo question" width="240"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/zarasyversen/Toado/docs/images/app-log.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fzarasyversen%2FToado%2FHEAD%2Fdocs%2Fimages%2Fapp-log.jpg" alt="The garden log" width="240"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install &lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt; and pull a Gemma model:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;ollama pull gemma4:26b&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install dependencies and start the app:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;pnpm install
pnpm dev&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To use a different model, change &lt;code&gt;VITE_OLLAMA_MODEL&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Scripts&lt;/h2&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pnpm dev&lt;/code&gt;: start the dev server (proxies &lt;code&gt;/ollama&lt;/code&gt; to &lt;code&gt;localhost:11434&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pnpm test&lt;/code&gt;: run the unit tests&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pnpm build&lt;/code&gt;: type-check and build&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;License&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/zarasyversen/Toado/LICENSE" rel="noopener noreferrer"&gt;MIT&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/zarasyversen/Toado" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;It's Vite and TypeScript with no framework, plus 60 tests, and MIT licensed.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The open pieces:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4&lt;/strong&gt; (&lt;code&gt;gemma4:26b&lt;/code&gt;), running locally with &lt;strong&gt;Ollama&lt;/strong&gt; on my Mac.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-Meteo&lt;/strong&gt; for the forecast, recent rain and past frost dates. It needs no API key.&lt;/li&gt;
&lt;li&gt;The app itself is a small PWA, so I can add it to my phone's home screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rules for the facts, Gemma for the rest
&lt;/h3&gt;

&lt;p&gt;I didn't want to rely on a language model for things like "is it below freezing tonight?". So Toado works in two steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, plain TypeScript rules work out which jobs could make sense today:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Greenhouse:&lt;/strong&gt; open it on a warm or sunny day, and close it in the evening if the night will be cold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frost:&lt;/strong&gt; compare tonight's low with how much cold each plant can take. A plant in a pot can take less cold, and one under cover more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watering:&lt;/strong&gt; how long since I last watered, whether it has rained, and whether it's hot. Pots dry out faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seasonal care:&lt;/strong&gt; the months when each plant should be sown, pruned, fed, mulched or harvested.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These rules don't use AI, so I can test them, and they're the part I most want to be right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then Gemma gets that list.&lt;/strong&gt; It picks a handful of jobs for today, groups them, words them in plain language and writes a short summary of the day. Its answer has to match a schema that only allows the jobs from the list, so it can choose and rephrase, but it can't add a job of its own. If Ollama isn't running, Toado just shows the rules' list instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting to know what I have
&lt;/h3&gt;

&lt;p&gt;Toado has care information for 40 common garden plants built in. When I add a plant that's more specific than that, or not on the list at all, I can ask Gemma for a suggestion: how often to water it, how much frost it can take, and which months to do what. The plant can be a variety, like my Melonäpple apple tree, which ripens a few weeks after the other one. The suggestion goes into a month grid that I check and correct before saving, because Gemma can be wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asking with a photo
&lt;/h3&gt;

&lt;p&gt;Gemma 4 can look at images. In &lt;strong&gt;Ask the garden&lt;/strong&gt; I can attach a photo and ask a question. Gemma gets my garden as context too: the plants, the log and this week's weather. I tried it with a photo of an apple leaf with reddish-brown spots, and it answered:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I can see reddish-brown, irregular blotches on your Melonäpple leaf. It is likely apple scab, which thrives in the damp, rainy weather we are having here in Forshaga this October. To be sure, check the underside of the leaf; scab often looks dusty or fuzzy there… Go outside and check if the spots are appearing on the fruit itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I asked it to say what it can see, how sure it is and what to check outside. I think that's more useful than a confident diagnosis, and it sends me outside to look.&lt;/p&gt;

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

&lt;p&gt;For me, it mostly comes down to three things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The data stays at home.&lt;/strong&gt; A garden app knows a lot: where I live, what I grow, when I'm out there, and now photos of our home. With Gemma running locally, none of that leaves my computer. The only thing sent out is the location, to Open-Meteo, for the forecast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I can make it completely mine.&lt;/strong&gt; It's my code and my model, running on my machine. I can change the rules, add my own plants and try other models; &lt;code&gt;VITE_OLLAMA_MODEL&lt;/code&gt; sets which one it uses. There's no account and no API key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It doesn't cost anything to use.&lt;/strong&gt; Toado asks Gemma whenever something changes: a new day, a new plant, a ticked job, a question. With a paid API I'd probably have held back on that. Running it myself, I didn't have to think about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What hasn't worked so well:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; the model needs a fairly powerful computer (it takes about 16 GB of memory). A question with a photo takes around 25 seconds to answer the first time, though follow-up questions about the same photo are much quicker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phones:&lt;/strong&gt; a phone can't run Gemma. I use Toado on my phone through Tailscale, which lets it reach my Mac at home privately. That only works while the Mac is awake.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mistakes:&lt;/strong&gt; Gemma sometimes gets things wrong. In one answer it suggested composting leaves with apple scab, which is usually advised against. That's part of why the important facts come from the rules, and why I check what it suggests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Future Ideas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Share it between our devices.&lt;/strong&gt; The garden and the log should live on the computer at home, so my partner and I can use the same garden from our own phones. The data still stays in the house.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real phone notifications&lt;/strong&gt; when something needs doing, like "close the greenhouse door, it'll be cold tonight".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A garden calendar&lt;/strong&gt; with a photo for each day. Over the seasons that would become a diary of how the garden changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes for the future.&lt;/strong&gt; If I do something in autumn that matters in spring, like planting bulbs or covering a bed, I'd like to write a note and have Toado remind me when the time comes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More rules.&lt;/strong&gt; The TypeScript rules are only a start. Because they're plain code, I can keep adding rules that fit this particular garden as I learn what it needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Took It Outside
&lt;/h2&gt;

&lt;p&gt;Today was a rainy Saturday, and I spent it outside doing what Toado suggested: harvest the last apples and pears, empty the greenhouse and clear the pallet collars.&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%2F0vf6jcqtazme7k06xojs.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%2F0vf6jcqtazme7k06xojs.jpg" alt="Me in the greenhouse in rain gear" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The greenhouse was full of finished tomatoes, squash, cucumbers and chillies. This is before and after:&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%2Fy5nzxyhv3u7youmb18dd.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%2Fy5nzxyhv3u7youmb18dd.jpg" alt="The greenhouse before clearing" width="760" height="1013"&gt;&lt;/a&gt;&lt;br&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%2F7n6fqxs0i1u42xxifa27.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%2F7n6fqxs0i1u42xxifa27.jpg" alt="The greenhouse after clearing" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the pallet collars. Clearing them turned up a bowl of potatoes.&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%2F1xsir7d647pi1514otdw.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%2F1xsir7d647pi1514otdw.jpg" alt="The pallet collars" width="800" height="600"&gt;&lt;/a&gt;&lt;br&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%2Fo5u6tho283aj2nglnhqs.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%2Fo5u6tho283aj2nglnhqs.jpg" alt="Potatoes dug up from the pallet collars" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the collars were empty, I wasn't sure whether to just leave them like that over winter. That's the question in the demo video. Gemma took about 20 seconds to answer. It saw that the collars were empty, and from my log it knew what had grown in each of them. It suggested covering the soil with mulch or a sack, so the autumn rain doesn't wash the nutrients away before spring. I hadn't thought of that.&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%2F5txf0lr0dgzwv4wcdiex.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%2F5txf0lr0dgzwv4wcdiex.jpg" alt="A muddy thumbs up" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;I built Toado together with Claude Code, working from a written plan step by step: weather and climate first, then the rules, then Gemma, then the app itself. I reviewed and tried out each step before moving on. Plenty changed on the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The first idea was too narrow.&lt;/strong&gt; It started out mostly about frost dates. That didn't fit a garden like ours, so it became a year-round helper built around my own plants, the season and the weather.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Varieties got added&lt;/strong&gt; when I realised my two apple trees ripen weeks apart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma needed some help.&lt;/strong&gt; At first it said tonight would be 3 °C when the forecast low was −2 °C, so now the prompt states tonight's low directly. It also called a gooseberry a flower.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A code review caught real bugs.&lt;/strong&gt; One was that editing one plant changed the care for every plant of that kind.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing it myself helped most.&lt;/strong&gt; I got stuck in the demo garden with no way back, so that got fixed. When I found out Gemma could read images, I added photo questions. Opening it on my phone showed that Ollama was turning away requests from the Tailscale address.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt;: Gemma 4 runs locally through Ollama. It plans the day's jobs, suggests care for plants and varieties, answers questions about the garden and looks at photos.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>ollama</category>
    </item>
    <item>
      <title>Learning Gulp</title>
      <dc:creator>Zara</dc:creator>
      <pubDate>Tue, 07 Apr 2020 18:11:20 +0000</pubDate>
      <link>https://dev.to/madebyzara/learning-gulp-5cjd</link>
      <guid>https://dev.to/madebyzara/learning-gulp-5cjd</guid>
      <description>&lt;p&gt;I have used Gulp for a while but I have never really understood everything in the gulpfile - it just seemed like magic to me. I have always just used examples from others and tweaked what I needed to &lt;em&gt;get it to work&lt;/em&gt;. Which has been fine, but I decided that I want to learn it properly so for my personal website, I wrote my own gulpfile.&lt;/p&gt;

&lt;p&gt;I have only used Gulp 3 before so I wanted learn Gulp 4. I googled my way through it all, I learned which plugins to use for what cause and how to write up my tasks. There are TONS of resources if you google &lt;code&gt;gulp 4 setup&lt;/code&gt; but I made sure I wasn't just copying and pasting. I want to understand each line of code in my file.&lt;/p&gt;

&lt;p&gt;My personal website is in HTML with Sass so I wrote a gulpfile for my needs right now. I want to compile my Sass, add source maps and have a better, easier workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  BrowserSync
&lt;/h2&gt;

&lt;p&gt;Here is how to setup BrowserSync with gulp: &lt;a href="https://browsersync.io/docs/gulp" rel="noopener noreferrer"&gt;BrowserSync docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Styles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What I wanted
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Compile Sass to CSS&lt;/li&gt;
&lt;li&gt;Add source maps&lt;/li&gt;
&lt;li&gt;Minify my CSS file&lt;/li&gt;
&lt;li&gt;Use BrowserSync to see changes straight away. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Packages used
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sass = require('gulp-sass');
const cleanCSS = require('gulp-clean-css');
const sourcemaps = require('gulp-sourcemaps');
const browserSync = require('browser-sync').create();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function style() {
    return gulp.src('./assets/scss/main.scss')
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(cleanCSS())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./assets/css'))
        .pipe(browserSync.stream())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this method does
&lt;/h3&gt;

&lt;p&gt;When we do &lt;code&gt;gulp.src('./assets/scss/main.scss')&lt;/code&gt;, it creates a node stream and reads our file. We can then use our plugins in &lt;code&gt;.pipe&lt;/code&gt; methods to change the file how we like it until we save it to the final destination using &lt;code&gt;.pipe(gulp.dest('./assets/css'))&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  The plugins
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;sourcemaps.init()&lt;/code&gt;: Initialise Source Maps - package &lt;a href="https://www.npmjs.com/package/gulp-sourcemaps" rel="noopener noreferrer"&gt;gulp-sourcemaps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sass().on('error', sass.logError)&lt;/code&gt;: Compile my Sass to CSS - package &lt;a href="https://www.npmjs.com/package/gulp-sass" rel="noopener noreferrer"&gt;gulp-sass&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cleanCSS()&lt;/code&gt;: Minify my CSS - package &lt;a href="https://www.npmjs.com/package/gulp-clean-css" rel="noopener noreferrer"&gt;gulp-clean-css&lt;/a&gt;. I started with &lt;a href="https://www.npmjs.com/package/uglifycss" rel="noopener noreferrer"&gt;uglify-css&lt;/a&gt; but noticed (after some debugging) that it broke my source maps! It basically removed the &lt;code&gt;/*# sourceMappingURL=main.css.map */&lt;/code&gt; part once minified, but this package does not. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;sourcemaps.write('.')&lt;/code&gt;: Writes my source maps, &lt;code&gt;('.')&lt;/code&gt; meaning the same directory so it sits next to my main.css file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;browserSync.stream()&lt;/code&gt;: This is my favourite part and I just learned about this! Instead of using &lt;code&gt;browserSync.reload()&lt;/code&gt;, this "injects" the css without doing a page refresh. So you see your style changes straight away - it's beautiful. We need to run this after &lt;code&gt;gulp.dest()&lt;/code&gt; so that the css file has been written.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What I wanted
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Notice when a .html or .scss file has changed&lt;/li&gt;
&lt;li&gt;Run BrowserSync and reload browser if necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Packages used
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const browserSync = require('browser-sync').create();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function watch() {
    browserSync.init({
        server: {
            baseDir: "./"
        }
    });

    gulp.watch('./assets/scss/*.scss', style);
    gulp.watch('./**/*.html').on('change', browserSync.reload);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this method does
&lt;/h3&gt;

&lt;p&gt;I first initialise BrowserSync by setting the baseDir. This will set up an Access URL where you can view your website. I am setting this to the same folder my file is in, this is where my index.html is. But if you have a local setup, you can add your url here, eg. &lt;code&gt;my-site.dev&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then we add our watch tasks.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gulp.watch('./assets/scss/*.scss', style)&lt;/code&gt; : It accepts 2 parameters, the files you want to watch and the function you want to run. This watches for a change in a &lt;code&gt;.scss&lt;/code&gt; file that exists within my &lt;code&gt;assets/scss&lt;/code&gt; folder, and calls my style method that I wrote before. This means that the Sass will automatically compile and BrowserSync will inject the css changes on my site straight away. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;gulp.watch('./**/*.html').on('change', browserSync.reload)&lt;/code&gt;: Here we are watching for a change in any .html in my project. When a .html file changes, it calls browserSync.reload that refreshes my browser so we will see the change straight away. &lt;/p&gt;

&lt;h2&gt;
  
  
  Set a Default task
&lt;/h2&gt;

&lt;p&gt;Finally I set my default gulp task, which means it will run when I type &lt;code&gt;gulp&lt;/code&gt; in the cmd line. I want it to use my watch function by default, however I could write &lt;code&gt;gulp watch&lt;/code&gt; and it will do the same. But it's good for learning purposes and it is quicker to type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exports.default = watch;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I went back and forth a bit, fixing one thing, adding a new plugin that turned out breaking something else but it's all a part of learning. I learned more about npm-packages like I have installed tons but never uninstalled one before - it's just &lt;code&gt;npm uninstall my-package&lt;/code&gt; who knew!? I know it sounds simple but I have come to a point now where if I get a problem and I solve it myself (by googling obvs), I feel soo good. Like I can figure it out by myself, it's ok. &lt;/p&gt;

&lt;p&gt;Another funny thing that happened is that once I pushed my new gulpfile to my repository on Github, Github was like oh no hun - you got security alerts. Long story short, I figured out that I was on an older node version, moved to a newer one, learned about &lt;code&gt;npm audit&lt;/code&gt; and fixed the security flaws. &lt;a href="https://itnext.io/fixing-security-vulnerabilities-in-npm-dependencies-in-less-than-3-mins-a53af735261d" rel="noopener noreferrer"&gt;This article&lt;/a&gt; helped me and &lt;code&gt;npm audit fix&lt;/code&gt; worked like a dream. &lt;/p&gt;

&lt;p&gt;So, this was a great learning process for me and I can now use gulp (and npm) more confidently. Here is the final gulpfile if anyone is interested.&lt;/p&gt;

&lt;h3&gt;
  
  
  The final gulpfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const gulp = require('gulp');
const sass = require('gulp-sass');
const cleanCSS = require('gulp-clean-css');
const sourcemaps = require('gulp-sourcemaps');
const browserSync = require('browser-sync').create();

// Compile, SourceMaps and Minify CSS
function style() {
    return gulp.src('./assets/scss/main.scss')
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(cleanCSS())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./assets/css'))
        .pipe(browserSync.stream())
}

// Watch for file changes
function watch() {
    browserSync.init({
        server: {
            baseDir: "./"
        }
    });

    gulp.watch('./assets/scss/*.scss', style);
    gulp.watch('./**/*.html').on('change', browserSync.reload);
}

exports.style = style;
exports.watch = watch;

// Default function when you run gulp
exports.default = watch;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>gulp</category>
      <category>frontend</category>
      <category>setup</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My 2019</title>
      <dc:creator>Zara</dc:creator>
      <pubDate>Thu, 02 Jan 2020 13:55:05 +0000</pubDate>
      <link>https://dev.to/madebyzara/my-2019-41ne</link>
      <guid>https://dev.to/madebyzara/my-2019-41ne</guid>
      <description>&lt;p&gt;I love looking back on the year that has passed, it helps me realise how much has actually happened and to recognise all the good things I have done. The brain has a tendency to hold on to the negative things so I put a lot of effort to always notice and remember the good things in life. &lt;/p&gt;

&lt;p&gt;I have kept a log of my days since 2012, but been adding in more details for each year and this year I even added "Highlights of the week" where I would list my 3-5 favourite things from the week. Yeah. I love this shit. &lt;/p&gt;

&lt;p&gt;So let's recap 2019. &lt;/p&gt;

&lt;h3&gt;
  
  
  January
&lt;/h3&gt;

&lt;p&gt;I started the year in Sweden with my parents. On the 1st, I flew back to Brighton and I started Veganuary. I attended &lt;a href="https://asyncjs.com/" rel="noopener noreferrer"&gt;Async&lt;/a&gt; and learned about WebGL. Organised a few codebar's and ate some pizza. &lt;/p&gt;

&lt;p&gt;I spoke about codebar in the Winter Issue of &lt;a href="https://issuu.com/thrivethemag" rel="noopener noreferrer"&gt;Thrive The Magazine&lt;/a&gt; that came out in January. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1084742388470464513-267" src="https://platform.twitter.com/embed/Tweet.html?id=1084742388470464513"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1084742388470464513-267');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1084742388470464513&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://labs.uk.barclays/locations/brighton" rel="noopener noreferrer"&gt;Brighton Eagle Lab&lt;/a&gt; hosted a free IoT workshop for 3 sessions (every other Thursday). &lt;/p&gt;

&lt;p&gt;The lead dev Aidan at Gene offered to mentor me! This was really exciting as I am always trying to grow and having someone to guide me, share my goals with and get advice from is priceless.&lt;/p&gt;

&lt;h3&gt;
  
  
  February
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1093623295533043713-984" src="https://platform.twitter.com/embed/Tweet.html?id=1093623295533043713"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1093623295533043713-984');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1093623295533043713&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The IoT workshops were so fuuun. Just made some lights blink. &lt;/p&gt;

&lt;p&gt;Aidan and I had our first mentoring session and Aidan made a training plan for me. I want to learn programming techniques, logic, different approaches and ways to solve problems. The plan was to build a website in PHP where you can register as a user, login, create posts, edit them, delete them and view all posts (CRUD). This also introduced me to working with databases, learning about security and keeping code DRY. But February was just the start. &lt;/p&gt;

&lt;p&gt;And the codebar girls got a lovely shoutout on Galentine’s Day! &lt;a href="https://clockworktalent.com/blog-galentines-day/" rel="noopener noreferrer"&gt;You can find the article here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1094926087648411648-592" src="https://platform.twitter.com/embed/Tweet.html?id=1094926087648411648"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1094926087648411648-592');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1094926087648411648&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  March
&lt;/h3&gt;

&lt;p&gt;Went on my first ever hen do in Toulouse! &lt;a href="https://www.wespringforward.com/" rel="noopener noreferrer"&gt;We Spring Forward&lt;/a&gt; kicked off and a friend and I attended a confidence workshop. On International Women's day a few days later, it was She Says Brighton which is always so, so inspiring. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1104102836961460224-848" src="https://platform.twitter.com/embed/Tweet.html?id=1104102836961460224"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1104102836961460224-848');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1104102836961460224&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I went to Async again where Pete G spoke about Imposter Syndrome which was so insightful. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1106303961605304320-698" src="https://platform.twitter.com/embed/Tweet.html?id=1106303961605304320"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1106303961605304320-698');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1106303961605304320&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  April
&lt;/h3&gt;

&lt;p&gt;We had a "Intro to Python" evening at Gene. I got told I get to go to Magento Imagine - the biggest Magento conference that is hosted in VEGAS. What. is. up. &lt;/p&gt;

&lt;h3&gt;
  
  
  May
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F768ft8ighg62vy4wsad8.GIF" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F768ft8ighg62vy4wsad8.GIF" alt="me and my colleagues posing, dressed up at Magento party" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Went to Vegas - it was my first Magento conference. It was unreal couple of days filled with activities like running 5K to Hoover Dam, party in the &lt;a href="https://stratospherehotel.com/" rel="noopener noreferrer"&gt;Stratosphere&lt;/a&gt; (and rode a rollercoaster at the top!), panels and developer sessions. So. fun.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1127628722259906561-833" src="https://platform.twitter.com/embed/Tweet.html?id=1127628722259906561"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1127628722259906561-833');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1127628722259906561&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The week after Vegas, I flew back to Toulouse for my friends wedding. This was one of the highlights of the year. I reunited with people I have not seen since 2012 when I studied in America. It was a beautiful weekend and I danced so much I broke a nerve in my big toe (which still hasn't healed oops). &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%2F5508ue3smaml8f02am2z.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%2F5508ue3smaml8f02am2z.JPG" alt="Me laughing with my friends at a wedding" width="720" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  June
&lt;/h3&gt;

&lt;p&gt;2 year anniversary at Gene and as a developer! We hosted codebar at Gene.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1138534045799911426-813" src="https://platform.twitter.com/embed/Tweet.html?id=1138534045799911426"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1138534045799911426-813');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1138534045799911426&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;We also had our first Gene day where our offices from Liverpool and London came down to Brighton for the day. We spent the morning doing a communication workshop, followed by a team building exercise at Phileas Fogg! In the evening, there was a dinner and drinks but I missed it as I went to Manchester for the weekend! And in the end of the month, I got to attend &lt;a href="https://patternsday.com/" rel="noopener noreferrer"&gt;Patterns Day&lt;/a&gt;, always so brilliant and I got to see one of my big role models, &lt;a href="https://twitter.com/Una" rel="noopener noreferrer"&gt;Una&lt;/a&gt; speak!&lt;/p&gt;

&lt;h3&gt;
  
  
  July
&lt;/h3&gt;

&lt;p&gt;Attended Async and learned about Gatsby Js. I went to &lt;a href="https://clearleft.com/" rel="noopener noreferrer"&gt;Clearleft&lt;/a&gt; lovely summer party. &lt;/p&gt;

&lt;p&gt;I also signed up and attended a &lt;a href="https://www.eventbrite.ca/e/magento-community-speaker-workshop-part-1-july-13-part-2-july-20-tickets-61263965169" rel="noopener noreferrer"&gt;Magento Speaker workshop&lt;/a&gt;. This was an online course that, due to time differences, took place over 2 Saturday evenings, but it was really interesting and fun to attend! It was run by Jill Binder, who founded &lt;a href="https://diversein.tech/" rel="noopener noreferrer"&gt;Diverse in Tech&lt;/a&gt; and she was absolutely brilliant. At the end of the course, I had a talk idea outlined but I am still working on that talk. Maybe this year I will do my first technical talk... &lt;/p&gt;

&lt;p&gt;We started doing Friday dev sessions at Gene and I lead a session about Semantic HTML. Gene also hosted the first Brighton Magento Meetup where our own Michael and Sophie spoke. Really fun evening! &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1151571402702622720-677" src="https://platform.twitter.com/embed/Tweet.html?id=1151571402702622720"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1151571402702622720-677');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1151571402702622720&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  August
&lt;/h3&gt;

&lt;p&gt;Did not work a lot in August! I spent the beginning in Romania at Untold Music Festival, the middle (and my birthday weekend) in Portugal and the end, I spent 12 days in Sweden with my family.&lt;/p&gt;

&lt;h3&gt;
  
  
  September
&lt;/h3&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%2Ffl6w98ufinmhpbapdiws.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%2Ffl6w98ufinmhpbapdiws.JPG" alt="Muddy in front of Tough Mudder wall" width="800" height="872"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Completed Tough Mudder! &lt;/p&gt;

&lt;h3&gt;
  
  
  October
&lt;/h3&gt;

&lt;p&gt;A website (where I was the FE lead for the first time) went live! Attended Async again about JavaScript bots and editor frameworks. I went to Sweden for a weekend to surprise my dad for his birthday. &lt;/p&gt;

&lt;p&gt;I completed &lt;a href="https://hacktoberfest.digitalocean.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; &amp;amp; I attended my last codebar as an organiser. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1186723646208987139-299" src="https://platform.twitter.com/embed/Tweet.html?id=1186723646208987139"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1186723646208987139-299');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1186723646208987139&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;That same week, I started as a instructor for &lt;a href="https://www.codefirstgirls.org.uk/" rel="noopener noreferrer"&gt;Code First: Girls&lt;/a&gt;. This was for a 8 week course teaching HTML, CSS, JavaScript, held at Sussex University every Thursday evening. We had one lead instructor who did the course before and 4 rookie instructors. But it went great and it was so fun! &lt;/p&gt;

&lt;p&gt;The second week was CSS and I got to lead the class! I was nervous all week for it (even had a nervous eye twitch!) but I smashed it and I was so proud. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1190352056265121794-518" src="https://platform.twitter.com/embed/Tweet.html?id=1190352056265121794"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1190352056265121794-518');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1190352056265121794&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  November
&lt;/h3&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1192739004107689985-168" src="https://platform.twitter.com/embed/Tweet.html?id=1192739004107689985"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1192739004107689985-168');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1192739004107689985&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Only because a colleague of mine got sick, I got to take his place and attend FFconf again! Absolutely loved it, brilliant speakers and I got to see so many familiar faces. Always such a great conference. &lt;/p&gt;

&lt;p&gt;Code First:Girls sessions carried on and I enjoyed being an instructor so much. I would arrive with low energy from the work day and thrive with happiness on the train home. Love teaching!&lt;/p&gt;

&lt;p&gt;oh, and I became a certified Magento Front End Developer!&lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1197833954205847552-497" src="https://platform.twitter.com/embed/Tweet.html?id=1197833954205847552"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1197833954205847552-497');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1197833954205847552&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  December
&lt;/h3&gt;

&lt;p&gt;Gene held it's Christmas party and on the same day, it was the last Code First:Girls session! So I managed to attend the beginning of Christmas party, skipped the dinner to go to CF:G and came back after for the drinks. I did not wanna miss seeing everyone's projects!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1205544867050532874-849" src="https://platform.twitter.com/embed/Tweet.html?id=1205544867050532874"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1205544867050532874-849');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1205544867050532874&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I also attended the codebar Christmas party which was so lovely! I saw so many people I haven't seen for a while, there was an amazing show &amp;amp; tell and all around spread of love. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1207057583208620032-814" src="https://platform.twitter.com/embed/Tweet.html?id=1207057583208620032"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1207057583208620032-814');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1207057583208620032&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;And that brings us up to Christmas which I spent in Sweden in the snow with my family and our dogs. Celebrated New Years back in Brighton with my boyfriend. &lt;/p&gt;

&lt;h3&gt;
  
  
  .. And a little about my PHP Project
&lt;/h3&gt;

&lt;p&gt;I worked on my project 26 times over the year. Mostly over weekends. It has been such a fun learning progress. Almost every other week, Aidan and I would catch up on my progress and discuss next step. He would tell me what I need to add and I would have to figure out how to do it.&lt;/p&gt;

&lt;p&gt;At the end of the summer, I had a working website with user authentication, all CRUD pages &amp;amp; profile pages where you could even upload your own profile pic. Mighty proud. Even went on to cover regex and wrote my own Markdown parser in PHP which was really tough but I got it working in the end. So you can write some simple markdown in the posts as well.&lt;/p&gt;

&lt;p&gt;In November, I had all the basic functionality. But I had all my logic in one file so now it was time for refactor and restructure. I learned about "Business Logic", and started learning OOP to re-write all my post functions in to one class. At the end of the year, I also added a repository class where it will handle the posts collections.&lt;/p&gt;

&lt;p&gt;I have learnt so much with this project over the year, so many "Aha!" moments and once my BE is in place, next steps involve writing APIs so that I can build the FE with Vue or React. It's gonna be so fun!&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;My year was full of professional and personal development! I got a mentor and learned tons on my side project. I became a certified Magento Front-End developer. I closed my chapter as codebar organiser after 2.5 years and opened a new chapter as Code First: Girls instructor. I kept up my training on an average of 2 sessions per week and I travelled to France, USA, Romania, Portugal and Sweden. &lt;/p&gt;

&lt;p&gt;Another amazing year! Can't wait to see what happens in 2020.&lt;/p&gt;

&lt;p&gt;My previous year reviews: &lt;a href="https://medium.com/@madebyzara/my-2018-dfda5a41ed6e" rel="noopener noreferrer"&gt;2018&lt;/a&gt; and &lt;a href="https://medium.com/@madebyzara/my-2017-2a9ed51fd739" rel="noopener noreferrer"&gt;2017&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>yearinreview</category>
      <category>devjournal</category>
    </item>
  </channel>
</rss>
