RSS Amplifier

Blog

jameskerr.blog

Recent content on jameskerr.blog

jameskerr.blogRSS feed ↗48 posts

Latest posts

It takes 5 years to be an overnight success

We never see all the years of hard work it took for people to have their viral moment. It always takes time to do significant things. This is a good reminder for me. I heard it from typecraft today as he talked about his dark moments over the past few months. It was a refreshingly vulnerable video. He has achieved many of the same goals I have for myself, like growing a YouTube channel, speaking…

Mental tricks to keep working on my work

I tried to imagine that today was a weekend where I had lots of free time. On weekends, work feels more fun. There’s less pressure. I’m not supposed to be working, so any work I do feels like extra credit. For some reason, obligation strips the fun out of things. As I drove my daughter to school, I pretended that this was a special kind of weekend — one where I had hours of childcare! What fun! It…

I Will Not Become My Heros

A version of how I thought my life would look died today. Now my life will look different. I am afraid. There are thousands of other stories my life might tell, but I don’t know any of them. I haven’t imagined them once. This unknown future is terrifying for my ego and its need for control. I want to be important. I want to win life. I attach my worth to the outcome of riches, status, fame,…

I Lost My Airpods

Quiet the noise. Uncomfortable, yet alluring. You get used to it. We get used to anything. So choose carefully what to get used to. Less. Giving up. Missing out. It’s not amazing. It’s not revolutionary. It’s quiet. It’s simple. It’s better. There is more space to cry. Rest is a shorter distance away. Lingering on a word or a moment gets easier, naturally. I miss the…

It's hard to deny the simple beauty of a function

I love object-oriented programming. I love naming concepts and materializing them with a class. I love dot notation. I love hiding implementation behind a seemingly simple accessor. I’ve always leaned a little more on the side of OOP in the holy war against FP. But the more code I write, the harder it gets to deny the simple beauty of a function. Data in, behavior, data out. Everything you…

DOM IDs are a real pain in my apps

The standard way to dynamically update HTML content in Ruby on Rails relies heavily on DOM IDs. These IDs are used to identify the target HTML element for an update. The ID must be present on the original page, and in the subsequent partial updates. Here&rsquo;s a very simple example of replacing content with a turbo stream. < form id = 'settings_form' ></ form > turbo_stream . replace…

When you put yourself out there, you’ll feel exposed

Yesterday, I got my first conference talk proposal rejection. It was going to be about folder structures, so I’m guessing there wasn’t enough AI to make the final cut. When I got the email, I felt both disappointed and relieved. It would have been a thrill to speak but I don’t have a ton of time and I love focusing on my main project Tend Cash . In that arena, I was also rejected yesterday! Right…

SuperDB Website Build Review

My work designing and developing the superdb.org website is finished. The first commit was on October 4th, 2024 and the final commit was on February 5th, 2025. It took 4 months of work with some holidays mixed in. The landing page was the first thing I designed. I only planned to make a marketing site with a blog for the project, but later decided to include the docs as well. Last year, my company…

useStateObject: A Simple, Convenient API Around useState

I am loving this API for working with React state. It&rsquo;s a very light wrapper around useState. I call it useStateObject . Here&rsquo;s how it looks: const state = useStateObject ({ offset : 0 , src : 1 , size : 200 , }); That&rsquo;s how I set it up with the initial state. I can access any of those state properties with dot syntax. state . src * state . size ; I get to use the following…

The 3 Types of CSS Utility Classes

A 9.0 earthquake shook my front-end world when I discovered &ldquo;layout primitives&rdquo; at every-layout.dev . Then an aftershock rolled through when I learned about fluid sizing and spacing tokens from utopia.fyi . It&rsquo;s completely changed the way I write HTML and CSS. Programming is the most fun when I am composing primitives. If those primitives are at the right level of abstraction,…

Ship That Code • Publish That Post

Two articles I read this week have inspired the heck out of me. The first was by Jared Turner of thoughtbot with the punchy title &ldquo; WIP is waste &rdquo;. Jared described how zero value is delivered to the users of your software until it is shipped. The longer code changes remain on your machine, the more pure cost it is to the organization. Those words have been ringing in my head for days,…

How to Debug NodeJS with Breakpoints in VSCode

I made a quick screen recording using the VSCode debugger to break on a line of code in my NodeJS electron process. It&rsquo;s a pretty nifty trick! *(main process, not main client 👍) Hope this helps someone!

The One Thing Missing in Every Budget App: Spending Commitments

The one thing missing in every budgeting application is the &ldquo;Spending Commitment&rdquo;. Definition: &ldquo;A thing I am already committed to paying for&rdquo; This concept a fundamental part of any budgeting system. Why? Let’s back up. Why does one create a budget in the first place? I have thought hard to distill a clear answer for this. Here it is. A good budget must answer: Is my…

Fix for Kamal Deploy Assets Not Updating

Does this sound like you? You are using Sprockets to pre-compile assets for production. You are using Kamal to deploy. You have asset bridging enabled in your deploy.yml file. If that is you, you will find that your assets are not updated about 50% of the time. Randomly. The fix is to disable asset bridging in deploy.yml. # comment this out 👇 asset_path : /rails/public/assets April 25, 2024…

How to Set Output Values in Github Actions

This is the syntax for setting an output parameter in a Github Actions step. echo '{name}={value}' >> ' $GITHUB_OUTPUT ' Here&rsquo;s an example of using this syntax in a workflow step. - name : Expose the artifact path id : paths run : echo 'artifact='app-setup.exe'' >> '$GITHUB_OUTPUT' Here&rsquo;s an example of using the output of a command as the value. run : echo 'artifact='$(yarn run…

Responsive Sizing for React Arborist Tree Component

Many people ask me about how to dynamically set the width and height of the Tree component based on its parent using react-arborist . < TreeView width = { 300 } height = { 500 } /> // How do I make these responsive? The component only accepts fixed pixels for the height and width because it virtualizes the rows. It uses the tree height, scroll position, and row height to render only the nodes that…

Cache the Result of a JavaScript Getter Method

My first programming language was Ruby. Well, it was actually Microsoft Excel, then VBA, then C# for a university class, then Ruby. Ruby&rsquo;s syntax is designed for developer happiness. What a wonderful goal. In Ruby, you don&rsquo;t need to add parenthesis to method calls if there are no arguments. class FSEntry def stat File . stat(path) end end # And you can call it like this entry = Entry .…

The Friend Is You

Imagine hanging out with someone all day who berates you. They make final judgements about your character. They criticize anything you do imperfectly. They gossip about everyone you meet. They treat everyone like this. They even shame you for having such a shitty friend around all the time. You desperately want them to go away, but they won&rsquo;t stop following you. They never leave. The moment…

Finally Understanding How Array.sort(comparator) Works

After 13 years of JavaScript, I finally have a way to remember how the comparator function in Array.sort() works. I think the trouble is that all the examples use this shorthand syntax. array . sort (( a , b ) => b - a ); // too hard for James This is beyond confusing for me. In the past, I would just try b - a then try a - b and pick which one gave me the result I wanted. But now I have a mental…

Using @monaco-editor/react in Electron without Internet Connection

The Monaco Editor is awesome. It&rsquo;s what powers VSCode. I wanted to use it to power the query editor pane in Zui , the data exploration app I work on. I reached for @monaco-editor/react because it fit well in the app&rsquo;s NextJS, React, and Electron tech stack. Loading the actual monaco-editor code seems to be a bit of a headache, so in an effort to make setup simple, @monaco-editor/react…

Transitions All Settled

I just published a JavaScript library called transitions-all-settled that allows you to wait for CSS transitions to settle before you do something. The package exports a single function that accepts an HTML node and returns a promise. The promise resolves when all CSS transitions on the HTML node and its children have settled. import { transitionsAllSettled } from 'transitions-all-settled' ; await…

There Are Only Two Types of Transactions

There are only two types of transactions. The ones you are present for. The ones you are not. This just dawned on me. It&rsquo;s easy to keep track of the spending you are present for (groceries, shopping, fun). It&rsquo;s hard to keep track of the ones that happen in the background (rent, insurance, subscriptions). Even harder to try and manage both in your head! Ideally, you have a tool that…

Against Single Element React Components

It's not uncommon to see this type of single element React component. function Title ({ children , ... rest }) { return < h1 { ...rest }>{ children }</ h1 >; } If you use a library like styled-components , you&rsquo;re very much encouraged to write in this way. const Nav = styled . nav `` ; const List = styled . ul `` ; const Item = styled . li `` ; const Link = styled . a `` ; function MyApp () {…

How to Optimize Your Hugo Blogging Workflow on Mac

I love this quote by John Cutler from his post on disincentives . &ldquo;Good things can happen when you make it easier to do good things.&rdquo; &ndash;John Cutler He advises to focus less on incentivizing desired behavior, and more on removing disincentives from desired behavior. It&rsquo;s brilliant. My desired behavior is to write more posts on my Hugo blog. I like Hugo because it&rsquo;s…

A Better Goal Than Sinless Perfection

Any two people in a close relationship are bound to eventually hurt each other. To most of us, it is no surprise when this happens. It’s simply accepted as the cost of growing close. Even though it feels terrible to be hurt, it would be a pointless endeavor to define success in the relationship as perfectly avoiding ever hurting the other’s feelings. Instead, I would say success is using the…

I Have Enough

I have enough food in my kitchen. I have enough water to drink. I have enough clothes to wear. I have enough things in my house. I have enough skill to work. I have enough ideas to think. I have enough people that love me. I have enough people to love. I have enough people to talk to. I have enough people to laugh with. I have enough time to relax. I have enough life to experience. I have enough.…

Company Culture & Church Community

This is a great podcast episode about company culture. The gist is, it doesn&rsquo;t matter what people say or write about what the culture is. It&rsquo;s what people are actually doing that matters. In fact, it may be even worse if what is said about the culture doesn&rsquo;t match what people are actually doing. There was one sound-bite that stood out to me from DHH at minute 7:15. The more…

Let It Flow

I was just in the gym and as I lifted a weight I thought of the energy flowing out of me to lift it. I thought, it&rsquo;s good for me to get this energy out. It feels good and my body is healthier when I send the energy out into the weight. Then I exhaled. That air was also flowing out of me. It was good for it to go out of me. If I held it in, I would be poisoned. It needed to leave for me to…

How to Pipe a NodeJS Readable Stream into a Child Process

I love pipes. Anytime I can pipe something somewhere, it seems that order has claimed a victory over chaos. In fact, there is pipe-related photo of me at the end of this article for your viewing pleasure. The other day I was working in NodeJS and wanted to pipe a readable stream to a spawned child process. I wanted something that could do this. const process = createProcess ( args ); const zq =…

Waiting for a Comet

Comets are constantly falling. We don&rsquo;t know when. But if we&rsquo;re open, our eyes are open, The comment will appear. It is not me. And it will change everything. If we&rsquo;d only wait for it to appear. This poem was written on a backpacking trip through the Wind River Range in Wyoming. I slept under the stars. A meteor broke into pieces in the middle of the night and it seemed I was the…

A Battle of Wit

Swords drawn, Draw blood, Blood in the water Recover, Respond, Respect Cross the line, Cut too deep, Feel the heat Reach out a hand, Pull up to stand Love wrapped up in a sheath This was written on a backpacking trip where eight men hiked for four days in the wilderness. Whenever a group of friends are together, you&rsquo;re bound to find this battlefield.

Partially Controlled Components: A Declarative Design Pattern in React

A common distinction in React is Controlled vs Uncontrolled components. But the real world is not so black and white&hellip; To summarize: Uncontrolled components manage changes within themselves, internally . Controlled components have their changes managed for them, from the outside, externally . I recently authored a tree view React component called react-arborist . After working on a complex…

Others May Know More

A child knows nothing about itself. Its body is a mystery, its ideas, its dreams, its feelings. The child relies on caregivers to teach her everything. The caregivers know more about who she is than she does. Does this ever stop? Do any of us ever fully know who we are? No matter what age I am, will there be others who know more about me than I do? Maybe not me as James, but me as human being. Me…

It’s Good to Wonder About Mysteries

I was talking with a group of friends trying to come up with possible answers to unanswerable questions like: What happens when we die? How does the way we live affect things after our death? We can never know the answers to these questions with certainty. They are fundamentally unknowable. So what is the point of spending so much energy on something you’ll never be able to fully answer? A friend…

React Hook for Avoiding Flash of Empty UI While Data Transitions

I&rsquo;m working on a React app that has frequent data transitions. Each time a user submits a query, the state is reset as we wait for a response from the server. The new data can arrive quickly or slowly. If it arrives quickly, a flash of empty UI will render as the data is transitioning from the previous results to the current results. Before Notice the flash of emptiness in the histogram.…

Confronting a Man at the Playground

While at a playground this weekend a man talked to my 3-year-old son in a way that upset me and I had to do something about it. I thought carefully about what was true for me, then walked over and told him. Earlier that evening I observed this man enthusiastically playing with an 18-month-old boy we&rsquo;ll call JJ. He wasn&rsquo;t the dad, maybe a friend or an uncle. He took little JJ down the…

Persisting the Human Experience

Experiences compress into memories. Memories compress into feelings. Feelings compress into instincts. Instincts compress into the unconscious. The unconscious compresses into the collective human unconscious. There&rsquo;s an analogy in software. When you make a song in music software, you start with big uncompressed files. All the sound layers are stored separately. When the song is finished, it…

Joshua Tree Trip

We took a trip down to Joshua Tree this weekend for a cousin&rsquo;s wedding. For the first time, I could appreciate the gifts of a desert climate. There is much less visual input stimulating the brain. The plants don&rsquo;t grow dense or tall so you can see everything around you. It&rsquo;s calming not to wonder what&rsquo;s behind the trees. And the heat makes you want to just sleep or sit in…

Jet Fuel

We build an engine for it. It propels us to new heights. It explodes. It destroys everything around it. It takes us to heavenly places. It burns. It brings us to life. It transcends the earth. Handle with care. Enjoy its power. Summon it for good. Rest in the potential within. Sacred energy. For purpose. For pleasure. For life.

5 Tricks for Taking Great Photos

I’ve owned a full frame camera for over 5 years. I’ve acquired 3 lenses and snapped many thousands of photos. And yet, last week I discovered these five tricks and was shocked by my ignorance of them. While watching a lesson on incorporating images in website designs, my instructor presented these five qualities of great images. The Five Qualities of Great Images: There should be one obvious…

It’s a Gift for Me to Be Angry

When I’m angry I stop needing everyone to like me. I don’t care if they approve of what I do. My face doesn’t hurt from smiling all the time. When people talk to me, I give myself a moment to evaluate if I agree or not before automatically nodding in agreement. It’s liberating. Some people on the other end of the spectrum are angry all the time. I’m on the overly agreeable side. I wish I could be…

13 Decisions to Make Before Publishing JavaScript to NPM

This post is half rant, half guide. Each of these 13 questions reveals tradeoffs that take time and mental energy to research. In case you don&rsquo;t already have enough to decide today, here&rsquo;s what you must consider when creating and publishing a new JavaScript package. 1. Do you want to write it in TypeScript? If so, you&rsquo;ll need to compile it before publishing. Bookmark the the…

Netflix Does Not Have My Best Interest

I watch Netflix because I’m too tired to do anything else. The kids are finally sleeping and I’m spent. It’s meant to be a quick escape from life before I do what I really need to do which is sleep. But then Netflix launches the attack! They release every episode to a show all at once. They give me 3 seconds to stop the next show from automatically playing. I’m too tired to get up and stop the…

Embedded Divinity

What if we didn&rsquo;t think of God as infinite. What if God poured itself into this particular universe. What if He&rsquo;s completely bound to this one cosmos. It&rsquo;s life is it&rsquo;s life. Our &ldquo;being&rdquo; is only because the Source is fully giving itself to the existence. If we think this way, God is embedded into the material around us. He&rsquo;s not a distant cosmic scientist…

Adults Don&#39;t Share

All the time at the playground I hear, &ldquo;good sharing!&rdquo; and &ldquo;no no Jackson, you need to share&rdquo;. We parents think it is some critical skill that children need to learn. A skill that must be forcefully developed in order to be a contributing member of society. Then one day I thought: We adults never share! How weird would it be to ask for someone&rsquo;s phone to play a game.…

TypeScript Classes Are Giving Me Carpal Tunnel

Whenever a class needs a few arguments in TypeScript, I cringe because I know I&rsquo;m going to need to perform a ceremony to make it happy. Let&rsquo;s start with the simple case. If a Class needs two arguments, I&rsquo;d do this: class Point { x : number ; y : number ; constructor ( x : number , y : number ) { this . x = x ; this . y = y ; } } There is some repetition to get the types and…

Sharing Steps in Github Action Workflows

I&rsquo;ve got an electron app that needs to be built on all three platforms. I&rsquo;ve got three workflow files all with slightly differing steps. Is there way to share whats common? Yes. It&rsquo;s called composite actions . Update (Jan 4, 2024) : There is another way to reuse workflows thats described in the reusing workflows section of the docs. What is a Composite Action? The name is not the…

How to useRef and forwardRef in React

What do I do when my component uses a ref internally but also needs to forward a ref from its parent? The short answer is merge the refs into a single ref function. If what that means is not immediatly obvious, you&rsquo;re like me. Read on. What is a ref? Look at what get&rsquo;s returned from useRef . const ref = useRef (); console . log ( ref ); /* prints */ { current : undefined ; } This ref…