Skip to content


October 22, 2022 | 06:02 PM

I’ve been experimenting this week with moving my powered blog onto a new tech stack. Why? I have no good reason, I just like to learn things and bang my head on my desk for some reason 🥴 In case you haven’t figured it out yet, I am not a professional web developer.

I’m planning on putting together a shortlist of tech I looked into as a separate post, but only once I’ve landed on one that works. I’m currently still struggling to get web component ”slots” to style correctly across the 3 major browsers. You may notice that in my video below.

For now I’m playing in Greenwood, I was hell bent on not using any JS Frameworks because it’s just a very simple blog and shouldn’t require much of anything more than HTML and CSS. I’ll talk more about my Greenwood experience in a follow up.

While bashing my head into the desk I found myself frustrated with the corner I had painted myself into. I wanted a static site, but that meant I had to go through the build/serve/reload cycle. I even tweeted at the project for help (I don’t 🕊).

In the mean time, I tried to get hot reloading working in their static site generator, but a couple of issues popped up.

  1. ⛔️ Their dev server doesn’t kick off a static site rebuild, resulting in none of my web components being rendered. It works fine if you’re not prerendering your pages though. I think that might have something to do with where it’s watching for changes and serving from. I think it just tries to load stuff from src instead of rebuilding into public and reserving.
  2. ⛔️ Their production serve command seems to have intentions of supporting both dynamic routes and static sites but it doesn’t live reload and kick off a rebuild of the public folder either.
  3. ⛔️ reload and live-server both failed me for different reasons, one didn’t like serving index.html from sub-folders. The other I think had an issue with CSS files in my web components changing, but the HTML that linked to them was not regenerating with an updated mapped filename. That is an effect of calling greenwood build which the dumb hot loading server had no idea about.

So I just smashed together some shell scripting with some mostly (🤏🍎) cross platform utilities. Since I’m laid up after having back surgery(!) ♿️ and working almost exclusively on my Macbook Pro M1, I threw caution to the wind and created some tech debt for when I return to my Gentoo install next week. More on that later.


My servehot script


# method to kill and start the server
restart_server() {

  # read server PID from disk
  SERVER_PID=$( cat /tmp/ )

  if [[ -n $SERVER_PID ]]; then
    # when a change occurs kill the old server
    echo "Killing process $SERVER_PID"
    kill -9 $SERVER_PID

  echo "CTRL-C to exit"
  node_modules/.bin/greenwood serve & # run the server in the background

  # write server PID to disk as this function is called from a child shell 
  # and cannot mutate the environment of the callee (fswatch)
  echo $! > /tmp/

  # (MacOS ONLY) refresh the browsers
  sleep 2
  osascript bin/refresh_browsers.scpt

# make the function visible to child processes
export -f restart_server

# ignore orphans
rm /tmp/

# bootstrap

# watch for changes in the src directory and execute restart as a child process
fswatch -r -o src | xargs -n1 -I{} sh -c "restart_server"

All we do here, in plain old sh, is make a restart_server function that can be called like a program.

Its job is to…

  1. Kill any greenwood PID still alive
  2. Call greewood serve again in the background.
  3. Stash the PID of that command on disk* for use the next time.

* This has to be to disk because of the nature of child processes and their lack of access to parent environments.

Any changes to my source trigger a build via fswatch, which is running recursively (-r) on my src directory, grouping all events that may land simultaneously as one (-o) event and piping that event to xargs. xargs receives the one argument, does nothing with it (-I{}) and executes the restart_server function in a new shell sh -c.

MacOS browser refresh

For good convenience I wanted all of my open browsers to refresh when I made changes so I didn’t have to manually cycle through each pressing ⌘-R. I mean, I was already burning enough calories laying around here in bed all week as it was… 🤡

activate application "Firefox"
tell application "System Events" to keystroke "r" using command down

activate application "Google Chrome"
tell application "System Events" to keystroke "r" using command down

activate application "Safari"
tell application "System Events" to keystroke "r" using command down

I had to of course give Script Editor and WezTerm Accessibility Privileges to run the script from my terminal.

System Preferences > Security & Privacy > Accessibility > [+]

I’m peripherally aware of there being really fancy ways to do this, probably streamlined, even just websites that will help you test across browsers, but for local development in this moment, I’m satisfied with my approach. I’ll learn that stuff another day.

Here’s how it looks from my view. servehot