All blogs / JavaScript / TypeScript
Thomas Hunter II
The personal website of Thomas Hunter II, Software Engineer.
- Posts
- 321 from 1 Jul 2006 to 24 Apr 2026
- Posting
- monthly (11 in the last year)
- Kind
- personal blog
- Feed
- https://thomashunter.name/feed.rss
2026 6
- Server-Side JavaScript Arc Part 2: Oden, a Server-First JavaScript Runtime
- Server-Side JavaScript Arc Part 1: A Retrospective on the Golden Age of Node.js
- Capturing and Culling a Photo Journalist Scene
- Alpaka Elements Tech Case as a Camera Bag
- Fear and Loathing and LLMs
- Repairing a Bose SoundDock iPod Speaker
2025 10
- Timeline
- “Photographing Potrero Hill” is in local coffee shops
- Introducing RFC Hub
- A few months with htmx
- The scales are tipping in the Software Engineering industry
- The scales are tipping in the Software Engineering industry
- Notes on installing Linux on a 2008 Apple Intel iMac
- Post Apocalyptic Computing
- AI will change the world but not in the way you think
- Running Debian Bookworm on a 13" AMD Framework Laptop
2024 14
- Writing Multithreaded Node.js Applications: Is it worth it? at NodeConf EU
- Writing Multithreaded Node.js Applications: Is it worth it? at NodeConf EU
- The Ultimate Fujifilm X-E1 Camera Guide
- Using an iPod Classic Monochrome 4th Gen in 2024
- Discreet, Cheap, Film-Like EDC Street Photography Camera in 2024
- Map Buddy Product Retrospective
- My Photography is Featured at Philz Coffee in Potrero Hill
- Introducing GenAI in O’Reilly Answers
- My Photography is Featured at Ikon Coffee
- Photography is a Loss of Dimension, Senses, and Fidelity
- A Cheap and Pocketable Camera in 2024
- Enabling English on a Japanese Panasonic Lumix GX1
- After your first 10,000 Photographs
- Repairing a Minolta X-370 Light Leak
2023 9
- Getting into Photography on a Budget in 2023
- PS2 RPI4 Part IV: Conclusion
- Photos
- How to file a CCPA complaint against Reddit
- How to Delete your Reddit Account and All Data under GDPR/CCPA
- Welcome to your Chat Bot
- Emulating Windows XP on Linux in 2023
- How NOT to Measure Latency by Gil Tene
- mig: The Universal Database Migration Runner
2022 1
2021 10
- Detecting if a PWA/TWA is Installed
- Node.js Package Management at UtahJS
- Multithreaded JavaScript: Concurrency Beyond the Event Loop
- Multithreaded javascript
- Distributed Systems with Node.js: Humble Books Bundle
- GitHub Actions for Node.js Apps at DevOps.js
- The Death of a Node.js Process
- Logging, Metrics, and Tracing with Node.js at Node Congress
- Node.js Modules, Packages, and SemVer
- Zero-downtime deploys with DigitalOcean, GitHub, and Docker
2020 7
2019 17
- Installing the Node.js Binary Archive on Linux
- The Apex Consumer
- Go v1.13.3 vs Node v12.12.0 Microbenchmark
- Cheap and Portable Writing Device in 2019
- Fixing the Massdrop AKG K7XX Squeak
- On using Service Workers with Static Content
- Nine Volt Daisy Chain
- Why should I use a Reverse Proxy if Node.js is Production-Ready?
- Cobalt Caliber
- JavaScript Symbols: But Why?
- Node.js Task Runners: Are they right for you?
- Introducing Package Diff
- Protecting your JavaScript APIs
- Treating OpenBox like a Tiling WindowManager
- The Increasing Need for Regulation of the Software Industry
- Removing gVim Right and Bottom Borders
- Common API mistakes and how to avoid them
2018 26
- On Migrating from Google Analytics
- Review of the iClever Foldable Bluetooth Keyboard
- Books I'm Reading to Become a Better Writer
- Compromised npm Package: event-stream
- 17 Pounds in 44 Days: My Adventure with Keto
- On Migrating from Wordpress to Static Markdown
- The Monster in the Basement
- Why you should avoid ORMs (with examples in Node.js)
- Essential Firefox Tweaks
- JavaScript Object Type Coercion
- JavaScript Object Property Descriptors, Proxies, and Preventing Extension
- Advice for Technical Public Speaking: Part 3
- Advice for Technical Public Speaking: Part 2
- Advice for Technical Public Speaking: Part 1
- Go v1.10.3 vs Node v10.6.0 Microbenchmark
- Recent Concerns about Node.js Security
- Node.js and Lambda Three Part Series
- Developing Cobalt Dungeon using Phaser and Cordova
- Cobalt Dungeon Dev 01: Creating a New Room
- Cobalt Dungeon for iOS is now available
- Cobalt Dungeon for Android is now available
- Cobalt Dungeon Dev 02: Creating a Bitmap Font for Phaser
- Cobalt Dungeon Dev 03: FL Studio Overview
- The Long Road to Async/Await in JavaScript at SF Node
- I'm working on a mobile game called Cobalt Dungeon
- Support me on Patreon
2017 24
- Twitter Plays Zork: @DemocraticZork
- Go v1.9.1 vs Node v8.9.0 Microbenchmark
- The Long Road to Async/Await in JavaScript at NodeConfAr17
- What have I been up to? Late 2017 Edition
- Is it time to replace REST with RPC?
- Enterprise Conversation Episode 14: OpenTable with Thomas Hunter
- Refactoring a Node.js codebase using Async/Await
- Random Meetup Attendee Bookmarklet
- 2017: A Central Europe Odyssey
- Redis and Node Part 4: Lua Scripting
- Redis and Node Part 3: Atomicity with MULTI
- Redis and Node Part 2: Shared State
- Redis and Node Part 1: The Basics
- Digital Nomad: Inventory Advice
- HTTP API Design Part 4: API Standards
- HTTP API Design Part 3: Bodies
- HTTP API Design Part 2: Responses
- HTTP API Design Part 1: Requests
- Advanced Microservices
- Node.js, Redis, and You! at RedisConf17
- Linux Mint Disable "Recently Used"
- Ubuntu 16.04 LTS Xen stuck on "Loading Initial Ramdisk"
- Service Discovery With Node.js and Consul at SF Node
- Online Colorscheme Configurator for i3, i3status, dmenu
2016 8
- A Holistic Approach to Microservices
- Running a Node.js process on Debian as a Systemd Service
- My Trip to Japan
- Enabling Yubikey U2F support in Linux
- The JavaScript Event Loop Presentation (2016 Edition)
- Installing Linux Mint on an XPS13 (9350)
- The only bad thing about ES7 Async/Await
- Upgrading to the XPS 13 (9350)
2015 10
- NextPlayer: A Node.js module for managing player turns
- HTML5 Mobile Apps, Part 5: Ecosystem Opinions
- HTML5 Mobile Apps, Part 4: Live Operations
- HTML5 Mobile Apps, Part 3: Distribution
- HTML5 Mobile Apps, Part 2: Performance
- HTML5 Mobile Apps, Part 1: Development and Debugging
- Strategic Game of Life: Mobile Edition
- Upgrading Linode II: Xen to KVM
- The long road to Async/Await in JavaScript
- Tips for Building Mobile Games in HTML5
2014 8
- Gridloche: Realtime Multiplayer Go-Like with RPG Elements
- Upgrading Linode
- Robot Onslaught: Multiplayer twin-stick 2D shooter using PubNub
- Arpad: An ELO Ranking System for Node.js
- Consumer Centric API Design
- Linux Kernel 3.15.3 on Linux Mint 17 (or other Debian-Based Distributions)
- Running a Node.js process on Debian as an init.d Service
- What have I been up to? Early 2014 Edition
2013 34
- Principles of good RESTful API Design
- Book Review: Debian 7: System Administration Best Practices
- JavaScript and Canvas version of Conway's Game of Life
- Letting PHP know that its connection behind NGINX is over HTTPS
- See which user accounts hackers try to access on your server the most
- Tips for assembling the O2 (Objective2) Headphone Amplifier Kit
- Only Push/Pull Current GIT Branch
- Remove OpenDNS from Linux Mint
- Enable Emoji fonts on Debian / Ubuntu / Mint Linux
- Border Patrol Saga
- Cheating at Cookie Clicker
- Recursively download website files using WGET
- Instant Backbone.js Application Development
- Book Review: Hands-on Testing with PHPUnit How-to
- Installing Redis on Debian as a Service
- Fixing Homebrew
- SSH into a machine with a dynamic IP
- Setting up a Security Camera for a Linux Webcam
- Track IP Address using DD-WRT + CRON + WGET
- Safely Parse Complex Objects and Arrays in PHP
- WordPress GET Variables with lighttpd
- The JavaScript Event Loop [Presentation]
- How to "Burn" an ISO to a USB drive in OS X
- Generate OAuth Consumer Key and Shared Secrets using PHP
- Set opendiff (FileMerge) as your git diff tool on OS X
- Lansing Startup Weekend February 2013: GeoMonsters Presentation
- Lansing Startup Weekend
- SleekMVC, my PHP Framework, gets Routing support
- Enable PHP Mail on OS X Mountain Lion
- GeoLocation based Communication with Node.js, Redis
- What WordPress 4.x Could Be
- I turned on a light
- Programmer Religious Wars and the Abstraction Gradient
- Node App Inspired by Daniel Suarez' Book Daemon
2012 82
- Wacom Bamboo Splash Review
- Subdomains and Google Apps with Gandi and Linode
- Client-Side Terrain Tile Representation Algorithm
- A Better Debian SSH Login Message
- Transitioning from MediaTemple to Linode
- Install Node.js on Debian 6
- Visual Git History Log in Terminal Window
- Using authbind with Node.js
- Fun Timing Game in Canvas
- Respond to JSON or XML requests from a Node.js API
- Drop Root Privileges in Node.js
- The Upcoming Parallel Digital Universe
- Could JavaScript support Parallelism like in Haskell?
- All Hands Active Board Member
- Configurable Object to XML Converter for Node.js
- MongoDB Node.js driver collection select doesn't require callback
- GitHub Connection Timed Out
- CouchDB and PHP Web Development
- Node.js Convert JSON to XML, Pluralize
- Backup External Music Collection using Rsync
- Fixing ApacheBench on OS X Lion
- Spaghetti Architecture and the Importance of Starting Over
- Review of OpenShift Node.js Support
- Step by Step guide to getting Cobalt Calibur running on OpenShift
- Raspberry Pi with Tons of Hardware
- Cobalt Calibur 3 Open Source
- Copying OpenIndiana Image onto USB in OS X
- My First Arduino Project
- Code School Review
- Series or Parallel Power-Source Switch
- Extended Pigpen Cipher to Include Numbers
- Auto Mount External Drives in Debian
- Per-User Password Hashing Algorithms
- Recursively Delete Files by Extension
- Recursively convert OGGs to MP3s
- Node.js GPS Module
- A Primer on Web Caching
- The Future of Augmented Reality
- PHP + Apache Stack vs Node.js
- OS X Wireless Control from the CLI
- Scan for Computers on Local Network with Nmap
- SSHing into Arch Linux Raspberry Pi
- Updating Pacman on the Raspberry Pi
- Linux CLI apps should have a --json flag
- Gracefully Kill Node.js App from Ctrl+C
- Move special OS X user folders to external drive
- Determine Wireless Encryption Type
- Express.js Pass-Through Directory
- Bad Mount Point Input/Output Error
- MacBook Pro with SSD and Hard Drive
- Git SSL Errors
- NPM SSL Errors
- Settling In to a New Mac
- Female Voice using eSpeak
- Know your Wireless Cards!
- Speech Synthesis and Bluetooth with Node.js
- Suppressing SSH MOTD Messages
- Re-Map Caps Lock key to Esc in OS X
- Why Android should switch to Go
- NERF Gun Laser Instructions
- Node.js Robotics Software Suite
- RedBubble Poor Product Quality
- Creating Self Executable PHP Scripts
- Open Sourcing Facebook App, Squirrelify
- Open Sourcing EVE Crawler
- Cobalt Calibur: Roadmap
- Ignore SSL Errors with NPM Node Package Manager
- Pitfalls when Renaming your GitHub Account
- Using .htaccess to Prevent www Subdomain
- Global gitignore vs repository gitignore
- Modded Laser NERF Gun
- Building a Really Simple Node.js Module
- Redirect all Pages from Old Domain to New Domain Using .htaccess
- Linux Force Dismount
- Moving Content to a new Domain and Keeping SEO
- Hiding Files and Folders in OS X Finder
- Open Source AJAX Game Engine
- Why Node.js is awesome: A short history of web applications
- Tracking Backbone.js "Page Views" with Mixpanel
- The Shark Fin Conjecture
- Why the MPAA and RIAA will soon be gone
- Cobalt Calibur 3.0: Node.js, MongoDB, Redis, Backbone.js
2011 19
- How to use javascript event bindings to make callbacks cleaner
- Xpath Expressions Explained
- Tech Startup Entrepreneur Books
- Force or Prevent WWW subdomain with lighttpd
- How to generate a Self Signed SSL Certificate for lighttpd
- Tumblr-like Template Syntax PHP Library
- Really simple SSH proxy (SOCKS5)
- GIT: Colored Output, Shortcut Commands, Autocompletion, and Bash Prompt
- Using Swipes in MacVIM in OS X
- Simple PHP Namespace Friendly Autoloader Class
- Scheduling a daily Cron task in Debian to check external IP
- Building Custom OS X Dashboard Widgets
- How to login via SSH Without a Password
- Delay command execution in X-Chat
- Submitting Multi-Dimensional Array Data to PHP
- lighttpd configuration to redirect subdomains
- MySQL REPLACE vs INSERT ON DUPLICATE KEY UPDATE
- Apache2 Outperforming lighttpd 1.5
- Installing lighttpd on Ubuntu 10.04
2010 7
- PHP / MySQL Web Application Migration Steps
- Time Differences between PHP and MySQL
- Dynamic Form Actions using Different Buttons
- Read GET URL variables using JavaScript
- Zend Certified Engineer (ZCE) Study Guide Links
- Accessing CodeIgniter Session Data using External Scripts
- PHP cURL cookies not saving on Windows
2009 23
- Convert ASCII to UTF-8 using VBA
- Web Spidering with PHP
- FL Studio Piano Roll Tutorial
- FL Studio Comprehensive Mixer Interface Overview
- Polymorphism, Abstract Classes, and Interfaces in PHP
- FL Studio Automations
- FL Studio Interface Overview
- Introduction to CSS: Selectors and Relationships Explained
- Preloading CSS Hover Images
- Simple AJAX
- Password Encryption, Hashing, Salting Explained
- Create Windows Vista like buttons using Photoshop
- Web Image Formats Size and Quality Comparison
- Creating Seamless Textures using Photoshop
- Introduction to Photoshop Blending Options
- CSS Image Button Rollovers
- CSS Box Model differences in Firefox and Internet Explorer
- Database Administration using phpMyAdmin
- Free Notepad++ Web Developers Theme
- Pagerank and higher search engine rankings explained
- Change PHP Timezones
- Setting up VHOSTS using XAMPP/Apache in Windows
- Changing MySQL Default Character Sets