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