<?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>Forem: Valeria</title>
    <description>The latest articles on Forem by Valeria (@valeriavg).</description>
    <link>https://forem.com/valeriavg</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F473770%2F2ee31638-e52d-40f9-8bf8-d98b82784a4b.jpg</url>
      <title>Forem: Valeria</title>
      <link>https://forem.com/valeriavg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/valeriavg"/>
    <language>en</language>
    <item>
      <title>Wrangling GenAI: Optimising prompts for Visual Tasks</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Sat, 28 Mar 2026 13:48:29 +0000</pubDate>
      <link>https://forem.com/valeriavg/wrangling-genai-optimising-prompts-for-visual-tasks-68b</link>
      <guid>https://forem.com/valeriavg/wrangling-genai-optimising-prompts-for-visual-tasks-68b</guid>
      <description>&lt;p&gt;When I wrote the first version of the magic cleaning tasks generator for &lt;a href="https://hounty.app" rel="noopener noreferrer"&gt;Hounty&lt;/a&gt; I wasn't particularly happy with it, but I thought that this is as good as it gets with Generative AI APIs and let it be till I have time to train my own model. Well, today I proved myself wrong and I want to show you exactly how I managed to drastically improve performance by adjusting the prompt in a few inconventional ways.&lt;/p&gt;

&lt;p&gt;I encourage you to follow along and try the prompts yourself. I used Gemini and Claude, but pretty much any chat AI app or API should work. And if you have never worked with GenAI - that's no problem - you don't have to have any prior knowledge to follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Task
&lt;/h2&gt;

&lt;p&gt;Here is a picture of my living room this morning:&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%2Fds3hfrr1h62sj6f66lx2.jpeg" 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%2Fds3hfrr1h62sj6f66lx2.jpeg" alt="Messy living room with laundry covering sofa; boxes and bags scattered on the floor" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like this a few days a week and every time it's a chore to get started. I do rely on Hounty to tell me what to do and where to start. So let's try and replicate the core functionality with nothing but prompts and see how to improve them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take one: You are an expert
&lt;/h2&gt;

&lt;p&gt;You've probably seen the advice to start your prompt with "you are an expert in ...". It sounds like a good idea, but let's try and see what it actually does.&lt;/p&gt;

&lt;p&gt;Paste an image of a messy room (yours or mine) into your AI chat and prompt this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are a home cleaning expert. Create a cleaning todo list of 3-5 most impactful tasks&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's what I got from Gemini:&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.amazonaws.com%2Fuploads%2Farticles%2F3rl5i4rzhpurp66dv3yp.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%2F3rl5i4rzhpurp66dv3yp.png" alt="Gemini trying to be an expert and responding with a lengthy and somewhat condecending list of tasks like " width="800" height="1230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now let's try without the "you're an expert" preamble:&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.amazonaws.com%2Fuploads%2Farticles%2Fzslau4nqeyaev3mqp7o4.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%2Fzslau4nqeyaev3mqp7o4.png" alt="Gemini responding with a much shorter and more grounded list of tasks like " width="780" height="1208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second output is about half the size of the "expert" one and I find it much more actionable and clear: "Clear the Floor" vs "Clear the Floor Transit Zones". So why does this happen?&lt;/p&gt;

&lt;p&gt;Turns out, giving AI a title doesn't unlock more knowledge, but instead it forces it to &lt;strong&gt;act&lt;/strong&gt; like an expert or, in other words, researchers found that &lt;a href="https://arxiv.org/abs/2603.18507" rel="noopener noreferrer"&gt;Expert Personas Improve LLM Alignment but Damage Accuracy&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Not to say that personas have no use, but in majority of cases adding  "you are an expert" would result in a confident tone and bloated output. Which means you'll burn more tokens for no benefit.&lt;/p&gt;

&lt;p&gt;Skipping it works better.&lt;/p&gt;
&lt;h2&gt;
  
  
  Take two: Detailed prompt
&lt;/h2&gt;

&lt;p&gt;On the first glance, a common advice to describe what you want in as many details as possible makes sense, so let's give it a try.&lt;/p&gt;

&lt;p&gt;Same image, more explicit prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Look at this image. List every visible object. For each object, determine whether it is out of place based on what should be in a Living Room. Consider laundry, dishes and clutter specifically. Return your findings in a structured list of 3-5 most impactful cleaning items as JSON.&lt;br&gt;
Example:&lt;br&gt;
[{"task":"Throw away newspapers", "advice":"Recycle as newspapers"}]&lt;/p&gt;
&lt;/blockquote&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%2Ftnwxn7yxl5qvarzc2rtc.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%2Ftnwxn7yxl5qvarzc2rtc.png" alt="Gemini returns a long output describing everything it sees on the image and only then providing requested JSON" width="798" height="1248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the json it returned, since it didn't fit into the first screen:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fold and put away laundry from the sofa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sort by owner or garment type and move to the bedroom or closet to regain seating space."&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stow reusable shopping bags"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Empty any remaining contents and store the Lidl bags in a pantry, kitchen drawer, or car trunk."&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Clear the floor of miscellaneous items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pick up the pink hairbrush and the black tub; return the brush to the bathroom and store the tub in a utility area."&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Declutter the windowsill and cat tree base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Move non-decorative items and loose papers to a dedicated desk or filing system to improve natural light flow."&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;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;And now try a simpler version:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a todo list of 3-5 most impactful cleaning tasks. Return as JSON {title,advice}&lt;/p&gt;
&lt;/blockquote&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%2Fujk77jgajrucrv4kmbqy.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%2Fujk77jgajrucrv4kmbqy.png" alt="Gemini returns just the JSON array with tasks" width="782" height="1240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the resulting json in full for comparison:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Clear the Sofa Surface"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fold or hang the large pile of clothing on the couch. Clearing this central furniture piece will immediately make the room feel functional and less overwhelmed by 'clutter weight'."&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Consolidate Floor Items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Gather the loose items on the rug and the shopping bags by the door. Use the empty black bin shown in the foreground to quickly corral miscellaneous objects that don't have a dedicated home yet."&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Clear the Windowsill and Radiator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Remove the papers and pink organizer from the windowsill. In a bright room, clear horizontal surfaces near windows reflect more light and create a much cleaner visual line."&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reset the Dining Area"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tuck the dining chairs neatly under the table and remove any small items from the tabletop. Aligning the furniture creates a sense of order that anchors the rest of the open space."&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;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;Both prompts produced a similar list, but the first one added a lot of noise, which would not only made it much harder to use in an API, but would also cost more since it used more input and output tokens.&lt;/p&gt;

&lt;p&gt;And the pink brush the first list mentions? It's a cat brush, it doesn't belong in the bathroom - it belongs in a box with cat stuff. Skipping that detail made the second list appear more precise.&lt;/p&gt;

&lt;p&gt;So why did the detailed prompt backfire?&lt;/p&gt;

&lt;p&gt;Because the second prompt gives the model room to reason. We've stated the goal clearly and let it do its job. When we provide too many details in the context LLM experiences effects similar to &lt;em&gt;overtraining&lt;/em&gt; a model. In other &lt;a href="https://medium.com/@jwbtmf/overcoming-overfitting-a-model-in-machine-learning-7dd6324d15bf" rel="noopener noreferrer"&gt;words&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Overtraining (often synonymous with overfitting) occurs when a machine learning model learns the training data too well, capturing noise and specific details rather than general patterns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By giving the LLM too many details we limit the ways it can solve the problem and thus as a general rule - less is more. You can always add or clarify something later.&lt;/p&gt;

&lt;p&gt;And once again, less tokens spent!&lt;/p&gt;

&lt;h2&gt;
  
  
  Take three: Structured data
&lt;/h2&gt;

&lt;p&gt;Now that we have the tasks in place it would be nice to add the coordinates of the areas on the image which illustrates each task.&lt;/p&gt;

&lt;p&gt;Let's try and enchance the prompt to return just that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Identify 3-5 most impactful cleaning tasks and return ONLY JSON{task,x,y,w,h} mapping tasks with the areas on the image where x,y are top-left corner pixels of the bounding box and w,h is width and height&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Adding "ONLY JSON" was needed to make sure that LLM doesn't interpret  "do this and then that" as two separate requests and spits out text and JSON.&lt;/p&gt;

&lt;p&gt;Here's the result:&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.amazonaws.com%2Fuploads%2Farticles%2F6zn6nyrlo46oyf2v45l2.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%2F6zn6nyrlo46oyf2v45l2.png" alt="Gemini returning a JSON with additional " width="786" height="784"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hm, I didn't ask for a "label". &lt;/p&gt;

&lt;p&gt;We could keep patching the JSON prompt, but there's a better tool for the job - CSV(comma-separated values).&lt;/p&gt;

&lt;p&gt;Try this adjusted prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Identify 3-5 most impactful cleaning tasks and return ONLY CSV(task,x,y,w,h) mapping tasks with the areas on the image where x,y are top-left corner pixels of the bounding box and w,h is width and height&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And here's what I got: &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.amazonaws.com%2Fuploads%2Farticles%2Fftk3ocnukw6i0o6mgpco.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%2Fftk3ocnukw6i0o6mgpco.png" alt="Gemini returning clearly formatted output without any extra fields" width="796" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CSV is just as easy to parse as JSON, but turns out it produces more reliable output with less tokens. I think it might have to do with a fact that JSON requires AI to add something around values and it can occasionally go overboard, whereas CSV is just text with values as is. LLM native, if you must.&lt;/p&gt;

&lt;p&gt;So ditch JSON, use CSV and alike. The only gotcha to keep in mind is that comma in the text might break the output, so it might be worth asking LLM to &lt;em&gt;escape strings in the output&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take four: Spatial coordinates
&lt;/h2&gt;

&lt;p&gt;In the previous step we asked LLM to provide the coordinates of the top left corner of the area corresponding to each task, let's see how it fared.&lt;/p&gt;

&lt;p&gt;To test it I prompted Gemini and Claude to create an app. You can use the resulting &lt;a href="https://gemini.google.com/share/c23903fd493f" rel="noopener noreferrer"&gt;artifact&lt;/a&gt; or try this prompt to create one yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a small frontend app that would ask user to choose an image and paste a CSV(task,x,y,w,h) with tasks and areas on the image in either absolute pixels (add switch) or normalized coordinates (0.0 - 1.0) as well as x,y being either top-left or center of the box&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see how our original prompt with absolute pixel coordinates performed:&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%2F9pfk8cgrry04bp18venx.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%2F9pfk8cgrry04bp18venx.png" alt="Image overlaid with tasks; areas are about 30% off" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Meh, stupid AI, can't even outline a box properly, right?!&lt;/p&gt;

&lt;p&gt;Now let's try to adjust the prompt to return normalized coordinates instead:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Identify 3-5 most impactful cleaning tasks and return ONLY CSV(task,x,y,w,h) mapping tasks with the areas on the image where (x,y) are coordinates of the top-left corner of the bounding box and x,y,w,h are normalized floats between 0.0 and 1.0 (fraction of image dimensions). Box must stay within image: x-w/2 &amp;gt;= 0, x+w/2 &amp;lt;= 1, y-h/2 &amp;gt;= 0, y+h/2 &amp;lt;= 1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I added the last sentence because Gemini kept returning absolute values (way more than one) for the y coordinate.&lt;/p&gt;

&lt;p&gt;Here's how the resulting overlay looks:&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%2Fe08etbfky9eddi7pkfsd.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%2Fe08etbfky9eddi7pkfsd.png" alt="Image overlaid with tasks that are much closer to where they should be, but still off-center" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not too bad, but still a little off.&lt;/p&gt;

&lt;p&gt;And now for the last trick, let's try and switch top-left corner to a center instead:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Identify 3-5 most impactful cleaning tasks and return ONLY CSV(task,x,y,w,h) mapping tasks with the areas on the image where (x,y) are coordinates of the center of the bounding box and x,y,w,h are normalized floats between 0.0 and 1.0 (fraction of image dimensions).Box must stay within image: x-w/2 &amp;gt;= 0, x+w/2 &amp;lt;= 1, y-h/2 &amp;gt;= 0, y+h/2 &amp;lt;= 1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Voilà! Almost as good as Hounty:&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%2Fn28s61pxgnaom49sdofr.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%2Fn28s61pxgnaom49sdofr.png" alt="Image overlaid with tasks in the correct areas" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're wondering why LLMs work better with normalized centered values - it boils down to how the original data that model was trained on looked like. &lt;/p&gt;

&lt;p&gt;Asking a vision model to produce output in it's native 0-1 centered way makes it easier for them to give you what you asked for than to perform operations on the go.&lt;/p&gt;

&lt;p&gt;"But what if I need a different format?"- you might ask.&lt;/p&gt;

&lt;p&gt;I hear you, I also wouldn't want to release a new app every time I'm making an update to my API - the app in my case expects absolute values returned as json.&lt;/p&gt;

&lt;p&gt;And this is where the plain old geometry comes in handy! &lt;/p&gt;

&lt;p&gt;If GenAI produces a reliable machine-readible output (like CSV) you can take that output and transform it with a little bit of regular programming into whatever format you'd like.&lt;/p&gt;

&lt;p&gt;As a rule of thumb: if you can do something without AI - it would be  cheaper and more reliable to do it without AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cool, but how do I ship my prompts?
&lt;/h2&gt;

&lt;p&gt;Great question! We spent this whole article in the chat, that's not something you can just use or can you?&lt;/p&gt;

&lt;p&gt;And the answer is: yes you can! GenAI APIs are pretty much standardised and you can write the same prompts as you do in the chat and send them via REST API just like you'd do for any other service.&lt;/p&gt;

&lt;p&gt;Almost any cloud provider nowadays has their managed Generative AI API; Claude, Gemini &amp;amp; co also offer that, and you can even host or run your own model with Ollama.&lt;/p&gt;

&lt;p&gt;AI might have changed software development quite a bit, but in the end of the day it is still based on the same principles and sheer logic. &lt;/p&gt;

&lt;p&gt;There's no perfect prompt like there's no perfect code, but every iteration gets you a little bit closer to it.&lt;/p&gt;

&lt;p&gt;Oh and I did clean up when I finished updating the APIs :)&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.amazonaws.com%2Fuploads%2Farticles%2Fpqt1jfrmvtw9ahpa3iex.jpeg" 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%2Fpqt1jfrmvtw9ahpa3iex.jpeg" alt="Same living room, but clean" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>api</category>
      <category>beginners</category>
    </item>
    <item>
      <title>TIL that App Store apparently loves small frequent updates. New version of Hounty got into review within hours today!</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Mon, 23 Feb 2026 22:35:29 +0000</pubDate>
      <link>https://forem.com/valeriavg/til-that-app-store-apparently-loves-small-frequent-updates-new-version-of-hounty-got-into-review-49b7</link>
      <guid>https://forem.com/valeriavg/til-that-app-store-apparently-loves-small-frequent-updates-new-version-of-hounty-got-into-review-49b7</guid>
      <description></description>
      <category>buildinpublic</category>
      <category>ios</category>
      <category>mobile</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>5 things I learned from building and releasing Hounty</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Fri, 20 Feb 2026 18:58:18 +0000</pubDate>
      <link>https://forem.com/valeriavg/5-things-i-learned-from-building-and-releasing-hounty-2pg0</link>
      <guid>https://forem.com/valeriavg/5-things-i-learned-from-building-and-releasing-hounty-2pg0</guid>
      <description>&lt;p&gt;First of all, I can't believe Hounty is actually out! It's been so long since I started a small project that turned out to be a year long crusade and I can't be more proud of crossing this threshold.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TL;DR&lt;/em&gt; You can download Hounty on &lt;a href="https://apps.apple.com/us/app/hounty/id6741363930" rel="noopener noreferrer"&gt;App Store&lt;/a&gt; for free, the app is written in Flutter and the backend is in Serverless Go + Serverless PostgreSQL.&lt;/p&gt;

&lt;p&gt;Looking back I can't say I would do many things differently - the lessons I learned had to be learned, but I sure wish I knew a few things sooner.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Build in Public
&lt;/h2&gt;

&lt;p&gt;While the idea is great and helps build trust and relationship it really only works if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are building a tool aimed at developers&lt;/li&gt;
&lt;li&gt;You have something for them to try&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same goes for building a community on social networks before the app is ready. When I submitted the new shiny Freemium version for release  I made the previous version free and shared a video "Coming soon" with the app preview on TikTok:&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%2F2fx1a3wdxdt1agued7yi.jpeg" 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%2F2fx1a3wdxdt1agued7yi.jpeg" alt="App Store Trends showing 500 dowloads" width="603" height="1304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Five hundreds downloads are amazing! Except these users must've been so frustrated when they didn't find the new AI cleaning planner and were met with completely different design...&lt;/p&gt;

&lt;p&gt;My point is - advertise what is ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Deploy small changes
&lt;/h2&gt;

&lt;p&gt;I've rewritten UI and backend several times and every iteration has taken me weeks up until the moment where I would either get exhausted or paint myself into a corner. It only started to work when I learned to apply what I preach: to refactor as you go.&lt;/p&gt;

&lt;p&gt;Here's an example: I was working on a sync feature and I wanted to change the logic from log-based storage (all events are stored in one table and then replayed on the device) to an entity-based storage (every entity is stored in it's own table with it's own versioning).&lt;/p&gt;

&lt;p&gt;At first, I tried rebuilding everything all at once and it got really frustrating and I almost abandoned the whole thing, but then I started moving small pieces: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;moved the files of one entity into a separate folder, tested, commited, deployed&lt;/li&gt;
&lt;li&gt;wrote an abstraction for command pattern, refactored one "submodule"&lt;/li&gt;
&lt;li&gt;refactored the rest one-by-one&lt;/li&gt;
&lt;li&gt;changed the storage one-by-one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apparently, this approach suits not only for working in a team, who would've thought?!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Play store requires 2 weeks and 12 beta testers
&lt;/h2&gt;

&lt;p&gt;This one was new for me, my old Play store publishing account was no longer usable - I don't know if it was because it was created in Russia originally or because I did something stupid, but I needed to create a new one to publish and I discovered that I had to find 12 beta testers to test the app for 2 weeks before I could release it. My friends and family are on Apple devices, so it's going slower than I expected.&lt;/p&gt;

&lt;p&gt;There's a "testercommunity" app and a few communities on Reddit where people support each other, so definitely not a deal breaker, but I chose to focus on App Store for initial launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. App Store subscriptions are a hassle
&lt;/h2&gt;

&lt;p&gt;Releasing a one time pay version was very easy - it got approved in two days, but the free version with subscriptions took almost 2 weeks of back and forth.&lt;/p&gt;

&lt;p&gt;First, I didn't add the subscriptions to the release and the app went out with a beautiful paywall and no working subscriptions.&lt;/p&gt;

&lt;p&gt;A tip here is to check that the subscriptions have all the locales and obligatory fields filled and have status "Ready for review" before you submit a new version.&lt;/p&gt;

&lt;p&gt;And most importantly to add them to the version before submitting it for review. If you don't see where to do it - your subscriptions aren't ready. Super frustrating.&lt;/p&gt;

&lt;p&gt;Then, apparently it's obligatory to have a dedicated "Restore purchases" button even for subscriptions, even if you store the subscriptions on user account.&lt;/p&gt;

&lt;p&gt;Oh and you have to have a link to your terms of services in the description.&lt;/p&gt;

&lt;p&gt;And after the release subscriptions might be lagging and not appearing on the app store or in your app for 8-24 hours. Joy!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Tech Stack for Solo developers
&lt;/h2&gt;

&lt;p&gt;Being the only developer and working after hours with a very limited amount of time LLMs are a must, but they need a bit of handholding and depending on choices of language they might need more or less.&lt;/p&gt;

&lt;p&gt;Anything web-related that looked like React has been a breeze, Flutter was okay-ish after I setup all the scaffold, and yet I am holding myself from refactoring most of it.&lt;/p&gt;

&lt;p&gt;I managed to make it work with Go, but if I'd do it again - I'd build the backend in Rust. I didn't like Rust compiler barking at me - but I love it keeping Sonnet and Opus in check. Besides, it has great documentation and the only one way of doing things in a majority of cases - which makes LLMs predict the code more reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  So was it worth it?
&lt;/h2&gt;

&lt;p&gt;I don't know what comes next yet. Well, apart from Rust rewrite, of course. It's time to send Hounty into the world, look at the data and iterate. It wasn't easy, I'm yet to brag about my MRR, but it has been a fun ride. &lt;/p&gt;

&lt;p&gt;I built something I'm proud of, users are downloading it and my kids are showing me their perfect before and afters (they clean!). So yes, I think it was absolutely worth it!&lt;/p&gt;

&lt;p&gt;So, wanna see my clean pics?&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%2Fmykcsp7vnlpvjw70m383.jpeg" 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%2Fmykcsp7vnlpvjw70m383.jpeg" alt="Sparkling Hounty stickers " width="768" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>buildinpublic</category>
      <category>flutter</category>
      <category>go</category>
    </item>
    <item>
      <title>Submitted Hounty fo App Store review yesterday night. The little cute ghost has been haunting me for almost a year - but the massive rebuild is finally over and I’m so excited to show it off! Fingers crossed for a quick one!</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Mon, 09 Feb 2026 05:41:58 +0000</pubDate>
      <link>https://forem.com/valeriavg/submitted-hounty-fo-app-store-review-yesterday-night-the-little-cute-ghost-has-been-haunting-me-242c</link>
      <guid>https://forem.com/valeriavg/submitted-hounty-fo-app-store-review-yesterday-night-the-little-cute-ghost-has-been-haunting-me-242c</guid>
      <description></description>
      <category>ios</category>
      <category>mobile</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>The Most Terrifying App I've Ever Built: Hounty.app</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Sun, 16 Nov 2025 13:24:12 +0000</pubDate>
      <link>https://forem.com/valeriavg/the-most-terrifying-app-ive-ever-built-hountyapp-5g18</link>
      <guid>https://forem.com/valeriavg/the-most-terrifying-app-ive-ever-built-hountyapp-5g18</guid>
      <description>&lt;p&gt;Ten months ago I decided to build a tiny side-project that should have taken just a few weeks. It isn't the first time I grossly underestimated my own capacity and it won't be the last, but that's not that made the whole experience terrifying.&lt;/p&gt;

&lt;p&gt;As many others I had this beautiful dream in my mind that if I'll just apply apply all my umphteen years of practical knowledge I'll be able to make just about anything happen over time.&lt;/p&gt;

&lt;p&gt;I don't think I fully realised how much more there is to building a product than just development and how paralyzing being a sole developer can be.&lt;/p&gt;

&lt;p&gt;And worst of all? I can't seem to let go of the idea no matter what, so I'm far from giving up, but let's save the future for later. Today I'd like to share with you the bone chilling story of a tiny home management app I started.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Find a problem to solve"
&lt;/h2&gt;

&lt;p&gt;Something that I took embarassingly long time to figure out is that chore management is just about the worst possible problem one can try and solve with an app. Chore management apps are downloaded in mass and abandoned in an instant for one reason: when you have a single responsible home manager - they become yet another thing to manage for them.&lt;/p&gt;

&lt;p&gt;The same happened with my beloved Hounty: while a home cleaning photo-gallery worked for me - my kids used it once and never touched again.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Keep iterating"
&lt;/h2&gt;

&lt;p&gt;Between the first, currently released, fully offline version and the one in the making I built at least three more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Earn and burn family points&lt;/em&gt;: kids were gaming the system with the artisanry of a penetration tester&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Clean together&lt;/em&gt;: apparently cleaning together for them meant that I clean and they wander off doing something else&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Visual cleaning todo list&lt;/em&gt;: they do not differentiate between me nagging them remotely or in person and do not do what I asked them to do&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some things worked, for example once I was sitting at a table across a sofa. Sofa was covered in toys and snacks. I opened my mouth to bark at my daughter "You left a mess again! Go clean it up right now!", but I remembered an article I read that suggested that reframing the expectation on oneself could help with habit forming. So instead I started to rub my eyes and said: "Oh, you're not gonna believe it! I'm so sleepy - I see things that aren't there! I know you're a very tidy person and there's no way you'd left sofa in this state. So I'll just rob my eyes for a bit and hope it'll pass". As expected, she giggled and quickly cleaned up everything.&lt;/p&gt;

&lt;p&gt;One of my proudest parenting moments, that's for sure. Did it solve the problem for good? God, no! I attempted to do the same thing a few more times and she ignored it entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Know when to pivot"
&lt;/h2&gt;

&lt;p&gt;Clearly, it wasn't working at all, but I was using my own app and a few of my friends enjoyed it too. Maybe, just maybe I should pivot towards adults? Clearly the dopamine hit adults were getting from seeing before and after transformations by their own hands wasn't cutting it for kids.&lt;/p&gt;

&lt;p&gt;I did ask my kids more than once what makes cleaning hard for them and the answers varied between "It's boring" to "I don't know where to start" and the fated "I don't see any mess" that started this whole thing for me.&lt;/p&gt;

&lt;p&gt;I spoke to several people (thanks to "The Mom Test" I got a lot more successful in conducting user research) and I learned that there's a hundred of different problems adults face with cleaning: from decision fatigue to lack of knowledge to sticking to routines.&lt;br&gt;
How can I possible solve all of them with one app?!&lt;/p&gt;

&lt;p&gt;And even if I would, how would I market it and to whom?&lt;/p&gt;
&lt;h2&gt;
  
  
  (Re)-Positioning
&lt;/h2&gt;

&lt;p&gt;When I'm lost I either read or write and since I have had very limited knowledge in marketing or product positioning I found a book that resonated with me. "Obviously Awesome: How to Nail Product Positioning so Customers Get It, Buy It, Love It" brought a few new and interesting perspectives and eventually I was able to describe what I built in a way that even LLM could deduct what the app does from a few words.&lt;/p&gt;

&lt;p&gt;I asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Describe the features that a "home cleaning gallery app" would have please"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And Gemini said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;That's a great idea! A "Home Cleaning Gallery App" sounds like a helpful tool for visualization and motivation.

Here are the key features and functionalities such an app would likely include, organized by category:

📸 Core Gallery &amp;amp; Visualization Features
These features focus on the main purpose of the app: managing visual evidence of cleaning.

Before &amp;amp; After Albums:

The ability to easily pair a photo of a messy area ("Before") with a photo of the cleaned area ("After").

A side-by-side or swipe-to-reveal comparison view to dramatically showcase the results.

Room/Area Tagging:

Allow users to tag photos with the specific room (e.g., Kitchen, Bathroom 1, Kids' Playroom) or area (e.g., Under the sink, Pantry).

Filter/Search Functionality to view all photos for a specific room.

Time &amp;amp; Date Stamping:

Automatically record the date and time a photo was taken to track cleaning frequency and effort.

Detailed Photo Captioning:

Space to add notes describing what was done (e.g., "Deep clean of grout," "Organized spices").

📋 Task &amp;amp; Tracking Features
These features connect the visual evidence to the actual cleaning process.

Cleaning Checklist Integration:

Allow users to link photos to specific items on their cleaning checklist (e.g., "After" photo confirms the Cleaning the fridge task is complete).

Task History/Log: Review a historical list of all cleaning tasks, complete with their associated "After" photos.

Goal &amp;amp; Challenge Setting:

Set personal cleaning goals (e.g., "Clean every room once a week"). The app uses the "After" photos as confirmation of completion.

Cleaning Routine Templates:

Pre-set weekly, monthly, or seasonal cleaning routines that users can follow, checking off and photographing tasks as they go.

⭐ Motivation &amp;amp; Sharing Features
These features make the app engaging and provide a sense of accomplishment.

"Brag Board" or "Success Gallery":

A dedicated section to celebrate the best "After" photos, perhaps automatically generating a montage of the past week's accomplishments.

Gamification/Badges:

Award badges for milestones (e.g., Bathroom Master for 10 bathroom cleaning galleries, Consistency King for a streak of weekly cleaning).

Sharing Functionality:

Easy option to share the impressive "Before &amp;amp; After" comparisons to social media or messaging apps (perhaps with a watermark/branded frame).

"Inspiration Feed" (Optional):

A feed of user-submitted (or curated professional) cleaning photos/tips to inspire users and showcase what's achievable.

🛠️ Utility &amp;amp; Settings Features
These features focus on the practical use of the app.

Photo Storage Optimization:

A way to store the high volume of photos without clogging the user's main camera roll (cloud storage or dedicated in-app storage).

Secure Backup &amp;amp; Sync:

Cloud backup to ensure cleaning history and photos aren't lost when switching devices.

Privacy Controls:

Options to make sure photos aren't accidentally shared or visible outside of the app.

Would you like me to elaborate on one of these features, such as the Before &amp;amp; After Albums, or think about the user flow for creating a new cleaning entry?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So pretty much everything I had on my roadmap! Great success! Perfect positioning! I even made cute stickers:&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%2Fzcoo723cigvsgfwqwjcz.jpeg" 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%2Fzcoo723cigvsgfwqwjcz.jpeg" alt="Cute Hounty Ghost with " width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what kind of problem does a home cleaning photo gallery solve?&lt;/p&gt;

&lt;h2&gt;
  
  
  Painkillers vs Vitamins
&lt;/h2&gt;

&lt;p&gt;Despite gaining some traction with the redesigned and updated website, I still felt that something is not right. There were no sales to the one-time-paid app, which was to be expected given that I  placed zero effort to market it, but I just wasn't comfortable with the app anymore.&lt;/p&gt;

&lt;p&gt;It was working, in fact the approach was so effective - I learned how to clean up without it. I could now take all the images in my head and get the same result. And if I wasn't using it anymore, who would?&lt;/p&gt;

&lt;p&gt;On top of that, I learned about "painkillers and vitamins" framework and of course my beloved Hounty fell into the latter category. I got really dissaponted: not only the market was crowded with high-churn apps - the problem I was desperate to solve wasn't painful enough to warrant paying for the solution.&lt;/p&gt;

&lt;p&gt;I spent about a week feeling sorry for myself and making no progress, until I looked a bit deeper into that framework. It didn't make sense: my own phone was full of "vitamin" apps that were profitable.&lt;/p&gt;

&lt;p&gt;Turns out selling a "vitamin" is not nessesarily harder than selling a "painkiller", but it requires a very different way of marketing: focused on building a brand and a community to earn enough trust from potential users to show them the long term effects of their investment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a brand
&lt;/h2&gt;

&lt;p&gt;Shiny sticker on my phone case was haunting me every time I would do anything else but working on Hounty. Of course, I resisted for as long as I can: I rebuilt my personal website, wrote a few articles, built a few tiny apps, but untimately I couldn't put it off anymore. &lt;/p&gt;

&lt;p&gt;Despite of all of the challenges Hounty threw at me - I couldn't let go of it. Tiny cute little bugger kept on popping up in my head like a ghost he is. &lt;/p&gt;

&lt;p&gt;And so I sat and outlined what Hounty meant for me and what kind of a brand it would be and what kind of company would Hounty be:&lt;/p&gt;

&lt;h3&gt;
  
  
  Bold. Open. Clean.
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bold&lt;/strong&gt; choices, ambitious goals, infectious energy. We reach for the stars, fall hard and fast and celebrate our learnings as big as our successes. We do not wait for a permission, we build and iterate fast. We take ownership of problems and find solutions regardless of the area. We are everywhere and do everything we can to achieve our shared goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open&lt;/strong&gt; communication, open discussions, high trust environment. We show up as we are - warts and all - and stand tall. We accept that mistakes are inevitable and share our learnings openly. We say what we mean and we mean what we say - loud and clear, to the best of our abilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clean&lt;/strong&gt; interface, clean architecture, clear policies, clear rules and flat structure - our lines are clear and boring, our politics are built on mutual respect and empathy. We clean up when things get messy - as they always do - and try to do better than the last time.&lt;/p&gt;

&lt;p&gt;I even generated a &lt;a href="https://suno.com/song/2e70262f-df39-477f-b6e1-af850f71079b" rel="noopener noreferrer"&gt;Hounty anthem&lt;/a&gt; in Suno! Because why not?!&lt;/p&gt;

&lt;h3&gt;
  
  
  SoMe
&lt;/h3&gt;

&lt;p&gt;Where does one do branding nowadays if you have zero budget? Social media!&lt;/p&gt;

&lt;p&gt;I started consistently posting on &lt;a href="https://www.tiktok.com/@hounty.app" rel="noopener noreferrer"&gt;TikTok&lt;/a&gt; (apparently #CleanTok is a thing) and I'm happy to report that I have no idea what I'm doing, but I'm getting a dozen of likes on each post, so I am hopeful.&lt;/p&gt;

&lt;p&gt;Instagram doesn't seem to get any reaction, so I paused posting there till I have better ideas.&lt;/p&gt;

&lt;p&gt;In general I'm not a big fan of social media, so it's been a struggle to learn how to do it and, most importantly, how to do so without sacrificing my values.&lt;/p&gt;

&lt;h2&gt;
  
  
  One app is not enough
&lt;/h2&gt;

&lt;p&gt;As I was testing different approaches and iterating on how I present Hounty to the world, I realised that I can never build an app that would solve all the problems with housework and would continiously keep solving the new ones that would come in their stead.&lt;/p&gt;

&lt;p&gt;But what if I would build many apps: one for each problem, somehow connected between themselves. Kinda like microservices, but microapps? That might just work yet.&lt;/p&gt;

&lt;p&gt;The concept of microapps is not new and have been used to connect multiple corporate internal tools, but there they were joined together by a super-app.&lt;/p&gt;

&lt;p&gt;The main goal of Hounty is to make house work less overwhelming, so you could imagine how great a super-dashboard app would work out for that, right?&lt;/p&gt;

&lt;p&gt;But what if I don't build a superapp at all? What if I connect the apps in a way Google has been doing for years - with one account?&lt;/p&gt;

&lt;p&gt;If you judge the idea's worth based on how fast I can execute on it - then this one was a great one: I updated &lt;a href="https://hounty.app" rel="noopener noreferrer"&gt;hounty.app&lt;/a&gt; in an evening, everything was making sense and I was having fun again!&lt;/p&gt;

&lt;p&gt;And when I was done - I got really really scared.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Terrifying Thing
&lt;/h2&gt;

&lt;p&gt;I had no excuse anymore, the vision, the story, all of my ideas there were now at the open. Do you know what happens when you put your art out there? People would see it.&lt;/p&gt;

&lt;p&gt;And it's terrifying. Despite of all the research and gut feeling, despite of execution I'm almost-not-ashamed of, what happens next is no longer within my control.&lt;/p&gt;

&lt;p&gt;You could ask: what's the worst that could happen, Val? Someone won't like it, so what?&lt;/p&gt;

&lt;p&gt;And I would have to admit that it's not the reaction I'm afraid of. I am afraid that I won't get any reaction or lukewarm at best - data I won't be able to iterate on.&lt;/p&gt;

&lt;p&gt;You made far in this point and by now you know enough to judge Hounty and my ideas. If you feel up for it, check &lt;a href="https://hounty.app/" rel="noopener noreferrer"&gt;hounty.app&lt;/a&gt; and either sign-up for beta or share your unfiltered thoughts in the comments.&lt;/p&gt;

&lt;p&gt;Tell me all the ways it doesn't make sense, all the reasons why it wouldn't work, because, as scary as it is - I really want to give Hounty my best try.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>startup</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Pair-Coding CleanIt.Now with AI on Cloudflare Workers</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Sat, 08 Nov 2025 12:10:39 +0000</pubDate>
      <link>https://forem.com/valeriavg/pair-coding-cleanitnow-with-ai-on-cloudflare-workers-2967</link>
      <guid>https://forem.com/valeriavg/pair-coding-cleanitnow-with-ai-on-cloudflare-workers-2967</guid>
      <description>&lt;p&gt;After building a tiny Flutter offline timer "&lt;a href="https://dev.to/valeriavg/kvart-timer-from-idea-to-app-store-in-2-days-2c09"&gt;Kvart&lt;/a&gt;" (it got about 73 downloads so far!), I've set into building a fully functional fullstack web application in a few evenings next.&lt;/p&gt;

&lt;p&gt;How and why I switched to building AI assisted free microapps is a whole another story that can be narrowed down to me underestimating the amount of effort my beloved &lt;a href="https://hounty.app/" rel="noopener noreferrer"&gt;Hounty&lt;/a&gt; takes and looking for ways to iterate and test ideas faster.&lt;/p&gt;

&lt;p&gt;I'm pretty sure that services like Lovable or Cloudflare's own platform would allow me to vibe-code it much faster, but I'm not ready to let go of that amount of control just yet. Besides I just love choosing a tech stack for a new project, don't you?&lt;/p&gt;

&lt;p&gt;You probably can already tell that this article is not going to be a smooth "how to build a perfect app with one prompt", but instead it tells a story about how I build this particular app, what worked and what didn't to hopefully make your journey smoother or just have a few laughs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idea
&lt;/h2&gt;

&lt;p&gt;In a nutshell, &lt;a href="https://cleanit.now" rel="noopener noreferrer"&gt;CleanIt.Now&lt;/a&gt; allows you to take pictures of the mess and send it to the person who made the mess in the first place so that they'd clean it up and send you pictures as a proof back. And, as the name suggests, each task has an expiration date: 24 hours, to be precise.&lt;/p&gt;

&lt;p&gt;The architectural approach I had in mind could be described as Cloudflare's R2 bucket with &lt;a href="https://developers.cloudflare.com/r2/buckets/object-lifecycles/" rel="noopener noreferrer"&gt;object livecycle policy&lt;/a&gt; and some-kind-of-signed URLs.&lt;/p&gt;

&lt;p&gt;And when I was buying the domain name it was more like "Hehe, it would be cool to send cleanit.now/something to my daughter" rather than "I have a whole business plan figured out". &lt;/p&gt;

&lt;p&gt;I still don't, but that's the beauty of it: I get to follow an idea and see it grow and turn into something. It's art, it's therapeutic.&lt;/p&gt;

&lt;p&gt;Now, let's talk about tools! &lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;Maybe one day I will let LLM decide on the tech stack (when it would offer anything but Tailwind and React perhaps), but that day is yet to come.&lt;/p&gt;

&lt;p&gt;At the moment my favourite fullstack framework is &lt;a href="https://hono.dev/" rel="noopener noreferrer"&gt;Hono&lt;/a&gt; and for this project I decided to give &lt;a href="https://www.solidjs.com/" rel="noopener noreferrer"&gt;SolidJS&lt;/a&gt; a try for the frontend.&lt;/p&gt;

&lt;p&gt;I quite liked it, though Claude &amp;amp; Copilot wrote most of SolidJS code, so I suppose "I liked reading SolidJS code" would be more precise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Planning
&lt;/h2&gt;

&lt;p&gt;I started with Claude Code in planning mode. We discussed a few approaches and settled into a plan that consisted of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We start with frontend single page application&lt;/li&gt;
&lt;li&gt;We use Cloudflare Workers for the backend&lt;/li&gt;
&lt;li&gt;It'll be a monorepo with two folders: &lt;code&gt;backend&lt;/code&gt; and &lt;code&gt;frontend&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We will use custom JSON web tokens for signing urls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Excited, I asked Claude to document the implementation plan and it produced extremely detailed markdown document full of weird suggestions. I didn't save a copy of it, after a request to clean it up and some manual refinement I ended up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# CleanIt.Now - Implementation Plan&lt;/span&gt;

&lt;span class="gu"&gt;## Overview&lt;/span&gt;
A full-stack web application for creating and managing temporary cleaning task lists with anonymous access, real-time collaboration, and automatic 24-hour expiration.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Phase 1: Frontend (Local Preview)&lt;/span&gt;

&lt;span class="gu"&gt;### Tech Stack&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**SolidJS**&lt;/span&gt; - Reactive UI framework
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Vite**&lt;/span&gt; - Build tool &amp;amp; dev server
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**TypeScript**&lt;/span&gt; - Type safety
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**CSS Modules**&lt;/span&gt; - Scoped CSS styling
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**nanoid**&lt;/span&gt; - ID generation
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**npm workspaces**&lt;/span&gt; - Monorepo structure

&lt;span class="gu"&gt;### Type Definitions&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
typescript&lt;br&gt;
TaskList {&lt;br&gt;
  id: string (nanoid)&lt;br&gt;
  title?: string&lt;br&gt;
  tasks: Task[]&lt;br&gt;
  created: string (ISO Date)&lt;br&gt;
  expiresAt: string (ISO Date)&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Task {&lt;br&gt;
  id: string (nanoid)&lt;br&gt;
  images: { before: string, after?: string } (blob URLs, optional)&lt;br&gt;
  completed: boolean&lt;br&gt;
  created: string (ISO Date)&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---

## Phase 2: Backend &amp;amp; Persistence

### Tech Stack
- **Hono** - Lightweight web framework
- **Cloudflare Workers** - Serverless compute
- **Cloudflare R2** - Object storage
- **JWT** - Authentication/authorization
- **Rate Limiting** - Abuse prevention

## Notes

- Event sourcing architecture ensures no data loss during sync
- All timestamps use ISO 8601 format
- JWT tokens expire with the list (24 hours)
- R2 storage is cost-effective for 24h retention
- Frontend can work offline, sync when online
- Consider adding optimistic UI updates for better UX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suffices to say, that while the current version mostly follows the plan - the only useful part about it were types. &lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;I prefer to see how the app would look like before I start building the backend, so I usually start with the frontend, but it's viable either way.&lt;/p&gt;

&lt;p&gt;So far LLMs very surprisingly good at frontend tasks or, perhaps, I was better at explaining what I needed.&lt;/p&gt;

&lt;p&gt;I started with a request to scaffold a new SolidJS SPA with some lightweight CSS-in-JS. Claude offered me a few options, but they were either outdated or had weird syntaxis. So in the end Claude suggested to just go with CSS modules and I relented.&lt;/p&gt;

&lt;p&gt;We started with "a modern app-like header" and step by step made our way to a god-awful multi-color monstrosity akin to my first projects in BootstrapCSS.&lt;/p&gt;

&lt;p&gt;Luckily "make it look more like Instagram, use grayscale" seemed to have fixed it, though blue buttons kept popping up every now and then.&lt;/p&gt;

&lt;p&gt;The app now consisted of an editable title (which proven far more challenging for LLM than I anticipated), two tabs: Edit and Preview and a sortable grid under the first tab.&lt;/p&gt;

&lt;p&gt;Surprisingly, as Claude struggled with making "just a goddamned accessible input please", it had no issues with drag and drop and state management. My only guess is that there hasn't been that many articles on semantic html markup in comparison to drag and drop functionality and thus got lost in the sea of training data.&lt;/p&gt;

&lt;p&gt;It took me just an evening to get to this point which was very reassuring! I even managed to squeeze in a landing page with text and all - Claude did exceptionally well there (or I didn't care enough to correct at this point - we'll never know).&lt;/p&gt;

&lt;p&gt;Excited to build the backend endpoints, I went to bed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;I genuinely thought that this part would be a walk in the park: there wasn't any complicated logic and just a few endpoints. And so I got this brilliant idea of using TDD for it!&lt;/p&gt;

&lt;p&gt;Now, I'm a big fan and supporter of test-driven development and when I do write tests they catch a great deal of errors, but I find the process of writing tests so excrusuatingly boring that in most cases I write only a few of them if any. Till stuff breaks that is.&lt;/p&gt;

&lt;p&gt;But this time I could pull a whole bunch of them out of thin air!&lt;br&gt;
And so I described the endpoints I wanted it to build and suggested Claude to use TDD for it.&lt;/p&gt;

&lt;p&gt;Here is how my code structure looked like after that:&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.amazonaws.com%2Fuploads%2Farticles%2F7wesek8srlezp8xdzyih.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%2F7wesek8srlezp8xdzyih.png" alt="VSCode interface with several files and folders in the tests folder and just a few of them in src" width="610" height="1178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You could notice that there are far more tests than actual code and a top of that most of the logic is stuffed into an &lt;code&gt;index.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It took me a few hours to review what it generated, correct it, ask to refactor specific bits and in the end I ended up writing some of the endpoints myself with the help of code completion.&lt;/p&gt;

&lt;p&gt;The tests aren't currently passing and I'm tempted to throw the whole folder away and rewrite them from scratch when something breaks. You know, old school.&lt;/p&gt;

&lt;p&gt;But jokes aside, it's very easy to ask AI to generate something and it will, but just like it is with the humans - GenAI produces far better results when you ask them for a very specific thing. Next time I'll outline what I want to test and ask an LLM to fill in the gaps and see if it works better. &lt;/p&gt;

&lt;p&gt;By the way, this is how the "Full flow" test starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should complete full flow: create list -&amp;gt; upload images -&amp;gt; share&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Skipping due to known vitest-pool-workers issue with FormData in long tests&lt;/span&gt;
    &lt;span class="c1"&gt;// The individual handler tests cover this flow in isolation&lt;/span&gt;
    &lt;span class="c1"&gt;// Step 1: Create a list&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yeah, no.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing in production
&lt;/h2&gt;

&lt;p&gt;By the end of the second day, the backend implementation was ready, everything was working great locally and I deployed it all to Cloudflare.&lt;/p&gt;

&lt;p&gt;Claude taught me a neat trick with &lt;a href="https://developers.cloudflare.com/workers/static-assets/binding/" rel="noopener noreferrer"&gt;Cloudflare assets binding&lt;/a&gt; which allowed me to do things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:listId/:token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Check accept header and serve SPA frontend if HTML is requested&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;acceptHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;acceptHeader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ASSETS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/view.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At some point I should definitely look into how it all (landing page, SPA and worker code) is bundled together because I have a few issues with HMR (it doesn't work at all), but the app went live and static pages looked good.&lt;/p&gt;

&lt;p&gt;And then I tried and failed to create a new list, then to upload a photo, then to upload a few photos and finally to complete the list.&lt;/p&gt;

&lt;p&gt;After fighting the bugs for a few hours, releasing yet another and another version and seeing that while everything worked brilliantly on my laptop it failed on mobile at the last step again - I threw in a towel and went to sleep.&lt;/p&gt;

&lt;p&gt;Luckily, sleeping on it helped and the morning of the third day (today) I was ready to show CleanIt.Now to the world!&lt;/p&gt;

&lt;h2&gt;
  
  
  What did I learn from this experience?
&lt;/h2&gt;

&lt;p&gt;The biggest takeaway is that me and LLMs still have a long road ahead of us before we'd learn how to communicate properly with each other. And I am nowhere ready to offload all the coding to the agents, though they can have my frontend bits, if they promise to build accessible solutions (it's best to use an existing design system like Tailwind it appears, but it works more or less okay either way).&lt;/p&gt;

&lt;p&gt;I will have to try and write the plan, types and tests cases myself next time. I was being lazy and let LLMs run wild and ended up with expectable outcome. Vision is on the creator, that's not something to delegate, as I've learned times and times again.&lt;/p&gt;

&lt;p&gt;I'm curious, what do you think of &lt;a href="https://cleanit.now/" rel="noopener noreferrer"&gt;CleanIt.Now&lt;/a&gt;? Did I miss something obvious? Anything I could do better?&lt;/p&gt;

&lt;p&gt;Share your thoughts in the comments and thank you for sticking around! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>startup</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Kvart Timer: From Idea to App Store in 2 days</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Fri, 31 Oct 2025 06:32:19 +0000</pubDate>
      <link>https://forem.com/valeriavg/kvart-timer-from-idea-to-app-store-in-2-days-2c09</link>
      <guid>https://forem.com/valeriavg/kvart-timer-from-idea-to-app-store-in-2-days-2c09</guid>
      <description>&lt;p&gt;A friend of mine, who works as an organizer, told me that some of her neurodivergent clients are very fond of physical timers for cleaning and count how long it would take in "kvarts". Notably what was helping the most is not the timer itself nor the magic of 15 minutes, but seeing the flow of time.&lt;/p&gt;

&lt;p&gt;When I came back home I asked Claude to research visual timer apps and common pain points. Turns out there were a few and I could probably build something that would work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TL;DR&lt;/em&gt;: The app is available on &lt;a href="https://apps.apple.com/se/app/kvart/id6754662969?l=en-GB" rel="noopener noreferrer"&gt;App Store&lt;/a&gt; and the code is available on &lt;a href="https://github.com/ValeriaVG/kvart" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've been working on Hounty for the past 9 months now so instead of giving that new app idea a try I convinced myself to keep pushing with the existing one.&lt;/p&gt;

&lt;p&gt;After I've spent a few hours on Hounty and saw that my sync feature was messing up dates and losing images I threw in a towel: I needed a break. And maybe to learn a little bit more of Flutter? And what's best for learning if not building something small and a bit different?&lt;/p&gt;

&lt;h2&gt;
  
  
  A Plan
&lt;/h2&gt;

&lt;p&gt;With my plan to build fast, I knew I needed to be strategic about scope. I could dedicate a few evenings and no more to take the app from design to app store submission. And it has to be a fully functional app with a viable business model, no less.&lt;/p&gt;

&lt;p&gt;I gave myself permission to try out whatever I wanted. I created a new flutter project and wrote the plan in &lt;code&gt;README.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Kvart&lt;/span&gt;

Kvart (from Swedish "kvart", meaning "quarter") is a visual timer app written in Flutter. 
It does one thing and does it well: it helps you keep track of time in set intervals.

&lt;span class="gu"&gt;## How to use&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; Open the app.
&lt;span class="p"&gt;2.&lt;/span&gt; Select your desired time interval from a preset or add a new one
&lt;span class="p"&gt;3.&lt;/span&gt; Tap the timer to start/pause/resume.
&lt;span class="p"&gt;4.&lt;/span&gt; Go on with your work / cleaning / cooking / studying / gaming / exercising / meditating / relaxing...
&lt;span class="p"&gt;5.&lt;/span&gt; Optionally, tap the "+ 15 min" or another preset to add one more "kvart" (15 minutes) to the current timer
&lt;span class="p"&gt;6.&lt;/span&gt; When the timer ends, you'll receive a notification - by default, a gentle sound and vibration.
&lt;span class="p"&gt;7.&lt;/span&gt; Repeat as needed!&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gu"&gt;## Core concepts&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Start timer in under 3 taps
&lt;span class="p"&gt;-&lt;/span&gt; Clear visual indication of passing time
&lt;span class="p"&gt;-&lt;/span&gt; Ability to add one more "kvart" at any moment
&lt;span class="p"&gt;-&lt;/span&gt; No forced breaks or interruptions
&lt;span class="p"&gt;-&lt;/span&gt; Reliable background operations &amp;amp; local notifications
&lt;span class="p"&gt;-&lt;/span&gt; Sensible defaults &amp;amp; customizable intervals and notifications
&lt;span class="p"&gt;-&lt;/span&gt; Offline only, no account or login required
&lt;span class="p"&gt;-&lt;/span&gt; Privacy first, no data collection or tracking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This plan wasn't perfect and I changed a few bits in the process, but that's where I started. Notably, there was nothing here about monetization, which, given the fact that I was set on keeping this app open source, was an interesting challenge to adress.&lt;/p&gt;

&lt;p&gt;Nonetheless, it was good enough to tell Claude Code to go and build the timer screen: I wanted an "arc" and a background "notch" in specific colors. Claude created a &lt;code&gt;timer.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I played a bit with the code and changed a few numbers here and there, asked to add some "realistic notches", scrapped it and settled onto something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:math'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFF020C1D&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;TimerView&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimerView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;TimerView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CustomPaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;painter:&lt;/span&gt; &lt;span class="n"&gt;TimerArcPainter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;'15:00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;letterSpacing:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimerArcPainter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CustomPainter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;TimerArcPainter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Canvas&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;startAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;sweepAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;strokeWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;32.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Rect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromCircle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;center:&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;radius:&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;progressSweepAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sweepAngle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Draw the background track&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;backgroundPaint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Paint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFF0A1A30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PaintingStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stroke&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strokeWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strokeWidth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strokeCap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StrokeCap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startAngle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sweepAngle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backgroundPaint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Draw the main arc&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Paint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFFC5F974&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PaintingStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stroke&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strokeWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strokeWidth&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strokeCap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StrokeCap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startAngle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;progressSweepAngle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;shouldRepaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;covariant&lt;/span&gt; &lt;span class="n"&gt;CustomPainter&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Counting Time, Reliably
&lt;/h2&gt;

&lt;p&gt;One of the things that came out of Claude research was a very common pain point that timers were stopping or lagging behind when app was backgrounded punishing users for answering the phone, opening another app or, worst of all, placing the phone aside to do the task they were going to do in the first place. &lt;/p&gt;

&lt;p&gt;Calculating progress is simple: divide time left by total time, but when the app is in the background it's essentially paused to save resources, so just counting how many seconds have passed is not enough.&lt;/p&gt;

&lt;p&gt;I asked Claude to build the ability to track the time by storing timestamps instead. I made a few edits, asked to switch to finite state machine and ended up with this &lt;code&gt;timer_controller.dart&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paused&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimerController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;TimerState&lt;/span&gt; &lt;span class="n"&gt;_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TimeInterval&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_intervals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;startTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;running&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;running&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_intervals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;pauseTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paused&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_intervals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;resetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimerState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_intervals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;TimerState&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Stream of seconds elapsed&lt;/span&gt;
  &lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;elapsedSeconds&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;totalDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_intervals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;totalDuration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inSeconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimeInterval&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;TimeInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_end&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;endTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_end&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;endTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_end&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was ticking! &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%2F11s9wux7b1maugxif9gc.gif" 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%2F11s9wux7b1maugxif9gc.gif" alt="It's Alive GIF" width="498" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven Segment Display
&lt;/h2&gt;

&lt;p&gt;As the timer was ticking, the display was "wobbling" around and switching to a monospace font didn't seem to help without installing one. So I got an idea to build the "digit clock display", Claude helped me out and taught me that it was called "Seven Segment Display":&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.amazonaws.com%2Fuploads%2Farticles%2Fgwhmx47pmon35ax65gwm.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%2Fgwhmx47pmon35ax65gwm.png" alt="8 on a display with pins from A-F clockwise and G in the middle" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However I needed to adjust the code quite heavily - some parts were weird and the display looked clunky. Eventually I ended up with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// A widget that displays a single digit (0-9) using a seven-segment display style.&lt;/span&gt;
&lt;span class="c1"&gt;///&lt;/span&gt;
&lt;span class="c1"&gt;/// The segments are arranged like this:&lt;/span&gt;
&lt;span class="c1"&gt;///     _a_&lt;/span&gt;
&lt;span class="c1"&gt;///   f|   |b&lt;/span&gt;
&lt;span class="c1"&gt;///     _g_&lt;/span&gt;
&lt;span class="c1"&gt;///   e|   |c&lt;/span&gt;
&lt;span class="c1"&gt;///     _d_&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SevenSegmentDigit&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SevenSegmentDigit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
         &lt;span class="s"&gt;'Digit must be between 0 and 9'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;/// Returns which segments should be lit for each digit (0-9)&lt;/span&gt;
  &lt;span class="c1"&gt;/// Segments: [a, b, c, d, e, f, g]&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_getSegmentsForDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CustomPaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;size:&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;painter:&lt;/span&gt; &lt;span class="n"&gt;_SevenSegmentPainter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;segments:&lt;/span&gt; &lt;span class="n"&gt;_getSegmentsForDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;onColor:&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;offColor:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;segmentThickness:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_SevenSegmentPainter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CustomPainter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;_SevenSegmentPainter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Canvas&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Paint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PaintingStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fill&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strokeCap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StrokeCap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strokeJoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StrokeJoin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Calculate segment positions&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;topY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;middleY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;bottomY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;leftX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;rightX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;centerX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Draw each segment&lt;/span&gt;
    &lt;span class="c1"&gt;// Segment A (top horizontal)&lt;/span&gt;
    &lt;span class="n"&gt;_drawHorizontalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centerX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Segment B (top right vertical)&lt;/span&gt;
    &lt;span class="n"&gt;_drawVerticalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rightX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Segment C (bottom right vertical)&lt;/span&gt;
    &lt;span class="n"&gt;_drawVerticalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rightX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Segment D (bottom horizontal)&lt;/span&gt;
    &lt;span class="n"&gt;_drawHorizontalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centerX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottomY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Segment E (bottom left vertical)&lt;/span&gt;
    &lt;span class="n"&gt;_drawVerticalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;leftX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Segment F (top left vertical)&lt;/span&gt;
    &lt;span class="n"&gt;_drawVerticalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;leftX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Segment G (middle horizontal)&lt;/span&gt;
    &lt;span class="n"&gt;_drawHorizontalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centerX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;_drawHorizontalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Canvas&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Paint&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Offset&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;moveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;_drawVerticalSegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Canvas&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Paint&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Offset&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;moveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;shouldRepaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;covariant&lt;/span&gt; &lt;span class="n"&gt;_SevenSegmentPainter&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;segments&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;segments&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;offColor&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offColor&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DigitSeparatorPainter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CustomPainter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;thickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;DigitSeparatorPainter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thickness&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Canvas&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Paint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PaintingStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;centerX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;centerY1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;centerY2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Draw top dot&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawCircle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centerX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;centerY1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;thickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Draw bottom dot&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawCircle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centerX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;centerY2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;thickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;shouldRepaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;covariant&lt;/span&gt; &lt;span class="n"&gt;DigitSeparatorPainter&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;thickness&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldDelegate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SevenSegmentDisplay&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;digitWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;digitHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SevenSegmentDisplay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0DFFFFFF&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digitWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digitHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;minTens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;minUnits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;secTens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;secUnits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;mainAxisSize:&lt;/span&gt; &lt;span class="n"&gt;MainAxisSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;SevenSegmentDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;digit:&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minTens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;digitWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="n"&gt;digitHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;segmentThickness:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;onColor:&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;offColor:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SevenSegmentDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;digit:&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;digitWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="n"&gt;digitHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;segmentThickness:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;onColor:&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;offColor:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;CustomPaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;size:&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digitHeight&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;painter:&lt;/span&gt; &lt;span class="n"&gt;DigitSeparatorPainter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SevenSegmentDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;digit:&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;secTens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;digitWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="n"&gt;digitHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;segmentThickness:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;onColor:&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;offColor:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SevenSegmentDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;digit:&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;secUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="n"&gt;digitWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="n"&gt;digitHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;segmentThickness:&lt;/span&gt; &lt;span class="n"&gt;segmentThickness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;onColor:&lt;/span&gt; &lt;span class="n"&gt;onColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;offColor:&lt;/span&gt; &lt;span class="n"&gt;offColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finishing Touches
&lt;/h2&gt;

&lt;p&gt;Once the main functionality was working, it took a few prompts and a couple of hours to get the sound to play (I spent more time choosing sounds on Uppbeat), add settings and theming. &lt;/p&gt;

&lt;p&gt;At around 2AM I added an in app purchase functionality for the Fallout-inspired amber theme (viable business model, yay!), filled in app submission details and released on TestFlight.&lt;/p&gt;

&lt;p&gt;I noticed a few bug with timer going over time after coming from the background, squashed some more and submitted the app for review. Review took more than the development itself this time, but the app passed it on the first try!&lt;/p&gt;

&lt;p&gt;I really enjoyed building this fast, and now I'm trying to figure out how to turn the rest of my ideas into micro-apps. Maybe that's what they meant with all the lean development and agile after all 😂&lt;/p&gt;

&lt;p&gt;The app is live on &lt;a href="https://apps.apple.com/se/app/kvart/id6754662969?l=en-GB" rel="noopener noreferrer"&gt;App Store&lt;/a&gt; and fully open source on &lt;a href="https://github.com/ValeriaVG/kvart" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you build something with it or create your own micro-app, I'd love to hear about it!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>devjournal</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How do I delegate when I can do it faster myself?</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Tue, 28 Oct 2025 18:24:33 +0000</pubDate>
      <link>https://forem.com/valeriavg/how-do-i-delegate-when-i-can-do-it-faster-myself-5lh</link>
      <guid>https://forem.com/valeriavg/how-do-i-delegate-when-i-can-do-it-faster-myself-5lh</guid>
      <description>&lt;p&gt;I remember why I became a manager. The team needed someone to advocate for their growth, compensation and overall well-being. I knew very little about leadership or management and the resources were somewhat scarce - I didn't even know what to look for. But I was determined to do my best.&lt;/p&gt;

&lt;p&gt;At times my best meant doing everything myself. After all, I was the most experienced engineer on the team. I could write code faster than anyone else, review PRs quicker than anyone else and ship features quicker than anyone else. Well, not really, but I'd like to think so anyway. &lt;/p&gt;

&lt;p&gt;Every once in a while I'd make a stupid mistake, miss a bug or forget to test something properly and these moments suck. They made me doubt my abilities as an engineer and a manager. If I can't even do my job properly, how can I expect others to do it for me?&lt;/p&gt;

&lt;p&gt;I did do some things right: I have been the first one to point out my mistake, own it and fix it. I have been transparent about my shortcomings and asked for help when needed. I was very proud that I could be a manager who still codes, who still understands the technical challenges and can help the team out.&lt;/p&gt;

&lt;p&gt;It was all going great till one day at the retro a developer said: "You know, Valeria, you should stop coding. Let us handle it, we can do it ourselves."&lt;/p&gt;

&lt;h2&gt;
  
  
  "You should stop coding"
&lt;/h2&gt;

&lt;p&gt;Oh boy, did that hit me hard. I was doing my best to be a good manager and a good engineer, and now I was being told to stop coding altogether? It felt like a rejection of my skills and my contributions to the team. I was confused and frustrated. Why would they want me to stop coding? Was I not good enough? Was I not contributing enough?&lt;/p&gt;

&lt;p&gt;I did listen. Well, almost. I still code, years after, but I no longer do that within my team. I can pick up some small side tasks here and there, but I don't own any features or projects. I don't review PRs or write tests. I don't deploy code or fix bugs. I delegate all of that to my team.&lt;/p&gt;

&lt;p&gt;Not because I'm incompetent, but because they needed space to grow. They needed to own their work, make mistakes and learn from them. They needed to feel empowered and trusted. And I was in the way.&lt;/p&gt;

&lt;p&gt;Here's the paradox: the fact that I &lt;em&gt;could&lt;/em&gt; do it faster was precisely the problem. Every time I jumped in to save time, I was robbing them of the chance to develop their own speed, their own judgement, their own mastery. I was optimizing for today's velocity at the cost of tomorrow's capability.&lt;/p&gt;

&lt;p&gt;So how do you delegate when you can do it faster yourself? You delegate &lt;em&gt;because&lt;/em&gt; you can do it faster. Because if you don't, your team will never get the practice they need to eventually do it faster than you ever could.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feeling guilty about not coding is normal
&lt;/h2&gt;

&lt;p&gt;My whole identity was wrapped around being a great engineer. I was proud of my technical skills and my ability to deliver results. Who am I now that I'm not coding anymore? Am I still valuable? Am I still relevant?&lt;/p&gt;

&lt;p&gt;To top it all off, I was still painfully aware of how little I knew about management. I was making mistakes left and right, trying to figure out how to lead a team, how to communicate effectively, how to motivate and inspire others. I was constantly doubting myself, wondering if I was doing the right thing, spiraling into a vortex of imposter syndrome.&lt;/p&gt;

&lt;p&gt;It didn't matter that I was getting praise left and right, I felt like a fraud. I felt like I was pretending to be a manager, while deep down I was just an engineer who couldn't code anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  WTF Button
&lt;/h2&gt;

&lt;p&gt;Instinctively, I was searching for a new identity. I wanted to find a way to feel valuable again. I wanted to find a way to contribute to the team, to the company, to the world.&lt;/p&gt;

&lt;p&gt;One day one of the developers called me a "WTF Button" - whenever they were stuck, confused or frustrated, they would come to me and ... I'd solve it for them. Just like that. No questions asked. Just hand it over to me and I'd fix it.&lt;/p&gt;

&lt;p&gt;It worked for a while, even though now I'm cringing at the thought of it.&lt;br&gt;
Nonetheless, it did help me find a new way to contribute. I was no longer coding, but I was still helping the team. I was still solving problems, just in a different way.&lt;/p&gt;

&lt;p&gt;I thought I was being a mentor, a guide, a coach (I wasn't, but it took a bit to figure that one out). I always had an answer and a solution. I was the go-to person for everything. I was the one-and-only WTF Button.&lt;/p&gt;

&lt;p&gt;But something was still off. &lt;/p&gt;

&lt;h2&gt;
  
  
  Manager or therapist?
&lt;/h2&gt;

&lt;p&gt;At some point I realised that there's more to being a manager than just solving technical problems. There's also the human side of things. The side that involves those pesky feelings and interpersonal dynamics.&lt;/p&gt;

&lt;p&gt;Psychology has always fascinated me and I found myself reading books and articles about it, trying to understand how people think, feel and behave. I wanted to be a better manager, a better leader, a better human being.&lt;/p&gt;

&lt;p&gt;I had the best intentions, but I was still struggling: I was trying to fix everything for everyone. A caring, empathetic, misguided Emotional-WTF Button.&lt;/p&gt;

&lt;p&gt;My team loved me and hated me for it. Thank god I learned to read the room and not push when they needed space.&lt;/p&gt;

&lt;p&gt;My team, they were so understanding with me and patient! I'm certain that I wouldn't have learned without them letting me fall flat on my face a few times.&lt;/p&gt;

&lt;p&gt;Luckily, I stumbled upon "The Phoenix Project" by Gene Kim &amp;amp; co and my falls become way more strategic. I got absolutely inspired, by Bill Palmer, the protagonist, but even more by his mentor, Erik.&lt;/p&gt;

&lt;p&gt;Erik reminded me of a "Good Witch" Cassie Nightingale - a magician who knows what to say and when to say it. A wise, experienced guide who helps the hero find their way to what they must do without any direct interference. Everyone knows that they did something, but no one can really point out what it was and to all intents and purposes, the hero did it all by themselves.&lt;/p&gt;

&lt;p&gt;I was clearly not even close to that level! I was way too involved: the problem solver, the fixer. &lt;/p&gt;

&lt;p&gt;I didn't even know how to measure the impact of my or my team's work!&lt;/p&gt;

&lt;h2&gt;
  
  
  What number should go up for you to be happy?
&lt;/h2&gt;

&lt;p&gt;One of my favourite moments from the book was when Bill asked CFO, Dick Laundry (I have a feeling that the authors don't like CFOs): "What number should go up for you to be happy?", which kickstarted the whole DevOps transformation.&lt;/p&gt;

&lt;p&gt;I started to wonder what number would that be and who should I even ask? I asked my manager and he said that he's happy with my work and that I should keep doing what I'm doing. &lt;/p&gt;

&lt;p&gt;I don't blame him: I had a dozen developers spread across 5 teams, each with their own goals and metrics. I knew goals for the company, but how do I move RevPAR (Revenue per Available Room) with just web developers, excluding designers, integration and backend engineers? Especially since I had no idea what their work really entailed on day-to-day basis.&lt;/p&gt;

&lt;p&gt;I had no idea and at that point I blamed our setup for it. I even came up with a couple of "strategic initiatives" on how to fix up our product teams.&lt;/p&gt;

&lt;p&gt;I really wish I knew what I was starting back then. A lot of good came out of it, but it was a long and painful journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stakeholder management
&lt;/h2&gt;

&lt;p&gt;One of the biggest challenges I faced as a manager was dealing with stakeholders. They had their own agendas, priorities and expectations, wanted things done their way and yesterday.&lt;/p&gt;

&lt;p&gt;Now while I was playing the WTF Button they didn't mind - the problems were getting solved, after all. But once I started to poke at the process, they were not too happy about it.&lt;/p&gt;

&lt;p&gt;Prior to product teams they could never align resources between different tech departments. Expectedly (for me now), the idea of going back to "silos" was causing them a lot of negative emotions.&lt;/p&gt;

&lt;p&gt;It wasn't pleasant, but after being surprised that my super-awesome proposal was met with a "hell no", I realised how little I knew about people me and my team were working with.&lt;/p&gt;

&lt;p&gt;In my head my only stakeholders were the developers and perhaps my manager. In reality, there were lots of people we depended on, each had their own goals and metrics and I knew nothing about their needs.&lt;/p&gt;

&lt;p&gt;"Business is about people", they say. I think I finally understand what that means: it's about learning their needs, removing their obstacles and respecting their boundaries.&lt;/p&gt;

&lt;p&gt;Easier said than done, that's for sure.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to be at 5 places at once?
&lt;/h2&gt;

&lt;p&gt;When I sat down to map out all the stakeholders, I was shocked. There were so many of them! Product managers, designers, content editors, customer support, data, architects, security... the list was endless. Each of them had their own priorities, timelines and expectations. How was I supposed to keep track of all of them? How was I supposed to manage their expectations? How was I supposed to make sure that everyone was on the same page?&lt;/p&gt;

&lt;p&gt;Clearly at this point coding or technical problem solving was the least of my worries. I spent so much time preparing slides and attending meetings that I barely had time to think about anything else.&lt;/p&gt;

&lt;p&gt;And then it hit me: I was at a point where I had to delegate not only technical parts, but management as well. There was no way for me to do it all and be everywhere at once and 1-1s alone were taking most of my calendar slots.&lt;/p&gt;

&lt;p&gt;I started to look into team topologies and among other things it became very obvious that each team needs a clear purpose to succeed.&lt;br&gt;
Ours had 5 instead.&lt;/p&gt;

&lt;p&gt;That meant that we had to split.&lt;br&gt;
Luckily at this point I already knew who in the team was leaning towards people management and we came up with a special "Web Goal Keeper" role in several of the teams. As the title could hint, I delegated goal setting to couple of team members. &lt;/p&gt;

&lt;p&gt;Having a dedicated person to own the goals within the team made a huge difference. It freed me up to focus on the bigger picture and gave each member clear objectives that they could achieve while doing their day-to-day work.&lt;/p&gt;

&lt;h2&gt;
  
  
  But numbers?
&lt;/h2&gt;

&lt;p&gt;I still couldn't answer the questions about our impact. I tried different approaches, from OKRs to KPIs to simple metrics dashboards. Nothing seemed to work.&lt;/p&gt;

&lt;p&gt;The solution came when my most prized initiative, the Foundation Team, was disbanded.&lt;br&gt;
It was a team that was supposed to own the shared infrastructure and work on strategic prototypes.&lt;/p&gt;

&lt;p&gt;It had been a cross-functional team, but only engineers from my team were excited about it. So when the other ones decided to pull out, I simply had to let it go.&lt;/p&gt;

&lt;p&gt;But before that, I had a chance to talk to a product manager about success metrics needed to secure buy-in from their side (they didn't understand nor support the idea of a Foundation Team).&lt;/p&gt;

&lt;p&gt;And what she taught me is that before you have metrics, you need to have a Vision. One distilled reason for the team to exist. A North Star that everyone can rally around, including stakeholders, tightly linked to shared goals.&lt;/p&gt;

&lt;p&gt;Once you have that, metrics become much easier to define: what numbers should go up for that vision to come to pass faster?&lt;/p&gt;

&lt;p&gt;I started thinking about the vision. Not the split tiny ones for each team, but the big one for all of us.&lt;/p&gt;

&lt;h2&gt;
  
  
  If we were a startup...
&lt;/h2&gt;

&lt;p&gt;If we'd be a startup, what would be our mission? What would be our purpose? What would be our why?&lt;/p&gt;

&lt;p&gt;And the answers started to come.&lt;br&gt;
We were experts in web development. We were working as long term consultants for several teams within the company. We had insider knowledge and we were building reliable in-house solutions.&lt;/p&gt;

&lt;p&gt;Around the same time I got introduced to the concept of SLIs and SLOs (Service Level Indicators and Service Level Objectives) and it all clicked.&lt;/p&gt;

&lt;p&gt;In one short session we aligned on our SLIs and objectives for the next 3 months together with the team. We picked the ones that were directly linked to guest experience and business outcomes: latency, availability and costs.&lt;/p&gt;

&lt;p&gt;And then the next day we had a dashboard to look at.&lt;br&gt;
Pure, distilled accountability: we could see exactly what we could control and knew what to prioritise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Culture &amp;lt;3 KPIs
&lt;/h2&gt;

&lt;p&gt;One downfall of numbers is that they can be gamed. If you only care about latency, you'll cut corners on user experience (cache it all) or security (let's serve everything from the edge). If you only care about availability, you'll ignore costs. And if you only care about costs, you'll cut corners on everything else.&lt;/p&gt;

&lt;p&gt;Without the culture to keep team aligned on the right values, KPIs can lead to disastrous outcomes.&lt;br&gt;
Some say blindly following KPIs is the root of all evil and source of many bankruptcies. I cannot neither confirm nor deny that, but it does make sense to me.&lt;/p&gt;

&lt;p&gt;I don't like the idea of placing people into tiny little boxes with labels on it, even though I see value of KPIs and OKRs. People are complex and multi-dimensional, and reducing them to a set of numbers is compelling, but dehumanising.&lt;/p&gt;

&lt;p&gt;By that time I've attended a few leadership workshops (I should have done that sooner) and read a couple of books on culture building ("The Culture Code" by Daniel Coyle is a masterpiece, by the way) and now I had the knowledge to offset the risks of numbers.&lt;/p&gt;

&lt;p&gt;We switched to more small groups meetings, actively learned the skills of giving and receiving feedback and set individual goals for each smaller subgroup.&lt;/p&gt;

&lt;p&gt;A couple of days ago I skipped the meeting where the team discussed the next tech stack to strive towards. Of course I couldn't leave them empty handed and left them with a draft. &lt;/p&gt;

&lt;p&gt;They delivered above and beyond what I expected.&lt;br&gt;
I definitely couldn't have done it better or faster myself.&lt;/p&gt;

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

&lt;p&gt;I still think that one engineering manager shouldn't manage more than 5-7 people directly. The quality drops and the complexity increases exponentially. And one team should have one clear direction. No more, no less.&lt;/p&gt;

&lt;p&gt;But we, leaders, are usually rising when things aren't perfect. It takes time and tremendous amount of selfless courage to take the responsibility and let go of control.&lt;/p&gt;

&lt;p&gt;The work doesn't stop - it transforms. And honestly? The parallels to engineering are stronger than I thought:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meetings and slides are your new coding sessions.&lt;/strong&gt; Just as you used to craft elegant solutions in code, you're now crafting clarity and alignment through communication. The syntax is different, but the goal is the same: turn ambiguity into actionable structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sudden stakeholder dissatisfaction is your new bug to fix.&lt;/strong&gt; Root cause analysis still applies. You still need to dig deep, understand the system, and address the underlying issue - not just the symptoms. The debugging tools are conversations instead of logs, but the analytical mindset remains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Helping people grow is your new feature to ship.&lt;/strong&gt; This one has the longest feedback loop you've ever worked with. You won't see the results in a sprint or even a quarter. But when someone on your team tackles a problem you would have struggled with years ago, or leads an initiative you couldn't have imagined - that's your deployment going live.&lt;/p&gt;

&lt;p&gt;You've done it before. You learned to code, to debug, to ship. Now you just need to do it in real time, using natural language, in an ever-changing environment with far messier requirements.&lt;/p&gt;

&lt;p&gt;Just an N-dimensional puzzle, no biggie.&lt;br&gt;
And I think you absolutely are up for the challenge.&lt;/p&gt;

</description>
      <category>management</category>
      <category>career</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Has anyone tried Scaleway cloud serverless offerings (db/functions)? What are your thoughts if so?</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Sat, 18 Oct 2025 07:07:32 +0000</pubDate>
      <link>https://forem.com/valeriavg/has-anyone-tried-scaleway-cloud-serverless-offerings-dbfunctions-what-are-your-thoughts-if-so-m2</link>
      <guid>https://forem.com/valeriavg/has-anyone-tried-scaleway-cloud-serverless-offerings-dbfunctions-what-are-your-thoughts-if-so-m2</guid>
      <description></description>
      <category>serverless</category>
      <category>discuss</category>
      <category>cloud</category>
      <category>database</category>
    </item>
    <item>
      <title>Six bets on web development in the era of AI</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Wed, 27 Aug 2025 04:27:19 +0000</pubDate>
      <link>https://forem.com/valeriavg/six-bets-on-web-development-in-the-era-of-ai-2ppa</link>
      <guid>https://forem.com/valeriavg/six-bets-on-web-development-in-the-era-of-ai-2ppa</guid>
      <description>&lt;p&gt;Is it safe to assume that AI is not coming for our jobs after all? What about SEO experts and old-school webmasters? I wouldn’t claim to know exactly what the future holds, but I’d like to share with my thoughts on the matter and hear yours. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. SEO would still matter
&lt;/h2&gt;

&lt;p&gt;Currently applications like Claude or ChatGPT rely on three sources of data: their internal training data, contextual information (system and user prompts, RAGs, “memory” etc) and old-school web search APIs.&lt;/p&gt;

&lt;p&gt;Depending on a particular prompt the system decides if it needs to fetch new information from the web or not. And for e-commerce requests like “I want to book a hotel” or “buy a bag of cat food” AI would need to go and fetch fresh data from actual sellers - they simply won’t have reliable information available elsewhere.&lt;/p&gt;

&lt;p&gt;That’s why I believe that structured and clear content, semantic markup and engagement signals would still matter just as much, if not more than today.&lt;/p&gt;

&lt;p&gt;In fact, I think that AI would have to learn to measure the quality of the content and its reliability. It’s all fun and games until someone is legally liable for producing false information, as they say. Cleaning up data - AI slop in this case - is a necessity for the next generation of AI tools to emerge.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Progressive Embedded media would emerge
&lt;/h2&gt;

&lt;p&gt;I don’t think users would ever stop visiting the websites directly. It might have been the case if we’d only rely on text and basic media, but it’s not - interactive web components are what makes user stick longer on the pages and give those good engagement signals for the search engines as a side effect.&lt;/p&gt;

&lt;p&gt;I believe that we will continue evolving technology to allow machines enjoy clear and fast well-structured content and for humans to enjoy accessible, rich, interactive widgets that can be accessed on the source website or directly in your AI chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. CSS would be used less for Design, more for Design Systems
&lt;/h2&gt;

&lt;p&gt;If we are to explore the idea of chat embeds further, I would bet that AI chat applications would still want to have a modicum of control over how the interface would look like. At the very least it would be great if an embed wouldn’t stick as a sore thumb and instead would fit into UI of the tool seamlessly.&lt;/p&gt;

&lt;p&gt;We have done something similar with dark and light modes, but I think we would move it even further - towards customisable designs. CSS already has variables that we could use to make embedded applications look great in ChatGPT, Claude, Gemini and our own apps/websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Accessibility would matter for AI too
&lt;/h2&gt;

&lt;p&gt;Let’s say I want to schedule an appointment with my hairdresser. I can ask my AI assistant to schedule it for me over voice or in a chat.&lt;/p&gt;

&lt;p&gt;If I use a device without a display, e.g. a home hub, AI assistant would have to present me with information verbally, akin to a screen reader.&lt;/p&gt;

&lt;p&gt;And to make an actual appointment AI would definitely prefer to use text-based information rather than a screenshot of the page as it’s much less energy consuming.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Wider adoption of MCP &amp;amp; LLMs Docs
&lt;/h2&gt;

&lt;p&gt;Model context protocol is already quite widespread and I think it would make its way into pretty much any e-commerce website. &lt;/p&gt;

&lt;p&gt;I’m not sure what we would settle on, but at some point we would most likely adopt something like &lt;a href="https://llmstxt.org/" rel="noopener noreferrer"&gt;/llms.txt&lt;/a&gt; as we need a way to share the information about capabilities like MCP support with the machines. &lt;/p&gt;

&lt;h2&gt;
  
  
  6. Single Sign On &amp;amp; Passwordless authentication adoption
&lt;/h2&gt;

&lt;p&gt;The future where one would trust AI to perform operations on its behalf on a wide variety of platforms demands a secure way to authenticate AI agents on external platforms.&lt;/p&gt;

&lt;p&gt;I think the most likely winner would be a combination of password managers and single sign on (SSO) from them or other trusted providers.&lt;/p&gt;

&lt;p&gt;That also means that MFA codes sent by email and SMS would have to retire and make way for passkeys or at the very least switch to digital MFA codes that one can share with the password manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Call me a hopeless romantic, but I’d love to see AI tools giving rise to genuine, unique, human made high quality content.&lt;/p&gt;

&lt;p&gt;Yes, we took a bit of a detour with image and video generation and Suno is making quite decent music nowadays, but ultimately I would like to hope that there soon come a time when AI would need creators to feed them new content. To be fair, the time is almost there, I just hope that writers, musicians, researchers, poets, artists, photographers, painters and, yes, us, developers would be valued for our skills and contributions.&lt;/p&gt;

&lt;p&gt;What do you think about the future? &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>You don’t need microservices… yet</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Sat, 10 May 2025 07:41:35 +0000</pubDate>
      <link>https://forem.com/valeriavg/you-dont-need-microservices-yet-378d</link>
      <guid>https://forem.com/valeriavg/you-dont-need-microservices-yet-378d</guid>
      <description>&lt;p&gt;Have you ever heard about Conway’s Law? As I’ve learned, this law states that the architecture of a system mirrors how the company communicates between different parts of the organisation. Apparently it was studied through and through and found true!&lt;/p&gt;

&lt;p&gt;The most fascinating part is that it works both ways: you can influence either of the systems and see the change reflected in the other. Clear up air between two teams and watch them uncover and fix bugs between their deployments sort of magic! &lt;/p&gt;

&lt;p&gt;Such a powerful realisation, isn’t it? And so I thought how can I apply it to my passion project - Hounty, a chore management app I’m building in my free time? &lt;/p&gt;

&lt;h2&gt;
  
  
  Kept it simple, silly?
&lt;/h2&gt;

&lt;p&gt;I’ve made significant progress, but it’s been so hard to get through these final 10%! And from the comments to my posts I’ve learned that others tried to build something similar but got stuck at various architectural stages. I myself attempted to rewrite everything from scratch over and over again even before the core functionality was there.&lt;/p&gt;

&lt;p&gt;But in the light of Conway’s law the reason why it happens became clearer - I think it stems from a misconception of how excellence should look like in software development.&lt;/p&gt;

&lt;p&gt;What surprised me the most is that I’m well aware of the pitfalls of premature optimisation and unnecessary complexity. &lt;/p&gt;

&lt;p&gt;I’ve been preaching the “simple is the new smart” for several years now! I’ve kept my team from overly complicated solutions and led gradual massive transition initiatives more than once! And yet I got stuck in a loop of endless perfectionism with a much simpler project - and being a sole contributor leads me to a refreshing understanding that this is a direct result of my mistake. But what did I get wrong?&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t place all your eggs in one basket?
&lt;/h2&gt;

&lt;p&gt;Along with preaching simplicity I’ve been a huge advocate for modular structures: it worked perfectly in so many projects I was part of! Clear scope of every folder allows to share ownership easier, the structure represents the teams that are handling it and I was absolutely certain that this setup is great a starter point of any project!&lt;/p&gt;

&lt;p&gt;And of course I must be proactive and make sure that I don’t have to completely redo the architecture when the system needs to scale up really quickly! Of course I’m aware that you don’t start with Kubernetes right away (as the joke goes you gotta wait till you get 7 concurrent users), but I still fell in the trap of “monolith is bad”.&lt;/p&gt;

&lt;p&gt;Now I didn’t deploy Hounty in microservices, but I tried to keep the code structure decoupled to be able to do it easier when the time comes. Because I’m an expert, okay?! I don’t build no monoliths!&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you want to build a monolith?
&lt;/h2&gt;

&lt;p&gt;Well, as per Conway’s law I absolutely should build a monolith. Just drop files in one folder, deploy it somewhere quick and get it out in the hands of real users to get data.&lt;/p&gt;

&lt;p&gt;Not because I’m cutting corners or accumulating tech debt, but because at this stage of the project that is how technical excellence looks like. &lt;/p&gt;

&lt;p&gt;I was trying to force modularity on a system held by a solo developer and it felt… lonely. Because my changes to the architecture demanded changes to the organisational structure and that’s not possible at the moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech debt?
&lt;/h2&gt;

&lt;p&gt;I think the biggest misconception was my understanding of technical debt: I used to think that it’s misalignment between current system and industry standards or best practices, but now I believe that it’s misalignment between system and supporting organisation. &lt;/p&gt;

&lt;p&gt;Ultimately, we want our software to do what it’s supposed to do at any given time and we want to make sure that developers working with this software can do it with the least amount of friction. &lt;/p&gt;

&lt;p&gt;And there’s no gold standard: there are patterns that one can apply in a specific situation. For example, a Strangler Fig pattern - that allows to wrap a system to decouple it bit by bit when the time comes.&lt;/p&gt;

&lt;p&gt;For Hounty I’ve built a system on Supabase with a Deno BFF layer. Most of the logic is in the database layer right now and it took me a while to accept that: I didn’t see that I’ve already went above and beyond by building a BFF layer that allows me to swap any part of underlying system without rewriting the app.&lt;/p&gt;

&lt;p&gt;The system as it is right now meets my security and scalability standards. It’s not just good enough: it’s perfect for this stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s not done till it’s out
&lt;/h2&gt;

&lt;p&gt;I was planning to release Hounty in beta, but users below 13 can’t participate in TestFlight or install unpublished Play Store apps without giving up all parenting controls, so I have to finish the app and polish user experience to be able to pass app review before I can release.&lt;/p&gt;

&lt;p&gt;And I’ll tell you all about the “90% ready” fallacy in my future posts if you’d like 🤗&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>devjournal</category>
      <category>management</category>
    </item>
    <item>
      <title>In the spirit of international women day: Ladies only because you can do it all doesn’t mean you have to 👑 Delegate 😎</title>
      <dc:creator>Valeria</dc:creator>
      <pubDate>Sat, 08 Mar 2025 07:20:36 +0000</pubDate>
      <link>https://forem.com/valeriavg/in-the-spirit-of-international-women-day-ladies-only-because-you-can-do-it-all-doesnt-mean-you-57bm</link>
      <guid>https://forem.com/valeriavg/in-the-spirit-of-international-women-day-ladies-only-because-you-can-do-it-all-doesnt-mean-you-57bm</guid>
      <description></description>
      <category>womenintech</category>
      <category>career</category>
      <category>leadership</category>
    </item>
  </channel>
</rss>
