Showing related posts beneath a blog post is a great way to give your visitors more to read and encourage them to spend more time on your site. Existing methods of showing related content include matching posts by tags or by manually adding related posts to your frontmatter . Both of these work, and I used to use tag-based related posts myself, but I wanted something a bit less manual. It’s a…
Much like almost every other developer on the planet, I have been trying to work out my relationship with coding agents. I have been using AI-assisted coding since the GitHub Copilot beta came out in 2021 (yes, that long ago) and have seen them evolve from being a fancy autocomplete to sidebar assistants to full-blown applications that don’t even show you the code (unless you want to see it). I’ve…
I have been speaking publicly at developer conferences for over a decade and in that time I’ve seen plenty of other people giving talks. Everyone gives talks differently, and if you are a speaker or thinking about getting into it, I encourage you to work on developing your unique style as well as your content. However, recently I have noticed a few little things that some speakers do and others do…
After the recent supply chain attacks on the npm ecosystem, notaby the Shai-Hulud 2.0 worm , GitHub took a number of actions to shore up the security of publishing packages to hopefully avoid further attacks. One of the outcomes was that long-lived npm tokens were revoked in favour of short-lived tokens or using trusted publishing. I have GitHub Actions set up to publish new versions of npm…
The Date object in JavaScript is frequently one that causes trouble. So much so, it is set to be replaced by Temporal soon. This is the story of an issue that I faced that will be much easier to handle once Temporal is more widespread. The issue In January 2025 I was in Santa Clara, California writing some JavaScript to perform some reporting. I wanted to be able to get a number of events that…
When you’re building a retrieval-augmented generation (RAG) app, the first thing you need to do is prepare your data. You need to: collect your unstructured data split it into chunks turn those chunks into vector embeddings store the embeddings in a vector database There are many ways that you can create vector embeddings in Python. In this post, we’ll take a look at four ways to generate vector…
This is one of those cathartic blog posts. One in which I spent several frustrating hours trying to debug something that really should have just worked. Once I had finally found out what was going on I felt that I had to write it all down just in case someone else is out there dealing with the same issue. So if you have found yourself in a situation where using fetch in Node.js for a…
Scraping web pages is one way to fetch content for your retrieval-augmented generation (RAG) application. But parsing the content from a web page can be a pain. Mozilla’s open-source library Readability.js is a useful tool for extracting just the important parts of a web page. Let’s look at how to use it as part of a data ingestion pipeline for a RAG application. This post was originally written…
Have you ever had one of those times when you think you’re doing everything right, yet still you get an unexpected bug in your application? Particularly when it is state-related and you thought you did everything you could to isolate the state by making copies instead of mutating it in place. Especially when you are, say, building a game that copies a blank initial state when you create a new room…
When you’re building a retrieval-augmented generation (RAG) app, job number one is preparing your data. You’ll need to take your unstructured data and split it up into chunks , turn those chunks into vector embeddings , and finally, store the embeddings in a vector database . There are many ways that you can create vector embeddings in JavaScript. In this post, we’ll investigate four ways to…
Retrieval-augmented generation (RAG) applications begin with data, so getting your data in the right shape to work well with vector databases and large language models (LLMs) is the first challenge you’re likely to face when you get started building. In this post, we’ll discuss the different ways to work with text data in JavaScript, exploring how to split it up into chunks and prepare it for use…
Generative AI enables us to build incredible new types of applications, but large language model (LLM) responses can be slow. If we wait for the full response before updating the user interface, we might be making our users wait more than they need to. Thankfully, most LLM APIs—including OpenAI, Anthropic, and Langflow provide streaming endpoints that you can use to stream responses as they are…
Grouping items in an array is one of those things you’ve probably done a load of times. Each time you would have written a grouping function by hand or perhaps reached for lodash’s groupBy function. The good news is that JavaScript is now getting grouping methods so you won’t have to anymore. Object.groupBy and Map.groupBy are new methods that will make grouping easier and save us time or a…
With the recent release of version 20.6.0 , Node.js now has built-in support for .env files. You can now load environment variables from a .env file into process.env in your Node.js application completely dependency-free. Loading an .env file is now as simple as: node --env-file .env What is .env? .env files are used to configure environment variables that will be present within a running…
Generating pagination links is not as straightforward as it may seem. So, while rebuilding my own site with Astro, I released a <Pagination /> component on npm as @philnash/astro-pagination that anyone can use in their Astro site. Read on to find out more. Pagination Pagination is something that most content sites need. It is often better to list collections with lots of entries, like blog posts,…
Bluesky is the new social network in town and it’s an exciting place to explore right now. I was fortunate enough to get an invite early on and take part in the early community. But Bluesky is not just a Twitter clone, it’s an application on top of The AT Protocol , a (still being built) federated protocol for social networks with some interesting properties. Because there’s a protocol, that also…
ChatGPT has taken the world by storm and this week OpenAI released the ChatGPT API . I’ve spent some time playing with ChatGPT in the browser , but the best way to really get on board with these new capabilities is to try building something with it. With the API available, now is that time. This was inspired by Greg Baugues’s implementation of a chatbot command line interface (CLI) in 16 lines of…
I recently came across this blog post from Ruud van Asseldonk titled “The yaml document from hell” . I’ve always heard that yaml has its pitfalls, but hadn’t looked into the details and thankfully hadn’t been affected, mainly due to my very infrequent and simple use of yaml. If you are in the same boat as me, I recommend reading that article now as I almost can’t believe I’ve avoided any issues…
Two factor authentication (2FA) is a great way to improve the security of user accounts in an application. It helps protect against common issues with passwords, like users picking easily guessable passwords or reusing the same password across multiple sites. There are different ways to implement two factor authentication, including SMS, using an authenticator application and WebAuthn. SMS is the…
Mastodon is different to most online services. It is a federated network, so when you set up an account you need to choose a server to use . Your username then becomes a combination of your handle and that server you signed up to. For example, I am currently @philnash@mastodon.social . But what if you want to personalise that a bit more? What if you wanted to use your own domain for your Mastodon…
Link shortening has been around for a long time and Bitly is arguably the king of the link shorteners. It has support for shortening long URLs as well as custom short links, custom domains, and metrics to track how each link is performing. For those of us with the power of code at our fingertips, Bitly also has an API . With the Bitly API you can build all of the functionality of Bitly into your…
Sometimes the platform we are building on provides more functionality than we can keep in our own heads. However, depending on the problem, we often find ourselves trying to write the code to solve the issue rather than finding and using the existing solution provided by the platform. I almost fell for this recently when trying to parse a query string. I can do it myself A colleagues had a query…
When I am developing web applications in Node.js, I like the server to restart when I make changes, so I use nodemon . When I am developing an application that consumes webhooks or that I want to share publicly, I use ngrok . In fact, I like ngrok so much, I volunteered to help maintain the Node.js wrapper for ngrok . Now, you can run ngrok and nodemon separately and things work fine. But what if…
Time zones are hard. Not only are there a lot of them, but they don’t fit nicely into whole hour blocks, daylight savings time changes individual zones some of the time, and zones move around and change all the time. In short, it is a hassle. Time zones of the world, via Wikimedia Commons , aren't they nice and easy? Events are happening online all the time and since people can join an online…
Got is a Node.js library for making HTTP requests . It has both promise and stream based APIs and in this post I want to explore how to use the stream API to download files. Using Got If you use HTTP libraries for making API requests, then the promise method is likely the best for you. Making a basic HTTP request with Got looks like this: const got = require ( "got" ); got ( url ) . then (…
Over the Easter weekend, a four day weekend characterised by lockdowns all over the world, I decided to use the extra time I had at home to start a new project and learn a new skill. By the end of the weekend I was proud to release my first VSCode extension: ngrok for VSCode . What’s that now? ngrok is a command line tool built by Alan Shreve that you can use to expose your localhost server with a…
I’ve been trying out streaming live code on Twitch which is a lot of fun. I wanted to share on my own site that I was streaming so I have built a page dedicated to it . The page will evolve, but one of the first things I wanted to include on it was an embed of my Twitch stream and chat. Twitch makes it easy to embed your stream but the less obvious part is how to make that embed responsive across…
The list on GitHub of repositories that depend on your repository is scary. There’s something nice about writing and releasing a library, module, Ruby gem, whatever. It is code that you wrote that worked for you. There may be download numbers on the registry, but they are fairly abstract and don’t necessarily relate to use. Seeing that there are real projects using the code that you wrote is kind…
Some things you do as a developer can work for you for years, then turn around and bite you when you were least expecting. These are the things that you wish another developer had told you early in your career so you never had to make the mistakes. This post is about one of those things and if you’re reading this, consider it me telling you. File paths look like strings. You have a number of…
So you’ve decided to speak at a developer conference? You have a story you want to share with your peers—how you built something, how you learned something new, how you became a better developer and how everyone else can too—but you need to find a stage on which to share this story. There are hundreds of developer conferences out there, covering everything you could think of in our industry.…
Recently I’ve been refactoring the tests for a gem I maintain and I needed to test that it sets the right cookies at the right time. But the cookies in use in the gem are signed cookies and that caused a slight hiccup for me. I’d never tested the value in a signed cookie before and it wasn’t immediately obvious what to do. So I thought I would share what I found out in case it helps. Cookies on…
Array sorting is one of those things you don’t spend too long thinking about, until it stops working for you. Recently I was working with array of items in JavaScript that were not sorting at all properly and completely messing up an interface. It took me way too long to work out what went wrong so I wanted to share what happened and why it was so weird. Basic sorting JavaScript has a sort method…
Sometimes I write blog posts to remind myself what I’ve learned and sometimes I write them because someone else shares something and I want to remember that better. This post is one of the latter. Starting a Node.js project Usually when I start a new Node.js project I use npm to generate my initial project. npm init npm then asks me some questions and builds a package.json file for me. Then I…
I’ve never been one for writing a review of my year. This year I’ve found myself not only reading, but comparing myself to others’ reviews. I realised that this is not particularly helpful, so decided I’d give myself something to compare myself to at the end of 2019. Thus, here is my first year in review. Here are some of the things I was proud of this year: Professional July 2018 saw me cross 4…
You’ve implemented a service worker to cache some assets. Everything is working well, your service worker is a success, you’re feeling good. But then… Some time passes and you deploy a video to your site. Everything is still working well in Chrome, in Firefox, in Edge. You check Safari. The video is broken. You don’t know what’s gone wrong. That was me last month. I published an article on…
I recently experimented with audio visualisation in React on the Twilio blog . While I meant to teach myself more about the web audio API I found that I picked up a few techniques for animating in canvas within a React project. If you’re creating a canvas animation in React then perhaps this will help you too. Good references First up, if you’ve used React before you’ll know that you’re supposed…
Crystal is still a young language, there aren’t a lot of libraries available yet. For some this could be offputting, but for others this is a chance to learn about a language and provide useful tools for those also starting to use it. I’ve given a number of talks over time, some of which were about two factor authentication . A while back I took the opportunity to improve my knowledge and…
I’ve seen the following tweet about git making its way around Twitter recently: I ❤️ Git. But honestly, it intimidated me for years. I thought I needed to understand all its powerful features to be productive. I found that's not the case. You can be quite productive in Git with around 6 commands: branch checkout add commit pull push — Cory House 🏠 (@housecor) August 19, 2018 And it’s true, you…
Development machines can build up such a lot of cruft. Old versions, oudated programs and unused caches litter the hard drive. It’s good to take time once in a while to clean all of this up and free up some space. Here are some tips for commands you can run or actions you can take to clean up your machine. If you have a tip that I’m missing here, please share it with me on Twitter . Homebrew If…
I’m a fan of the web share API but I was not happy with my initial implementation of the API . It was all a bit complex for what is a very simple API. I wanted something more declarative and easier to use with a more generic fallback for when the share API was not available. I’ve been playing about with web components on and off over the last year and I wanted to see if I could make a component…
There are a whole bunch of CSS selectors available to web developers, but sometimes there’s still not enough. I found this recently when building the speaking section of my site and wanted to use the non-existent :first-of-class pseudo class to apply some styles. The problem The pseudo class :first-of-type does exist, but it is limited. It is a special case of the :nth-of-type() pseudo class. From…
At the start of the year I looked into how to better compress the output of a Jekyll site. I’ll write up the results to that soon. For now, here’s how to gzip a file using Ruby. Enter zlib Contained within the Ruby standard library is the Zlib module which gives access to the underlying zlib library . It is used to read and write files in gzip format. Here’s a small program to read in a file,…
I am a fan of progressive web apps and the powers that they bestow on web developers to build the next generation of applications. We can write web applications that work offline, download large files in the background , send push notifications , and much more. I was so excited about push notifications on the web that I wrote a whole talk about it in 2015 and was fortunate enough to give it in a…
I had the fortune of attending the wonderful Brighton Ruby conference last week. It was full of excellent advice, wisdom and code. There was one talk, however, that urged me to go home and do something straight away to ensure the security and usability of my projects. Andrew Nesbitt , with the backing of the libraries.io open data , told tales of the hidden costs of open source software in Ruby…
The service worker API is expanding as more ways to use the background dwelling worker emerge. I’ve written before about push notifications and background sync and I recently explored the very new background fetch API . Here’s what I found out about it. Downloads and uploads The background fetch API seeks to solve two problem: When a service worker is downloading large files to cache and the user…
Did you know bundler can download and install gems in parallel? That’s right, using the --jobs option for bundle install means you can set the number of gems that can download and install at the same time. To use four jobs, for example, you can run: bundle install --jobs=4 As a bonus, you don’t even have to remember to use the --jobs option every time. You can set this in your global bundler…
Here’s a quick tip for anyone who uses rbenv and ruby-build to manage installing and switching Ruby versions. When installing a new version of Ruby I cannot think of a situation in which I wouldn’t want Bundler installed too. The good news is that you can get rbenv to install Bundler, or any other gem you like, as soon as you install a new version of Ruby. All you need is the default-gems plugin.…
Recently I implemented the web share API for my site as a means of testing it out. If you are using version 55 or above of Chrome on Android then you can see it in action by clicking “share it” at the bottom of this post. If you don’t have a browser that supports the API, then this is what it looks like when you hit the share link. The Web Share API origin trial has finished and after…
I wrote a blog post last week and bits of it were wrong. This is not a retraction of that blog post, I just wanted to share the feedback that I got, the things I changed and some lessons that I learned. Inconsistency sucks The first feedback I received was from posting the article on /r/javascript . The comment is deleted now so I can’t credit the author, but they pointed out a few things: Code…
I think the ES2015 destructuring syntax is pretty cool. It might not grab the headlines like Promises, Generators or the class syntax, but I find it really useful. It’s also surprisingly detailed when you read into it . The only shame is that most of the examples I’ve found focus on just the syntax and not real life usage. Like this one from the MDN docs : var a , b ; [ a , b ] = [ 10 , 20 ];…