I wanted short urls for Dimspirations, and I wanted a custom domain name (dim.moi), but didn’t want to pay the somewhat exorbitant prices to do so with something like Bit.ly. So I set out to build my own URL shortener.

PHP/mySQL seemed like the path of least resistance on my current server setup, so I went looking for existing tools that met my needs without too much complication. I found Shorty by Mike Cao, a decade-old project that still worked just fine. I forked it and built a tool called Shortly on top of it. It uses all of the base code of Shorty with my own additions, so full credit for this goes to Mike, but it has enough changes specific to my needs that I’m not pushing my fork upstream.

Shortly is a basic URL shortener. You just have to register your short domain, set up basic PHP/mySQL hosting for it, and then install the files. So the total cost is one domain registration, plus whatever hosting you use for it. It requires very few resources, so a simple $5 shared hosting plan will work fine. I have multiple servers where adding new domains doesn’t cost me anything, so I went with a Dreamhost server for this and built it for just the cost of a .moi TLD ($30/yr, if I recall correctly).

The install instructions are detailed in the README and on the project page. It’s pretty simple, just creating a mySQL database and importing an SQL file to set up the simple database. In about 15 minutes you can have a custom URL shortener that outputs urls like dim.moi/eQ and passes them through to the full url on the target site. All of my Dimspirations now have short urls, and I can generate new ones with a simple curl call from my build system.

Here’s what I added to the script:

  • Allow limiting shortening to one domain
  • Allow forwarding of paths containing hyphens or which are not found in the database to be forwarded to a root url
  • Allow appending query strings to urls before shortening or forwarding
  • Accept format=qr and size=XXX to create QR codes for shortened urls
  • Add longURL keys to JSON and XML output
  • Default to plain text output format, perfect for curl calls

All of these settings are detailed in the README and commented in the config file.

For my particular needs, my shortener will only shorten URLs from dimspire.me, will forward unknown urls like dim.moi/ether-bunny to https://dimspire.me/dimspiration/ether-bunny/, and will append some UTM parameters to any url it shortens so I can track usage.

Part of the impetus for this was I wanted to include UTM parameters in the links I offered for sharing, but didn’t want to make ungainly URLs. With Shortly, I can add any query parameters I like to a url and end up with a simple https://dim.moi/fR url to share. And I can shorten https://dimspire.me/dimspiration/optimal-anxiety-level/ to https://dim.moi/optimal-anxiety-level/ without even using the API (as the unrecognized slug automatically gets forwarded to the base url dimspire.me/dimspiration/SLUG).

Hopefully this inspires some fun projects of your own, and revives a great little project that Mike Cao started. It’s such a simple concept that I’m sure there are dozens, if not hundreds, of permutations of it. This is just the one I found the easiest to hack away at and get running with minimal fuss. Check out the project page or the GitHub repo to get started.

As an aside that’s not worth it’s own post, I also set up a CloudFront instance that forwards from.ttscoff.me/(filename) from an S3 bucket, and added a Dropzone destination so I can just drag any file to Dropzone and get back a from.ttscoff.me URL with which I can share any file. It lacks all of the niceties of other file-sharing tools, but I’m running it for less than a dollar a month. Subdomain was free, and it doesn’t use enough bandwidth to really register as an expense in my Amazon plan. If you want any details on how to do this, just let me know.