<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>blog.kittenin.space</title><link>https://blog.kittenin.space/</link><description>A personal blog about fiber crafts, creativity, technology, cats, and everyday interests.</description><generator>Hugo</generator><language>en-US</language><atom:link href="https://blog.kittenin.space/index.xml" rel="self" type="application/rss+xml"/><item><title>Lessons Learned by Counting Rows From Sheep</title><link>https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/</link><guid isPermaLink="true">https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/</guid><pubDate>Mon, 21 Sep 2026 17:52:36 -0400</pubDate><description>Whenever learning a new programming language, framework, backend, or tech skill, I have always relied on remaking the same applications: This lets me focus on learning, not product design. Initially, this was a simple to-do list application I called Forethought, although I also dabbled in pomodoro timers. But after a time, I wanted to try to make something important to me: a knitting/crochet row counter.</description><content:encoded>&lt;p&gt;Whenever learning a new programming language, framework, backend, or tech skill, I have always relied on remaking the same applications: This lets me focus on learning, not product design. Initially, this was a simple to-do list application I called &amp;ldquo;Forethought,&amp;rdquo; although I also dabbled in &lt;a href="https://cozytime.kittenin.space/"&gt;pomodoro timers&lt;/a&gt;. But after a time, I wanted to try to make something important to me: And as a knitter and crocheter perpetually unhappy with my row counting applications, I realized what I wanted out of a row counter was what I wanted out of, well, fiber arts in the first place &amp;ndash; a app customized to me.&lt;/p&gt;&#10;&lt;h2 id="gauge-swatch-the-first-version"&gt;Gauge Swatch: The First Version&lt;/h2&gt;&#10;&lt;p&gt;When I first built &lt;strong&gt;Count Rows From Sheep&lt;/strong&gt; &amp;ndash; a name that has persevered through every version &amp;ndash; it was with Node.js and Express, using MongoDB as a database to store row counter and project information. Truth be told, I did not get too far with it: I got the Express server set up, the database schema, an intended item structure, and part of a REST API coded.&lt;/p&gt;&#10;&lt;p&gt;But then I saw a new shiny: I had started experimenting with TypeScript and React, and decided to pivot. You might say the gauge swatch worked: It let me realize what I wanted out of the fabric of the application. It was just a little different than what I started with.&lt;/p&gt;&#10;&lt;h2 id="frogging-realizing-what-i-really-wanted-but-only-after-making-an-entire-app"&gt;Frogging: Realizing What I Really Wanted (But Only After Making an Entire App)&lt;/h2&gt;&#10;&lt;p&gt;I started from scratch with version 2. Like the unfinished first iteration, this version of &lt;strong&gt;Count Rows From Sheep&lt;/strong&gt; used something JavaScript-esque, with TypeScript, and created an Express RESTful API. I switched the database to Postgres with Prisma, allowing me to logically organize my database tables with schemas and handle project and row counter data without spending too much time on database management.&lt;/p&gt;&#10;&lt;p&gt;I also finally got to the front end, and I admit: I spent most of my time here. There&amp;rsquo;s something to be said about having written the API partially before. TypeScript and Express weren&amp;rsquo;t new to me, and Postgres/Prisma removed some of the weight of database schemas. This let me focus learning more React, building &lt;strong&gt;Count Rows From Sheep&lt;/strong&gt; as a single-page application.&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="theme-8.png" alt="image"&gt;&lt;/p&gt;&#10;&lt;p&gt;This also let me realize the things I really wanted from both the UI and the application as a whole: Clean, easy-to-use counters that can be visually linked and configured to track repeats, and an affective pattern viewer that let me highlight charts, write annotations, and add text. I also wanted to be able to change themes and settings based on my mood &amp;ndash; I&amp;rsquo;m a native of the 90s and 00s Internet; I love some color.&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="theme-2.png" alt="image"&gt;&lt;/p&gt;&#10;&lt;p&gt;Finally, with everything working how I (think) I wanted, I added authentication: This was a progressive web app, after all! If someone other than me wanted to use it, they would need their own account. This was the first time I had ever implemented auth to an app, and I leveraged &lt;code&gt;bcrypt&lt;/code&gt; and JSON Web Tokens. I also set up invite codes, since I didn&amp;rsquo;t exactly want to release the app to other users yet.&lt;/p&gt;&#10;&lt;p&gt;And that&amp;rsquo;s a good thing: Because when I started using it, I realized I kind of hated it.&lt;/p&gt;&#10;&lt;p&gt;When I decided to build a progressive web app, it was primarily because I was impressed by the PWA of others: &lt;a href="https://www.dabblewriter.com/"&gt;Dabble Writer&lt;/a&gt;, in particular, is an application I thought was &lt;em&gt;really cool&lt;/em&gt;. I wanted to do that! And so I did: But then while using it, I realized that a.) needing the Internet to use my row counter kind of sucked, and b.) I didn&amp;rsquo;t actually care about using the app on multiple devices. I also didn&amp;rsquo;t like the $40+/month bill I was paying Digital Ocean just to use it myself.&lt;/p&gt;&#10;&lt;h2 id="the-fo-count-rows-from-sheep"&gt;The FO: Count Rows From Sheep&lt;/h2&gt;&#10;&lt;p&gt;&lt;img src="crfs-light-horizontal.jpg" alt="image"&gt;&lt;/p&gt;&#10;&lt;p&gt;After a few months of using my PWA web app exclusively, I decided to start fresh again. I wanted to rip out the database in favor of storing project data as JSON files, have it work local-first (and local-only), and provide users the option to use it on their platform of choice (so long as it was a platform I already used and could test it on). This led me to Tauri, which meant I was rewriting the backend again: This time in Rust! I had never actually used Rust before, but the transition to JSON-based project files made this a lot less intimidating than it would have been: It was all CRUD functions! No databases to integrate with! And best of all: It was quick as hell to use. (Well, except for the brief foray into using Android SAF so the user could &lt;em&gt;see&lt;/em&gt; their project files in the tablet filesystem, but apparently that was a bad idea.)&lt;/p&gt;&#10;&lt;p&gt;With the backend simplified, this let me dive head-first into the frontend again: I kept up with using React, although since I knew I wanted more and more (and more and more) themes, I decided to try out Tailwind CSS. And while I won&amp;rsquo;t say Tailwind is the &lt;em&gt;only&lt;/em&gt; reason I was able to implement custom, user-supplied themes, it didn&amp;rsquo;t hurt, either.&lt;/p&gt;&#10;&lt;img class="content-image content-image--left" style="--content-image-width:40%;"&#10; src="https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/crfs-bottom-counter_hu_67f5ee6064c31cec.webp" srcset="https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/crfs-bottom-counter_hu_5420cc5a4361973e.webp 480w, https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/crfs-bottom-counter_hu_67f5ee6064c31cec.webp 720w, https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/crfs-bottom-counter_hu_7c25fe54f15ede7.webp 960w, https://blog.kittenin.space/posts/lessons-learned-by-counting-rows-from-sheep/crfs-bottom-counter.jpg 1320w" sizes="(max-width: 650px) 90vw, 45vw"&#10; width="720"&#10; height="1112"&#10; alt="CRFS bottom counters"&#10; loading="lazy"&#10; decoding="async"&gt;&#10;&lt;p&gt;Since this was the second time leveraging React for the frontend, I was also able to go in with a better idea of what I wanted and how to get there. For example, one simple quality-of-life feature I was adamant about was the ability to move my row counters to the bottom of the screen, where I can see them best on my tab&lt;/p&gt;&#10;&lt;p&gt;I also didn&amp;rsquo;t want to lose portability entirely: But instead of native syncing between devices, which would involve a server and cost money, I developed a simple export/import system. You can save a project &amp;ndash; or &lt;em&gt;all&lt;/em&gt; your projects &amp;ndash; exported as a &lt;code&gt;zip&lt;/code&gt;, then import that &lt;code&gt;zip&lt;/code&gt; onto a different decide with &lt;strong&gt;Count Rows From Sheep&lt;/strong&gt; on it; it doesn&amp;rsquo;t even have to be the same type of device! I work from Windows to Android and occasionally Linux as needed. And it means the application can always be free!&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;I have never finished an application before &amp;ndash; at least not one I wanted to share. But &lt;strong&gt;Count Rows From Sheep&lt;/strong&gt; became something more than a learning experience for me: It became a customized application suited to my knitting and crochet needs, like how my knitting and crochet projects are clothes and accessories made just for me and my loved ones. Of course, that doesn&amp;rsquo;t mean I don&amp;rsquo;t want to share, and you can currently download &lt;strong&gt;Count Rows From Sheep&lt;/strong&gt; from the &lt;a href="https://crfs.kittenin.space/"&gt;CRFS website&lt;/a&gt; for Windows and Linux. Android is still in closed testing, but &lt;a href="mailto:countrowsfromsheep@pm.me"&gt;drop me an email&lt;/a&gt; if you want an invite; bonus points if you can take 30 minutes to run through a test survey!&lt;/p&gt;&#10;</content:encoded><category>tech</category><category>coding</category><category>crfs</category></item></channel></rss>