RSSAmplifier

Blog

James Doyle

The personal blog of James Doyle (james2doyle) Web Developer in Canada.

ohdoylerules.comRSS feed ↗181 posts

Latest posts

How I use AI in Sublime Text

My Editor Situation In my previous article about Sublime Text (Why I Still Like Sublime Text In 2025) , I mentioned all the reasons I still like using Sublime Text over any of the other editors I have tried. In quick summary, the overall speed/performance, snippets, LSP support, project workspaces, keybinding features, build system, and plugin ecosystem/interface are still unrivaled (in…

a11y Accessibility Checker (2025 update)

I recently updated my a11y accessibility checker tool with improved accuracy, better logic, and a more polished user experience. This tool helps designers and developers ensure their color combinations meet WCAG accessibility standards. Overview The a11y accessibility checker is a web-based tool that evaluates color contrast ratios to determine if text is readable against background colors…

Alpine.js Playground

I created a live coding playground for Alpine.js with Tailwind CSS support. View the live site Features Live Preview : See your Alpine.js code render instantly as you type Code Sharing : Generate shareable URLs with compressed code Resizable Panes : Adjust the editor/preview split to your preference Tailwind CSS Support : Full Tailwind CSS utility classes available One-Click Actions : Copy…

Super Webhooks Chrome Extension

Super Webhooks for Chrome I was looking for a way to send details of web pages, or page context, to my automation tools like n8n , Zapier , or IFTTT . Doing this manually is a friction-filled process of copying, switching tabs, and pasting. Ideally, I could use this for simple bug tracking. By using the context of the page and browser, I can easily send additional metadata that can be captured and…

A MCP for the Godot documentation

I have been playing with game development lately and have found it to be a really refreshing break from working in the web development space. It is so different from the way that websites are built. That being said, I have some web dev habits I wanted to bring to my game development workflow. I have been using Godot , Defold , Love2D , and even playing with Raylib a bit, to get the hang of things…

Block 3rd party sign in prompts in Google Chrome

If you have ever seen that annoying popup in Chrome? These things suck right? Well you can block them: If you wanted to visit this setting directly, you can go to chrome://settings/content/federatedIdentityApi . You can then set it to "block" these prompts so you never have to see them again! There are some other settings in there for blocking specific sites or allowing them…

Things I like about Dart (Compared to Node.js)

My Recent Use Case I recently had to make a small sever that would be the endpoint for a webhook from Twilio. The server just puts entries into a database or checks to see if there are entries. So two endpoints. Not a very complicated project. Creating simple servers is really where Node.js should shine. But I found myself dreading getting a Node.js project going just for this simple server…

Why I still like Sublime Text in 2025

I still get people asking me why I use Sublime Text in 2025 given there are soooo many other great editors out there. My response: there is? Because I still think Sublime Text holds up as a great editor. Table Of Contents It fast LSP Snippets Project workspaces Build systems Multiple cursors Key/mouse bindings Included niceness Wish List I started with Sublime Text 2 back in 2010/2011…

Light Weight Privacy Policy

Privacy Policy for Light Weight Last Updated: 2024-12-01 1. Introduction Welcome to Light Weight ("App"). This Privacy Policy explains our commitment to protecting your privacy. Our app is designed to function entirely offline and does not collect, store, or transmit any personal data. 2. Data Collection Our app does NOT collect: Personal information Usage statistics Device data Location…

Hammerspoon hyper key

If you aren't using Hammerspoon on OSX, you are missing out! It has some great features that you can use to control your desktop, automate tasks, build small UIs and toolbar apps. It can also trigger key presses and modifiers like shift, alt, etc. Here is the script I use to create "hyper" key shortcuts. If you aren't aware, the hyper key is a modifier key that combines the Shift,…

Use Your Numberpad To Control Google Hangouts/Meet

The number pad Number pads can be pretty handy. Not just for accountants or spreadsheet junkies. Did you know that the keys on a number pad register in their own way? If your number pad is setup right, pressing a 1 on your keyboard number row and pressing 1 on your number pad, will be different keys. I have a bunch of my number keys on my number pad set to control the window positions on my…

Using Browser Devtools To Improve Your Bug Reports

Good bug reports Reporting bugs can be very difficult when you are not a developer. How do you make sure the bug can be recreated? How do you avoid the "it works on my machine" rebuttal? Well, we can greatly improve bug reports on web apps by using some simple tools built into the browsers we use every day. Easy Screenshots Did you know you can take screenshots of DOM nodes right from the browser?…

Versioning Service Workers In Hugo

I have been running this blog on Hugo for quite some time. It is fast, well supported, and full of features. Until recently, one of the features I was not taking advantage of was the pipes feature . For all intents and purposes, pipes are used for processing strings and templates. They are "assets" that are used on your site. They live outside your theme at the top level /assets folder in…

Using Laravel `when` Method To Support Multiple Queries

There is a method on Laravel collections called when that allows you to create a condition on your code without using an if statement. This can be really handy given we often have conditions on queries to deal with missing or present data, the session-specific environment, or even information in the config. Let's look at the common pattern I was using in the past to put conditions on my…

Bitbucket Weekly Reports Using Make (Integromat)

At my job, we like to keep our team updated with all the dev work we do each week. This means we have meetings every Monday to review the work that has happened since the previous week. I often like to review the work done over that time frame by looking at the projects git log for all the pull-requests merged during that previous week. Now, I could open up the develop branch and run a git…

Autocomplete TailwindCSS In Custom Attributes/Strings

If you are using TailwindCSS along with their extension for completing tailwind classes but you are using styled components, custom attributes/props for class names, or packages like twin.macro , then autocomplete for class names might not work properly for you. There is a setting inside the language server for tailwind that let's you provide a custom regex for when/where you want…

Setup A Raspberry Pi with PHP And Lighttpd

I recently got a Raspberry Pi model 4+. I'm using it to run a minidlna server that loads music and movies from an old external hard drive that I have. On top of that, I wanted to run a local web server so that I can write scripts and pages that I can access locally on my network without having to have my laptop open and running. I wanted to setup lighttpd as it is much more efficient than the…

Vue stateful form component

Recently, I needed to create a app that could recreate a form from static JSON and then fill it with values from another source. This was pretty difficult as storing a form in JSON is very hard. You can't add handlers or events given you only can store string, numbers, booleans, and arrays. No functions. I ended up coming up with a component that uses a render function in order to recreate…

Lodash i18n (translation) function

One of the great things about lodash is that it gives you all the building blocks to create some really powerful functions. I was working on a site that needed to use dynamic translations. The way this is done today is usually through a function that is loaded in your components and called with a key that then gets mapped to whatever language you are using. You can pass in variables to the…

Lodash memoize with a timeout

If you are familiar with lodash you may also be familiar with one of the very handy functions called memoize . The definition of memoize on the lodash site is quite verbose. So I will use the definition on wikipedia : In computing, "memoization" or "memoisation" is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and…

Fastmod Codemod For Refactoring

If you have ever encounter a big refactor, you were probably dreading the steps it would take to get all the changes done. You have to find patterns, replace them, remove old code, rename variables, so much work! Well, like most things in the development world, there are tools to help you do this. Yes, you can use find-and-replace, but that approach is very naïve (as in simple) and doesn't…

Vue Omnibar Component

I'm working on a project right now that requires us to have a search modal. The feature is actually inspired by the "Quick Search" experience in Notion . I looked around for a component that was already created that would do this for me. I couldn't find one, so I wrote my own! This component allows you to create modal popups that emulate omnibar, command palette, open anywhere, or other…

Vue Toggle Component

Have you ever created a switch component that just shows and hides an element? How about an accordion? Or maybe a slider? If you distill down these components into their core offering, it is really just a simple state toggle that is either a boolean or a index/key value that is being used. I created this component because it is something I use all the time. I wanted to share it with other…

Tailwind Screens In JS

If you haven't heard of Tailwindcss before, what is going on? It is the hot new CSS framework for building custom designs. From the site: Tailwind CSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you need to build bespoke designs without any annoying opinionated styles you have to fight to override. One of the things Tailwindcss gives you is a…

Vuex Crosstab Plugin

Did you know that you can use localstorage as an event bus between same-origin tabs? Yep! Local storage is shared across same-origin domains. Which means you can share information between tabs on the same domain. Other cool thing is that the storage event that is fired on the window when localstorage changes, it only fired on non-focused tabs . This means you can write an event bus to sync the…

Vuex Stateful URL Plugin

Have you ever used permalinks on a site? These links store the state of the page in the URL. They can be super useful for simple single-page-apps (SPAs) for bringing users back to where they were when they left the page or just adding the ability to share that page state with someone else without requiring logins or anything like that. I'm a Vue.js user who likes VueX. So I wanted to create a…

Using slots in Vue js

If you are working with server-rendered apps (your view is compiled on the server down to HTML), and you are a Vue.js user, then you should definitely learn to use a Vue feature called slots ! Not only will it allow you to make more reusable and flexible components, but you will also improve the rendering performance of your apps as well. Basic Example Here is the example we will be refactoring…

Create JSON Sections In Shopify

If you're like me, you're probably constantly running into issues with the flexibility of Shopify themes. There are a lot of issues that come up when trying to squeeze in features and functionality that are "shop-adjacent". Shopify does a good job at running a store but it can be difficult to reach beyond that and make some more interactive experiences. Recently, I wanted to share the…

Detect Theme Editor In Shopify Liquid Templates

So you may already know that you cannot detect if an liquid page is running in the theme editor. You can however, detect this in Javascript . But what if you want conditional content? What if you want to use this "switch" in a liquid template? There are a couple good reasons to do this. The first one being that sometimes you need to show the content the website admin is editing in a different way.…

Using Zapier Webhooks for HTML forms

If you don't know about Zapier , it's a service that allows you to "automate everything". I've been using it for over 4 years to automate tons of different things like posting daily Trello tasks to Slack, activity in Intercom to Emails, and even a custom scheduled job that gives me task information for the current day. One of the best built-in zaps (that's what they call the…

Use Laravel Valet for WordPress Multisites

Working with WordPress multisites can sometimes be a pain. Especially if you are not using the amazing Laravel Valet tool to manage your local sites. From the site: Valet is a Laravel (or any site really) development environment for Mac minimalists. No Vagrant, no /etc/hosts file. I would add that everything can be managed from the command line as well. Very handy. I'm going to make…

Build A Multi-lingual Laravel Site With Subdomains

OK, so you want to make Laravel a multi-lingual (or just multi-functional) site based off the subdomain? Cool. Must be an interesting project. In order to test this on local development, we are going to use Valet . Let's say our Laravel project folder is in ~/Sites/multisite . We can use that as our base path moving forward. With Valet, we can set up subdomains with valet link .…

Simple Slack Slash Supplier

This is a reprint of the README from my project simple-slack-slash-supplier . This examples project showcases a simple way to create new slash commands without having to work too hard. This example assumes you have access to AWS Lambda as well as have created a Slash command in Slack . Handling application/x-www-form-urlencoded Slack sends their POST requests using Content-Type:…

SQL As An API

There has been a lot of fanfare around the idea of GraphQL lately. For good reason in my opinion. GraphQL allows you to essentially define your API with your query. For example, if you want to only include a single field then you can do that. If you want to nest related items, or not, you can do that as well. If you take a quick look at the GraphQL website (as it is today) you can see how they lay…

Laravel Scout Sonic Driver

If you haven't heard about the cool new search indexer Sonic you must be living under a rock! If you want to read about Sonic directly from the author, check out his blog post on why and how they went on building the tool. According to the Sonic page, it is: Fast, lightweight & schema-less search backend. An alternative to Elasticsearch that runs on a few MBs of RAM. There are some main…

Function Currying To Make Reusable Code

Function currying. If you haven't heard of it before, let me introduce you to this magical pattern that can help reduce duplicate code and improve readability. Currying is just a fancy way to describe a function that returns a function . Pretty simple right? I mean this literally. There are no gotchas here. A function that returns a function is a curried function. Enough words though. I will…

When And Where To Compromise Your App Design

You won't believe number 3! When initially developing an application or a new feature we are constantly trying to balance best practices in system/application design with delivering a finished product. Usually, things like scaling or flexibility become a secondary thought or something that would be "nice to have, if we had the time" . Given those restrictions or that type of scenario, we…

Using Sqlite As A Cache In Laravel

I was playing with a new project using Laravel 5.7 and I wanted to use sqlite for the cache feature that comes with the framework. If you didn't know, Laravel allows you to choose a cache "driver" and Laravel will handle writes, reads, and even locks, using that cache. By default, Laravel includes drivers for "database", "redis", "memcached", "file", and "array". In typical Laravel fashion,…

Angular (v1.x) Through iFrame

Note : This is an older project/repo that uses the previous version of Angular (v1.x) so keep that in mind. I was working on a project that required users to generate content that had dynamic templates. The goal was to make the entire thing was just a javascript client application and not have to worry about adding a server for handling the updates. Even better, if we could avoid AJAX…

Nuxt Firebase Starter

Over the past few weeks, I have been working on a boilerplate/starting template for using the Nuxt.js framework with Firebase . I plan to use this boilerplate for easily creating apps that require authentication, real-time feedback from the database (chats, threads, account balances, etc.), and proper modern support for the new PWA (progressive web app) conventions (service worker, offline,…

Using DigitalOcean Spaces

If you are a fan of DigitalOcean , or you keep an eye on DevOps news, then you probably heard about the new DigitalOcean Spaces offering. Spaces is essentially an AWS S3-compatible service but with that special DigitalOcean touch. Now Spaces is not a 1:1 replacement for S3. There are quite a few features that have not yet been implemented. They also don't have any GUI interfaces for things…

3 Ways A Website Project Falls Apart

Photo by veeterzy on Unsplash Over the last seven years, I have been involved in hundreds of website projects. I've worked with a ton of different clients on various types and sizes. From design/branding projects all the way to sophisticated web applications. From a couple of thousand dollars to hundreds of thousands of dollars. While working on these projects, I noticed that whenever a…

Handle spaces and no-spaces in MySQL where-like clauses

Have you ever been writing a search for MySQL and had an issue where the search wouldn't handle spaces properly? I was writing a search for a users table and wanted to find a user by their first name or last name or a combination of both. I started with a query like this: SELECT * FROM ` users ` WHERE LOWER (` users `.` first_name `) LIKE LOWER (:searchTerm) OR LOWER (` users `.` last_name `)…

WordPress Browser Body Class

Sometimes, browsers just don't behave. While working on a WordPress site, I had a particular styling issue that was affecting Safari. I was wondering what the best way to target the browser was. If you didn't know, there are some primitive browser detection booleans that are built into WordPress. Using those primitives, I was able to whip up a little snippet that adds classes to the body…

Update Laravel Pagination With New Collection

Have you even done a database search (using the DB facade) and got back an array of results that wasn't wrapped in lovely little Eloquent Models? After some googling, I am sure you probably found out about the hydrate method. Using hydrate , you can turn an array of results from the database into real models from your application. This works phenomenally. But what if you want to return…

Color Helpers In Fish Shell

I am one of those people who likes a lot of colors in my shell. When there is a failure, I like to see red. If there is something stuccessful, I like to see green. Working with the prompt to output the correct colors can be a bit of a pain. I manage to find a nice way to handle both colorizing backgrounds for the text as well as the actual text color. You can see an example below: "> Once you add…

Conditional Vue.js Mixins

When building more traditional Vue.js applications, I tend to use mixins a lot. It helps split up code, speparate concerns, and can allow for some cool tricks. One that i keep using is conditionally requiring a mixin based on the details of the page. Here is an example. The first module is a function that, like require , will load a file into the script it is being called from. The thing is, this…

Install the latest Node.js on Amazon Linux

Installing the latest version of Node.js on the Amazon linux AMI can actually be a little painful. Here is a script for doing just that. "> Hopefully, sometime soon, Amazon will stop using 0.10.* and start using a x.* version by default.

Running Go (golang) in Docker

Lately, I have been trying to learn golang. This means playing with a lot of tools and busting up my local environment. In order to keep things simple, I have been using Docker container to run my applications when I am ready to deploy or build them. "> I use now.sh to deploy the applications. Since now.sh support deploying Docker, using the Dockerfile approach makes it really simple to deploy.

How To Use Template Strings As Modules

I had a project the other day that needed to make some HTML strings based on some other data in my code. This is a standard approach when you need to write to the innerHTML of an element, or if you want to populate a string before writing it to the DOM or some HTML attribute. I was trying to find a nice way to split up my JS - that had a bunch of functions in it - and my template string which had…