Welcome friend

My avatar
Join me on my adventures in software

Flushing the DNS cache on a Mac turns out to be very easy.

dscacheutil -flushcache

After updating a Cloudflare DNS CNAME record to point to a Railway app, I had to flush the DNS cache to be able to verify that the change was successful.

Railway docs on setting up a Cloudflare root domain to point to a Railway app.

Resolving a Prisma Generation Issue with PNPM workspaces

A quick write up on a problem I ran into with Prisma and PNPM workspaces.

I’ve been playing around with Hammerspoon for automating my Mac with Lua.

One of the functions which Hammerspoon (hs) exposes is hs.application.launchOrFocusByBundleID(bundleID), but how do you know what that bundleID is?

mdls -name kMDItemCFBundleIdentifier $PATH_TO_APP

Ta-da!

mdls – lists the metadata attributes for the specified file

Who would have guessed that Slack’s is com.tinyspeck.slackmacgap

Async React client side components

…are actually possible

// testcomp.tsx
export default async function TestComponent() {
  // some client side promise
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return <div>Test</div>;
}

And then import it with lazy

// some other component file
let TestComp = lazy(async () => {
  const comp = await import("./testcomp");
  // await the component itself
  const res = await comp.default();
  // must return default key, with the result wrapped in a closure
  return { default: () => res };
});

// render the lazy component, wrapped in Suspense
<Suspense fallback={<div>Loading...</div>}>
  <TestComp />
</Suspense>;

This pattern will run the async component exactly once. Which could be useful for certain use cases 🤔

You can run Postgres in the browser now!

https://github.com/electric-sql/pglite

You can literally open the JS console and run the following

const { PGlite } = await import("https://cdn.jsdelivr.net/npm/@electric-sql/pglite/dist/index.js");
const db = new PGlite();
await db.query("select 'hi mum' as message");
// { rows: [{ message: 'hi mum' }]}

🤯

In Ecto you can bulk replace string content in a database field. This is useful if you need to update a column across multiple rows without needing to do any manipulation on the Elixir side.

I came across this when needing to efficiently bulk anonymise chat message content for GDPR, but its a handy little transferable trick to know.

thirty_days_ago = Timex.now() |> Timex.shift(months: -1)

from(
  m in Message,
  where: m.inserted_at < ^thirty_days_ago,
  update: [set: [
    content: fragment("REGEXP_REPLACE(content, '[^ ]', 'a', 'g')")
  ]]
)
|> Repo.update_all([])

Moving compute to the database can be a great performance win, so tricks like this one are great to have in your back pocket.

🤖

Dependabot for private packages

Dependabot is a great tool for keeping your dependencies up to date. But what if you have private packages? This piece dives into setting up Dependabot for private Github packages.

TIL how to move to a specific spot in vim

:call cursor(x, y)

This is particularly helpful when exploring compiled bundles of Javascript, you can hope right to the column / row the code which threw the error is located.

🕹️

Opening the current PR in Arc

Lets step through a workaround to open the current GitHub pull request in the Arc browser using a custom Fish shell function. We even touch a little bit of AppleScript.

The image-set property in CSS lets you control displaying a different image dependent on the resolution of the <img> tag.

Cool additional things it can handle are gradients as well as handling is a specific image format is supported by the browser.

Am I the only one who missed that scale got upgraded to its own property in CSS?!

MDN doc on scale

No more delving into transform for that one!

Oh snap, i just found rotate as well

Here’s the MDN page for that one

Whilst doing some reading on fonts I came across this gem! A font which automatically censors bad language!

Scunthorpe Sans

Its crazy what you can do with variable fonts 🤩

The below React Router actually doesn’t wait for the top loader to resolve before starting the second loader 🤯

{
    path: '/contacts'
    element: <ContactLayout />,
    loader: async (params) => {
        console.log('loader 1');
        return new Promise((resolve) => setTimeout(() => resolve(true), 3000));
    },
    children: [
        path: '/contacts/:userId/topics',
        loader: (params) => {
            console.log('loader 2');
            return "foo";
        },
        element: <Topics />,
    ]
}

So you don’t get nested loading spinners sadly, but you do get parallel-ish loading

Framer exit animations gotcha

I was having issues with the exit animation prop just not running.

The fix was to wrap the element I was removing in an <AnimatePresence> component.

Although there was actually one higher in the tree, adding this seems to fix the exit animation nicely.

🐪

Implementing a binary heap in Ocaml

Lets learn about and implement a new datastructure in the (mostly) purely functional beast of a language, OCaml 🐪

In Tailwind you can do the whole text overflow elipsi… thing with a single class name: truncate 💁

Tailwind docs on Truncate

🗳️

SvelteKit dynamic page components

Lets look at how to dynamically load and display Svelte components for pages in SvelteKit

👋

Thoughts On Moving Away From Ash

Ash is a freaking cool technology. But here's why I'm moving away from using it.

🔌

File based routing with Plug

A lot of frontend frameworks take the design decision for the project file structure to dictate the structure of the API. Let's mirror that with Elixir's Plug library

🪲

Debugging Tailwind's Language Server Protocol

I use Neovim as my code editing driver. At work, our tech stack revolves around the Phoenix framework on top of Elixir Recently we've made the move to incorporate TailwindCSS into the mix - hardly a controversial decision since TW is basically bundled into Phoenix at this point!

🤖

Metaprogramming in Elixir with macros

Macros are one of the most powerful concepts in Elixir. Its what differentiates the language from the underlying Erlang BEAM your code is compiled to run upon.

🕊️

Comparing a file with master branch

I find myself very regularly needing to understand what has changed in a specific file compared to (most commonly `master`) another Git branch. There's no quickfire `git` command which will just take the file and branch you want and hand you back the file unfortunately, so we are left to come up with other means.

🛫

Moving to Zola

First article of the new year, and I tell myself that this time, this time I'll actually stick to writing! As every developer knows, you can't just go and start writing articles, you need to build the platform which they will be hosted on first!

thumbnail gif

Sequential Asynchronous Operations in Typescript

A dive into how to handle asynchronous operations one after the other after the other in Typescript

🌯

Exploring Haskell’s `newtype` as a type wrapper

Sometimes when programming in various languages, it can be incredibly useful to be able to adapt the core primitive or third party types in your platform. A particular library’s API not quite to your liking? Need an additional sorting function on that damned list type? Sounds like a nice, ergonomic way of wrapping that external type to provide more functionality is in order.

thumbnail gif

Tmux Session Communication

Lets play around with communicating between multiple Tmux sessions!

thumbnail gif

Typed CSS Variables In React

A look at how to make injected CSS variables in the style attribute typesafe in Reacts JSX

🗳️

Type safe local storage

In my day job we were continually hitting an error with users whenever we rolled out changes to a particular form based feature.

🪢

Checkout that PR

The `gh` CLI is awesome. Everyone and their nan knows this. For me one of the best parts about it, is its potential for compose-ability with other CLI tools.

thumbnail gif

Jotai Async

"A look into the Jotai state management library and its usage in handling asynchronous work"

thumbnail gif

Go Static Asset Server

Time to build a static AND dynamic Go server capable of serve static assets as well as dynamic API content

thumbnail gif

RIP

A play around with the Rust built tool RIP

🛑

Find and stop systemd services

A delve into the CLI toolbox to kill a rogue Caddy process

📦

Running my package json test command - the hard way

Sometimes it can be super handy to have a quick and dirty way of accessing your package json scripts. Maybe you just want to know what the right name to call is. For that jq is our friend.

🧙

Fast and dirty favicon

We’ve all been there. We need a favicon for our new shiny website, but its in the wrong bloody format. Legends across the internet have spoken of a tool. A single tool so mighty, it can handle any image, video or audio manipulation any young squire could possibly dream up. That tool... is ffmpeg.

💪

Solid is Solid

🪖 Solid in a good way. No more manually managing dependency arrays to trigger re-renders.

🌉

Farewell for now XMonad

For the last 3 months or so I've been using Xmonad on my Arch box. Its been greater. Its a super powerful window manager, with #limitlesspotential to do anything and everything you could want on a linux desktop ...but you have to have the skills to do it!

🔤

ABC's of Javascript - Apply, Bind & Call

Here's a super quick reference of how each of the confusing initially confusing JS function `apply` , `bind` & `call`

🕺

Damn you pango!

Today the unthinkable happened. On booting into my arch box, I couldn't open Firefox.

🐙

SSH me to Github

🔥 SSH randomly no longer wanting to work when pushing/pulling/fetching etc?

🤙

useLess useCallback

I found this `useCallback` in the one of the components at work. This is actually not needed.

🏈

The Quest For PWD In A Fresh Shell

🔥 I open a new shell. I'm greeted by the home directory. Dang! I wanted to be back in pwd. With the power of zsh on our side we will conquer this worthy challenge!

🎯

Focusing on inputs in react

🎯 Inputs can require focus... Focusing the user onto an input is usually pretty simple

😳

Flattening nested objects

🎯 When your object has nested objected, sometimes you just need to flatten that s**t down!

♦️

Async Array.reduce

🎯 Handling async actions in a reduce function

🐿️

Git Squash in style

🔥 Instructions on how to implement single commit branches

🎙️

Releasing Podcasts

Despite its popularity, the technology which drives the world of podcasting is surprisingly archaic. Although it is true that there are paid services which abstract the nitty gritty of what is actually happening away from *you*, the podcast releaser. I'm sure there are many DIY-minded content producers who would prefer, like me, to go it alone and see the release of their product from start to finish (or just want to do it on the cheap and not pay a third-party service when you don't need to).