Posts tagged: webdev

All posts with the tag "webdev"

214 posts latest post 2026-07-05
Publishing rhythm
Jun 2026 | 2 posts

Mermaid gives us a way to style nodes through the use of css, but rather than using normal css selectors we need to use style <nodeid>. This also applies to subgraphs, and we can use the name of the subgraph in place of the nodeid.

graph TD;
    a --> A
    A --> B
    B --> C

    style A fill:#f9f,stroke:#333,stroke-width:4px
    style B fill:#f9f,stroke:#333,stroke-width:4px

    subgraph one
        a
    end

    style one fill:#BADA55

produces the following graph

graph TD; a --> A A --> B B --> C style A fill:#f9f,stroke:#333,stroke-width:4px style B fill:#f9f,stroke:#333,stroke-width:4px subgraph one a end

style one fill:#BADA55

Mermaid provides some really great ways to group or fence in parts of your graphs through the use of subgraphs.

Here we can model some sort of data ingest with some raw iot device and our warehouse in different groups.

graph TD;

    subgraph raw_iot
        a
    end

    subgraph warehouse
        A --> B
        B --> C
    end
graph TD;
subgraph raw_iot
    a
end

subgraph warehouse
    A --> B
    B --> C
end

connecting subgroups #

If we want to connect them, we can make a connection between a and A outside of the subgraphs.

graph TD;

    subgraph raw_iot
        a
    end

    a --> A

    subgraph warehouse
        A --> B
        B --> C
    end
graph TD;
subgraph raw_iot
    a
end

a --> A

subgraph warehouse
    A --> B
    B --> C
end

separation of concerns #

It’s also possible to specify subgraphs separate from where you define your nodes. which allows for some different levels of grouping that would not be possible if you were to define all your nodes inside of a subgraph.

graph TD;
    a --> A
    A --> B
    B --> C

    subgraph one
        A
        C
    end
graph TD; a --> A A --> B B --> C
subgraph warehouse
    A
    C
end

Since GitHub started supporting mermaid in their markdown I wanted to take another look at how to implement it on my site, I think it has some very nice opportunities in teaching, documenting, and explaining things.

The docs kinda just jumped right into their mermaid language and really went through that in a lot of depth, and skipped over how to implement it yourself, turns out its pretty simple. You just write mermaid syntax in a div with a class of mermaid on it!

<script src='https://unpkg.com/[email protected]/dist/mermaid.min.js'></script>
<div class='mermaid'>
graph TD;
a --> A
A --> B
B --> C
</div>

You just write mermaid syntax in a div with a class of mermaid on it!

The above gets me this diagram.

graph TD; a --> A A --> B B --> C

This feels so quick and easy to start getting some graphs up and running, but does lead to layout shift and extra bytes down the pipe. The best solution in my opionion would be to forgo the js and ship svg. That said, this is do dang convenient I will be using it for some things.

In looking for a way to automatically generate descriptions for pages I stumbled into a markdown ast in python. It allows me to go over the markdown page and get only paragraph text. This will ignore headings, blockquotes, and code fences.

import commonmark
import frontmatter

post = frontmatter.load("post.md")
parser = commonmark.Parser()
ast = parser.parse(post.content)

paragraphs = ''
for node in ast.walker():
    if node[0].t == "paragraph":
        paragraphs += " "
        paragraphs += node[0].first_child.literal

It’s also super fast, previously I was rendering to html and using beautifulsoup to get only the paragraphs. Using the commonmark ast was about 5x faster on my site.

Duplicate Paragraphs #

When I originally wrote this post, I did not realize at the time that commonmark duplicates nodes. I still do not understand why, but I have had success duplicating them based on the source position of the node with the snippet below.

from itertools import compress

import commonmark
import frontmatter

post = frontmatter.load("post.md")
parser = commonmark.Parser()
ast = parser.parse(post.content)

# find all paragraph nodes
paragraph_nodes = [
    n[0]
    for n in ast.walker()
    if n[0].t == "paragraph" and n[0].first_child.literal is not None
]
# for reasons unknown to me commonmark duplicates nodes, dedupe based on sourcepos
sourcepos = [p.sourcepos for p in paragraph_nodes]
# find first occurence of node based on source position
unique_mask = [sourcepos.index(s) == i for i, s in enumerate(sourcepos)]
# deduplicate paragraph_nodes based on unique source position
unique_paragraph_nodes = list(compress(paragraph_nodes, unique_mask))
paragraphs = " ".join([p.first_child.literal for p in unique_paragraph_nodes])

BeautifulSoup is a DOM like library for python. It’s quite useful to manipulate html. Here is an example to find_all html headings. I stole the regex from stack overflow, but who doesn’t.

Make an example #

sample.html

Lets make a sample.html file with the following contents. It mainly has some headings, <h1> and <h2> tags that I want to be able to find.

<!DOCTYPE html>
<html lang="en">
  <body>
    <h1>hello</h1>
    <p>this is a paragraph</p>
    <h2>second heading</h2>
    <p>this is also a paragraph</p>
    <h2>third heading</h2>
    <p>this is the last paragraph</p>

  </body>
</html>

Get the headings with BeautifulSoup #

Lets import our packages, read in our sample.html using pathlib and find all headings using BeautifulSoup.

from bs4 import BeautifulSoup
from pathlib import Path

soup = BeautifulSoup(Path('sample.html').read_text(), features="lxml")
headings = soup.find_all(re.compile("^h[1-6]$"))

And what we get is a list of bs4.element.Tag’s.

>> print(headings)
[<h1>hello</h1>, <h2>second heading</h2>, <h2>third heading</h2>]

I recently added a heading_link plugin to markata, you might notice the 🔗’s next to each heading on this page, that is powered by this exact technique.

Today I discovered a sweet new cli for compressing images. squoosh cli is a wasm powered cli that supports a bunch of formats that I would want to convert my website images to.

from the future

  > Unfortunately, due to a few people leaving the team, and staffing issues

resulting from the current economic climate (ugh), I’m deprecating the CLI and libsquoosh parts of Squoosh. The web app will continue to be supported and improved. I know that sucks, but there simply isn’t the time & people to work on this. If anyone from the community wants to fork it, you have my blessing.

https://github.com/GoogleChromeLabs/squoosh/pull/1321

Web App #

First the main feature of squoosh is a web app that makes your images smaller right in the browser, using the same wasm. It’s sweet! There is a really cool swiper to compare the output image with the original, and graphical dials to change your settings.

CLI #

What is even cooler is that once you have settings you are happy with and are really cutting down those kb’s on your images, there is a copy cli command button! If you have npx (which you should if you have nodejs and npm) already installed it just works without installing anything more.

The button on squoosh.app

Converting all of my png’s to webp #

I copied the command that it gave me for converting to webp, and set it up to run on all of my pngs.

npx @squoosh/cli --webp \
  '{"quality":75 \
    "target_size":0 \
    "target_PSNR":0 \
    "method":4 \
    "sns_strength":50 \
    "filter_strength":60 \
    "filter_sharpness":0 \
    "filter_type":1 \
    "partitions":0 \
    "segments":4 \
    "pass":1 \
    "show_compressed":0 \
    "preprocessing":0 \
    "autofilter":0 \
    "partition_limit":0 \
    "alpha_compression":1 \
    "alpha_filtering":1 \
    "alpha_quality":100 \
    "lossless":0 \
    "exact":0 \
    "image_hint":0 \
    "emulate_jpeg_size":0 \
    "thread_level":0 \
    "low_memory":0 \
    "near_lossless":100 \
    "use_delta_palette":0 \
    "use_sharp_yuv":0 \
    }' \
    static/*.png -d squoosh-webp

I opened my images repo and converted all pngs to webp using the command above. I got 94% compression on my existing pngs without resizing anything. This is dang impressive, and not too hard to do. I do want to refactor my images site at some point and include this as part of the ci system.

resulting file sizes for converting png to wepb.

I also converted to avif, but it sent all my cpus to 100 for quite awhile, for only another 2MB total. Not sure if its worth it or not.

Building Rich a Dev Server

Draft Post I’ve really been digging [1]@willmcgugan [2]’s rich [3] library for creating TUI like interfaces in python. I’ve only recently started to take full advantage of it. Dev Server # [4] I am working on a project in which I want to have a dev server running continuously in the background. I really like dev servers theat automatically chooose an unused port and list out the running pid so that I can kill it if I need to. - automatic port number - auto-restart - display ( port, pid, uptime ) finding the port # [5] I am very novice at best when it comes to sockets, the following function came from searching StackOverflow for how to tell if a port is in use. I recursively check if a port is being used, if it is I increment by one until I find an unused port to return. def find_port(port=8000): """Find a port not in ues starting at given port""" import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: if s.connect_ex(("localhost", port)) == 0: retur...

Site Down During Build

Recently I noticed a new netlify site of mine was down while I was checking to see if new content was live. Later found out this was consistent after each and every push the site would go gown as soon as I hit push, and would not come back until the build finished. Is this normal? # [1] Do other Netlify sites go down during build??? Short Answer NO. All of my google fu lead me to believe I was alone and none of my other sites do this. Digging into my build # [2] My deploy script ends with the following. After resetting keys and watching it build half a dozen times I determined that everything was working as normal here. - name: Deploy to Netlify uses: nwtgck/[email protected] with: publish-dir: "./markout" production-branch: markout production-deploy: true deploy-message: "Deploy markout from GitHub Actions" env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} Opening the Nelify Console # [3] After poking at t...

Adding Audio to my blog posts

This is episode 1 of the Waylon Walker Audio experience, posts from waylonwalker.com [1]{.hoverlink} in audio form. So I have had this idea for awhile to add audio to my blog posts. The idea partly comes from the aws blog, if you have ever been on their blog you will have noticed that they have a voiced by amazon polly section. What to Expect # [2] Honestly I don’t know this is all new to me and I dont have much to go off of. For now its a test that may or may not work out. I will say that the time that I have available for clean audio is a bit limited so expect these to come out in batches as I get time to go back and record. What Not to Expect # [3] One thing that makes the aws blog really hard to listen to is the robotic voice, I definitely don’t want that. This will be voiced by a real human, Me. At the same time written text doesn’t translate directly to audio well so don’t necessarily expect the audio to be word for word. Code blocks # [4] There are a lot of code block...

gatsby-remark-embedder

Inspired by discourse’s link expansion I am rolling out expansions for one line links on the blog waylonwalker [1]. I was able to find a gatsby plugin gatsby-remark-embedder [2] that expands one line links for social cards for popular platforms like twitter and YouTube through a repose from Kyle Mathews to my tweet. https://twitter.com/kylemathews/status/1329817928666005504 Use Cases # [3] This covers a couple of use cases I have with very little effort. - Twitter - YouTube install # [4] npm i gatsby-remark-embedder gatsby-plugin-twitter This was super quick and simple to setup, the only thing that was extra was to install the gatsby-plugin-twitter plugin as well as the gatsby-remark-embedder. enable # [5] // In your gatsby-config.js module.exports = { // Find the 'plugins' array plugins: [ `gatsby-plugin-twitter`, { resolve: `gatsby-transformer-remark`, options: { plugins: [ { resolve: `gatsby-remark-embedder`, options: { customTransformers: [ // Your custom t...

Expand One Line Links

I wanted a super simple way to cross-link blog posts that require as little effort as possible, yet still looks good in vanilla markdown in GitHub. I have been using a snippet that puts HTML [1] into the markdown. While this works, it’s more manual/difficult for me does not look the best, and does not read well as Goals for new card # [2] The new card should be fully automated to expand with title, description, and cover image. Bonus if I am able to attach a comment behind it. - fully automated - card expansion - Title - description - cover image Old Card # [3] If you can call it a card 🤣. This card was just an image wrapped in an anchor tag and a paragraph tag. I found this was the most consistent way to get an image narrower and centered in both GitHub and dev.to. <p style='text-align: center'> <a href='https://waylonwalker.com/notes/eight-years-cat/'> <img style='width:500px; max-width:80%; margin: auto;' src="https://dropper.wayl.one/file/99f80283-2f27-4664-8c4a-d1...

Why use a cms

When first learning to code its very common to hard code everything right into the code. This happens with most folks in just about any language. Whether its HTML [1] or markdown for front end content, or even hardcoding parameters in our backend languages like python, or node.js. 🤷‍♀️ What’s wrong with hard coding everything? # [2] Hard coding everything right into your code makes it really hard for non-technical collaborators to join. It makes it nearly impossible to hand websites off to clients without needing to come back for routine updates. The cms generally come with a rich content editor that feels more like something most folks are used to. There are buttons for changing the font, font-size, adding images, bold, italics, etc. Sometimes I don’t feel technical # [3] Even when you are developing for a technical audience there is a layer of polish that comes from giving them a nice interface to edit their content in. YouTube doesn’t have you manually inserting records into...

How I Built My GitHub Profile

I ran a discussion on dev that collected quite a list of examples in the comment section. So many great calls to action, animations, memes, and weird tricks. [1] My current profile # [2] [3] social icons # [4] Upload all of your icons to the repo in a directory such as icons or assets, then link them with a height attribute like below. I used html [5] for mine, not sure if you can set the height in markdown. <a href="https://dev.to/waylonwalker"><img height="30" src="https://raw.githubusercontent.com/WaylonWalker/WaylonWalker/main/icon/dev.png"></a>&nbsp;&nbsp; note I did add a bit of &nbsp; (non-breaking-whitespace) between my icons. Without adding css this seemed like the simplest way to do it. Center # [6] Aligning things in the center of the readme is super simple. I used this trick to align my social icons in the middle. <p align='center'> ...html </p> right # [7] For my latest post [8] I floated it to the right with a little bit of align='right' action. <p> <a ...

Refactoring your blog urls

I just did a quick refactoring of my JAMStack blog urls. Some didn’t fit with my style, some had _ that I wanted to switch to -, and others were ridiculously long. I’ve been using forestry as my CMS, I write many of my posts there, and sometimes it picks some crazy file names (based on my titles). It was time to refactor. Large Refactor At The Command Line [1] When refactorings similar to this get really big I often need to do some project wide find an replace, I usually do this right from the command line. 🖊 Rename posts change the filename # [2] My post urls are based on the file name of my markdown file, so I can simply go through my filesystem and rename anything I want. From here its probably best to only commit the addition of the new file name, until the redirects clear, but these are all low traffic posts for me so I just commited both at once. Safely redirect without breaking links _redirects ⤴ /redirects # [3] I am hosted on netlify, which automatically puts very ⚡ ...

Gatsby Scripts with onload

This might be useful https://github.com/nfl/react-helmet/issues/146 https://github.com/gatsbyjs/gatsby/issues/13136

How to get Dev Comments from an article Url

I want to incorporate some of the wonderful comments, \U0001F495, \U0001F984, and \U0001F516’s that I have been getting on dev.to on my website. I have dabbled once or twice with no avail this time I am taking notes on my journey, so follow along and let’s get there together. By the end of this post, I will have a way to get comments from posts on the client-side thanks to the wonderfully open dev.to API. I want to incorporate some of the wonderful comments, 💕, 🦄, and 🔖’s that I have been getting on dev.to on my website. I have dabbled once or twice with no avail this time I am taking notes on my journey, so follow along and let’s get there together. By the end of this post, I will have a way to get comments from posts on the client-side thanks to the wonderfully open dev.to API. The API # [1] dev.to has an open API that allows us to easily get comments as HTML [2]. They have their API hosted at https://docs.forem.com/api/#tag/comments, let’s take a look at it. [3] Here we can...

Explicit vs Implicit Returns in Javascript

Often when reading through javascript examples you will find some arrow functions use parentheses () while others use braces {}. This key difference is that parentheses will implicitly return the last statement while braces require an explicit return statement. It is important to understand the difference between them because it is likely that you will find code examples of both and trying to edit code written differently than you’re used to may have unintended consequences. [1] # [2] Arrow functions are one-liner functions in javascript that have two main syntactical ways to create the code block. with parentheses and braces. Let’s take a look at both ways of creating arrow functions so that when we come accross them in the wild it will all make sense. [3] # [4] Here is an example of an arrow function that will implicitly return the last statement without the return keyword. I believe that these are a bit more restricted in that you cannot set variables inside them. They are ...

Do You Hoist

I am working through Wes Bos’s beginnerjavascript.com/ [1] I just hit module 18 on hoisting. It’s something that I always knew was there, Its not something I typically see used or use myself. Do you Hoist? # [2] Do you have any use cases that you use hoising? Why? It seems like a really cool feature in any language that uses it, but I dont really notice it in use. What is Hoising # [3] There are many articles that cover this in far more depth, but its the idea that variable declarations and functions are defined before they are executed. This means that it doesnt matter if you call a function before or after it is defined. Hoisting # [4] console.log(`Hello ${getUser()}`) function getUser() { return 'Waylon' } Running this code will log out “Waylon” What about variable hoisting # [5] I am most familiar with python which does not variable hoist so this one kinda confused me at first. It only hoists the variable declaration not the value of the variable. It defines whether th...

Custom Scrollbar Design

Getting a custom scrollbar on your site makes it stand out a bit compared to the very plain stock one that are on most sites. This is how I set mine up on my gatsby site. Inspired by Wes Bos’s new uses.tech [1] I wanted a custom scrollbar on my personal site. I had tried to do it in the past, but gave up after it was not working. Looking at the Source # [2] Since uses.tech [1] is open source I jumped on github, searched for scroll and found this layout.js [3]. Copy it to my own component # [4] My first step was to take his css and copy it into a styled component for my entire layout, but it failed. I do not fully understand why. None of the custom style came through at all. If you know please leave me a comment. [5] I suspect for some reason it has to do with attatching to the html [6] element inside of a styled-component. I think wes was able to get around this by using createGlobalStyle. But I was still using much of the default gatsby template, so I did not have a createG...