Ignored By Dinosaurs 🦕

At my gig we host our sites on Acquia's dev cloud. The dev environment is pretty locked down, obviously, since you don't want multiple, publicly accessible copies of your sites floating around out there, especially when it could be in any state of brokenness at any given time. So the way we do it is to use .dev domains that aren't publicly routable via DNS. We have a big ole master hosts entry in the local network that takes any of those dev domains and routes them to the proper IP.

Today however, I go out and my car won't start. This means I'm working from home, and that I need to add these host entries on my local machine myself since I'm not on the company network. As I type this I realize I could VPN, but that's no fun and I'm already done with this method that I'm about to explain.

So, I go to Acquia's cloud panel thingy. They have a “servers” menu item, but it only gives you the names of your servers, not IP addresses. Oh, we also have a load balancer sitting in front of everything that I can't log in to to get the IP that way (via ifconfig, presumably). So, they do give you this really vague

The following tables show all of the servers and the services(s) they provide for each of your site's environments. Each server's full DNS name is server.prod.hosting.acquia.com.

So anyway, the answer is the dig command – more or less a DNS swiss army knife.

dig server.prod.hosting.acquia.com spits back a wealth of info at you, including the IP address of your load balancer, which you can then put into an entry in your /etc/hosts file.

Love this stuff...

#drupal #devops

I was on the phone with Mom yesterday, and we got to talking about technology – a thing that actually happens fairly frequently. Being an only kid, she's genuinely interested in everything that I do and it's been helpful to have someone who's mostly non-technical to bounce explanations off of when I'm getting my head around a new piece of gear.

The piece of gear that I was explaining the other day was something called Mongo DB. Mongo's parent company is called 10gen, and they landed on the startup scene about 5 years ago or so with their flagship product, Mongo DB. Mongo is currently the pre-eminent player in the “NoSQL” database market. The NoSQL flavor of databases has come en vogue in the last few years in certain technology sectors, primarily ones that are evolving so quickly that having to slow down to put forethought into your data store and how it's going to be structured might literally be the difference between your whole company suceeding or not. That whole sentence will make more sense in a minute, but first it'd be helpful to understand how a traditional, “relational” database works.

The Relational model

The relational model of storing data has been around for more than 40 years. Wikipedia, of course, has a great article – http://en.wikipedia.org/wiki/Relational_database – giving a technical overview, and I wrote my own article 4 years ago while trying to get my own head around the concept – http://www.ignoredbydinosaurs.com/2009/04/chapter2-databases. Wow, that's hilarious reading that article actually, since my “Railroad Earth setlist database” example is well underway – http://www.hobocompanion.org/. So yeah, read that second one for the idiot's guide.

The classic example I gave to my mom was that of a common blog. You have a table for all your posts. Each post in that table has a row, and each row has something like a numeric ID, and the text of that post. When you want to read a blog post, the URL in that address bar of your says something to the effect of “give me post #1”. Whatever blog hosting software your using then turns around to the database behind it and says “select everything from the posts table where the ID of the post is 1”. The database hands back the post, the software renders some HTML out of it and sends it back to your browser. This is the simplest example of your interacting with a database.

The relational model typically comes into play when you visit a blog that has comments. Now you don't just have a Posts table, but you also have a Comments table. That Comments table will most likely have the same ID column, and a column called “body” or something like that for storing the text of the comment. However, this table will also have a column called something like “postid”, and what gets stuffed in that column is the (you guessed it) ID of the blog post that this comment “relates” to. So now when your reader comes by, the blog software turns around to the database and asks for two things this time – “select everything from the posts table where the ID of the post is 1”, and then “select everything from the comments table where the postid is 1”. This second “query”, if you're lucky enough to write something that people respond to, will return a list of comments, an array if you will, that your blog software will then convert to HTML and append to your blog post in the form of the comments section. Pretty simple, or is it?

Issues with the relational model

For the purposes of this simplistic example, this hopefully isn't that hard to get your head around. “But”, you might be wondering, “does that really make sense to store blog posts over here and comments over there? They're clearly related. When are you ever going to be examining a post's comments without wanting that post also?”

Very good. And this is a prime example of when a “non-relational” or “NoSQL” database might make a lot of sense.

The non-relational model

Let's stick with the same example, the blog post and comments, but let's think about how to “model” this in a non-relational way. By the way, if you're still with me, you have a deeper technical understanding than 99% of everybody around you.

The non-relational data model would look more like a sheet of paper. In fact, the concept of one entity and all the data that pertains to that one entity is known in Mongo as a “document”, so truly this is a decent way to think about it.

The way that your blogging software interacts with this blog post is theoretically a lot simpler in a non-relational database. Request comes in, blogging software turns around to Mongo and says “Please give me back this specific post and everything related to it”, in this case a listing of comments. BUT, that's not all. Since we're not forced to be too uptight about having to define how the data is structured beforehand, what if we want to tag that post with an arbitrary number of categories? No problem, stick them on the same document and when blog software says “gimme everything on Post #1”, the tags, the comments, and any other randomly associated data come back with it. Your software doesn't need to know ahead of time, you don't need to know ahead of time. It all just kind of works, provided you know what you're doing on the software level.

This amount of flexibility is what makes Mongo a very popular “data store” with quickly moving techonology companies that might be chasing an idea that changes from week to week or day to day. You don't have to rearchitect your entire system when you discover this particular use case down the road where you need to stick some “extra data” on this particular “thing”.

Issues with the non-relational model

It seems obvious that for this example a non-relational database makes a lot of sense, but like any useful tool, it has it's limits.

For this example, let's use a grocery list. You can model the grocery list in a lot the same way – a piece of paper, you write the items you want on there. But let's say, for the purposes of this example, you figure out after a couple of months that you want to keep track of how many loaves of bread you actually bought last year. Well, with the non-relational model you might literally have to go through every list and count each loaf individually (*simplistic example alert*), whereas had you modeled this in a relational way, you could get that count back almost instantly. Yes, it'd be a bit more work on the front end – essentially you'd have a Lists table and an Items table. But, modelled correctly, you'd also have a table in the middle called a “join table” that allows you to associate any number of items with any number of lists. After a while, were you truly the hacker, you could probably write some code that'd predict what you need to put on that list without even having to put it on there yourself, based strictly off of patterns that are easily discernable in a relational database.

That's why the Hobo Companion has a relational database behind it. It's super easy to count how many and which shows each user was at (2000+ shows tagged between about 30 users so far). It's super easy to count the number of times they've played Mighty River. It's super easy to count the number of times that I played Mighty River (somewhere around 260 times). It's super easy to figure out where in the setlist they typically put Dandelion Wine (Either first, or at the end of the first set). These calculations are far from impossible in a non-relational database, but they are also pretty far from trivial.

In situations where you absolutely want to be really uptight about your data and how it's structured – think bank accounts as the classic example – a relational database is absolutely required, not just because it's theoretically better suited for the job, but it's also a “mature technology” that's older than I am.

The wonderful point here is that we actually have decent options depending on what it is we are actually trying to do. Startup hackers love Mongo precisely because it lets you move fast. You can rock out an application in a weekend without having to spend most of one day setting up the equipment in the studio first.

Thanks for sticking with me.

#databases #theory

I have a friend for whom I'm building a site right now, and I chose Rails to do so. I think I'll probably reach for Rails for most sites I build until I get bored of it, which isn't going to happen any time soon. I also learned a few things about different browser's implementations of HTML5 audio, which I'll get into first.

My buddy is in a band, and so part of the functionality of the site is a photo gallery, and another part is a music player. Whereas in the past I'd have just reached for something off the shelf like jPlayer, I decided to go the HTML5 route this time, as I was fairly confident that my buddy wouldn't be asking for legacy browser support. In any event, he's not paying for legacy browser support, so I decided to teach myself a few long overdue tricks.

First up is a bit of a primer on the HTML Audio element. I found, as usual, Mozilla to have the most understandable and trustworthy documentation – here, and here. Building the player was fairly straightforward, but required a bunch of repetitive code that I'm too embarrassed to post here. It's fairly simple to create an audio element, list out a bunch of song objects with recording attributes attached to them, set a data-source attribute on those songs that points to the path where your uploaded recording file lives, courtesy of the Carrierwave and jQuery FileUpload gems. When you click on one of the songs, it kicks off the player.play() method and your song plays.

The surprise was that Firefox, in which I work every day, doesn't like mp3 files. There's some contradictory info out there about whether or not FF does or doesn't support mp3, but my version does not, so I had to figure out how to get an ogg version of the file up there also.

The method I came up with was to install FFmpeg to do the conversion, but to place the conversion into a background Sidekiq job so it didn't hang up the browser when my buddy uploaded his song. Sidekiq makes this so absurdly easy, and the Railscast steps you right through the process. Basically any processing that you'd want to do in the create or update action in your controller can be moved into a Sidekiq worker that's called instead of doing the processing synchronously. Watch -

# songs#create

def create
  @song = Song.new(params[:song])
  @song.title = @song.default_name unless @song.title
  if @song.save
    ConversionWorker.perform_async(@song.id)
    #logger.debug path
    redirect_to music_path
  end
end

And the worker —

# app/workers/conversion_worker.rb

class ConversionWorker
  include Sidekiq::Worker

  def perform(song_id)
    song = Song.find song_id
    path = "#{Rails.root}/public#{song.recording_url}"
    ogg = path.gsub(/mp3$/, "ogg")
    yup = %x[ffmpeg -i #{path} -acodec libvorbis #{ogg}]
  end
end

Converting stuff with FFmpeg was really straightforward, but only in Ubuntu. I fought with trying to get it set up with libvorbis on the Mac and eventually gave up. %x[] is the easiest way I found to execute shell commands from Ruby, complete with string interpolation. Basically this says – load that song, give me the recording_url (convenient that these Carrierwave methods are in scope), and create an ogg version. Do that by putting it right next to the mp3 version, but with the ogg file extension.

#ruby #rails #devops

I didn't remember mixing this but it must've been some time last year. This was the gig that Vince Herman opened up and Phil Lesh pulled up in his Ferrari out front and helped us level the joint for the second set. Strangely, there were no tapers present whatsoever, so no tapes showed up on the Archive. This was, however, one of the tours that we were taping for Elko, so we were running a 24 track rig that evening. I remember it being a challenge to get everyone down to 24 inputs, and being really glad that we figured it out later.

I remember listening to the little slice that we did put up on the Archive while I was doing this and being amazed how much reverb I put on it. Here's a drier version of the whole show.

2005-04-16SanFrancisco_CA.zip

#music

I've been a Media Temple customer for a long while now, almost 4 years. The file system on my grid server is a timeline of my learning programming and systems administration. I mostly work on big-boy systems over the last 2 years or so, so my comfort level with working through SSH is pretty high now (much higher than working through GUI tools that want to hold your hand, actually). That's one thing that I always loved about MT – the fact that they give you a pretty decent command line experience for administering your server.

One thing that's kind of always gotten on my nerves, however, is the DB admin experience. Lately since it seems like their PHPMyAdmin installation has completely gone to shit. Seriously, it's unusable. I couldn't even restore/import a < 1 MB brand-new-site database the other day because it kept timing out. Of course, this would be a 3 second maneuver on the command line mysql -u user -p pass target_database < dump.sql, but they have the command line locked down on the grid server.

I've recently moved a rather involved client project back onto their production server which is hosted on said grid server. I'm still banging on the thing, so I'd like to delete some rows straight out of the DB without having to spend 30 minutes trying to get PHPMyAdmin to do what I need it to. So the other day I went poking around the hosting admin panel.

I'd seen this years ago, and fortunately it's still there, probably just for this use case. In the “global settings” under the “databases” section of your admin panel at the very bottom of the screen is an option to allow external IP addresses access to the DB server. It even has a handy option to “use current IP” to prefill the field for you. Do this.

Next, invoke mysql locally, but pass it the --host option, like this —

mysql -u user -p pass --host=external-db.s123456.gridserver.com.

You're welcome.

PS – I tried importing the aforementioned <1 MB db in this method to no avail. Don't know if their db servers were on the blink at the time, but it definitely wasn't bandwidth.

PPS – it has occurred to me since this morning that mysql doesn't run on localhost, that's why you can't login as you normally would. Thus, if you were logged into your webserver, you could pass the same --host argument and specify the internal-db host to carry on about your business.

Never said I was that good at this stuff.

#databases #devops #mysql

I love this blog. It's amazing how much I used to write. I was so young and so passionate! My ego was totally huge! I had no idea how much of a ride I was really in for! It's a good thing, too!!

So yeah. I got a job. I've been bouncing around a bunch of different technologies for the last few years, trying to figure out where to land, what to do, what to be. Emmitt-Nershi is kind of chilling for the time being, and I happened to find out this was going to be the case the day I got a call back from a recruiter to tell me that the interview that I went on a few days earlier wanted to talk to my references...


So let's back up a minute. I'd been out on my own (a rather precarious place to be), freelancing whatever web stuff I could get my hands on and playing some really fun bluegrass with ENB. We had our third back in April of last year, possibly the most handsome Grubb boy yet, although they're all pretty much in a league of their own as far as cuteness is concerned. You never realize the ways in which your life is going to change when this whole new-kid thing happens, but the biggest difference this time was that I had absolutely no time or energy to go and scare up new work. We had been at about 80% of bandwidth with 2 kids, and now we were permanently at about 140%. My earnest advice to young parents – two is enough. Maybe if we had family nearby or something, but damn.

So anyway, throughout the summer I'd been fielding emails and phone calls from recruiters, kinda curious what would stick. I got one in August or so asking if I might be interested in a full time gig. I was interested in not having to chase down new work and I was interested in a salary and benefits, so sure, what's the gig? It turned out to be a Drupal gig in the publishing business up here in Jersey, not NYC (where the vast majority of programming jobs up here are).

So to make a long story shorter so that I can finish it, it turns out they're working on a lot of really cool stuff at a very transitional time for the company. It's the publishing business, and perhaps you've heard a bit about the upheaval in that particular business sector lately? Anyway, this company has been around for decades and has a couple dozen different magazines, mostly really technical trade magazines, stuff for which I have no background. They have websites in support of all of those magazines though, which means about 24 websites – half of which had already been moved into a large D7 multisite install, and the other half of which were in the process of being migrated into the same base.

Of 120 people in the entire company, there are 3 Drupal developers, of which I'm one. There's a “web production” team, but what they actually do is build emails. There's a dedicated designer who has been doing the front end/theming stuff for all these sites that we're rolling out, but she's leaving next week for good. What that means is that I'll probably be put somewhat back in charge of the front end (where I started), but in the meantime I've been working with a dude named Mike who is exactly the guy I've been looking for for the last 4.5 years. He's really good, really patient, really free with his copious knowledge, and seems genuinely stoked to have me on board. And over the last 4 months or so, my skills have started really snowballing.

I still suck at this stuff, but I'm getting a lot better, and fast. I'm getting pretty comfortable with the Ops part of DevOps, and am even writing some decent Drupal code. I've been working on a contract project for the last 3 months and I can confidently say that it would probably be over my head if not for the stuff I'm being exposed to on this gig. If nothing else it's given me a lot more confidence that I actually know some stuff now. They in house bugtracker is called Redmine, which just happens to be a Rails thing. Nobody in the company knew Rails or Ruby server setup, so it's become mine. It's a huge PITA, but I'm learning a hell of a lot about this tiny little OSS community around Redmine, and how to run a production Ruby app that gets a fair amount of traffic. And the hell that being stuck in a Ruby deployment situation can be.

I was given a ginormous Dell laptop running Windows 7 as my work computer – the only thing that looked like it might be a hiccup in the awesomeness. Given that there are only 3 real developers in the entire company though, the corporate process and restrictions that I've been afraid of for the last 34 years were pretty much non-existent, at least as far as what I could do with my laptop were concerned. I installed a VM running Ubuntu 12.04 the second day and have been working in Ubuntu for 8 hours a day. This is in addition to working between 10 and 20 hours a week on the contract work that I still have, and unfortunately have to do to make the ends meet (supporting a family of 5 in NJ is expensive as it turns out). I don't think I could keep up a 55 hour week forever, but who knows? Practicing and practicing and practicing in the service of getting really, really good at something has pretty much been what I do since I've been a teenager, so in that regard I'm well equipped.

I finally feel like I'm at the station, though not on the train yet. This is the training ground I've been looking for for 4 years now. My mission for this year is to get really involved with the Drupal community. I didn't get very excited by D7, but D8 is looking like Drupal is finally going to broaden it's scope into a project that encompasses modern development techniques that are going to be useful beyond Drupal's borders – a rather big hangup of mine as far as putting eggs in the Drupal basket is concerned.

So anyway, that's about it for now. Need to play more music, but I will again some day.

#life

WARNING! D6 code ahead!!

As improved as D7 is, they don't seem to have caught on to this one, so maybe this will help those of you as well.


The internet is surprisingly scarce on information about this topic. Maybe most people don't need to alter the password retrieval process, but I've got a client with a variety of different roles on their site. These different roles have different profiles via the Content Profile module. On account of numerous other account/profile management related modules that I've added – LoginToboggan, Auto Assign role, Invite – the whole process as well as the standard Drupal callbacks have gotten a little muddled.

By muddled I mean broken. For instance, the standard user/%uid%/edit page is broken to hell. I don't know why really except that there's some competing permissions/access thing that I just can't, for the life of me, find. Unfortunately this is the page that the stock Drupal password reset process brings you to to reset your password after logging in.

“No sweat!”, you might say. “Just call hook_password_reset() and be on your merry way!”

“I'd love to!”, I'd say in reply. “But there is no hook_password_reset()!”

After much digging I finally found a clue to look in the user.module in a file called user.pages.inc. Herein lies the function that handles this very process – user_pass_reset(). Reading through this function is pretty cool. It's very readable, but also feels kind of bloated and hackish in a way that makes me feel a little better about how shitty a programmer I actually am.

Down around line 111 is where the magic happens. Now, if you're reading this, you've probably tried everything I tried. I tried setting #redirect on the form, which doesn't work because Drupal will ignore #redirect on the form if #action is set. I tried unsetting #action on the form, which breaks the whole thing because Drupal relies on that very unique URL being submitted to validate the password reset. All that logic can be viewed in user_pass_reset, so there's no monkeying with that. All you want to do is change that stinking URL inside that drupal_goto() and the end of that function! Has noone encountered this use case before?!?

So I did what any desperate soul would do. I hacked core. I didn't respect myself afterward, but at least the process worked like my client needed it to.

Step away, do some thinking. The comment at the top of the function says “menu callback for”...

Enter hook_menu_alter().

So obviously, the solution requires a custom module. In the absence of a hook_password_reset(), you have to move a little deeper down the chain. hook_menu_alter() is the backdoor into the club of elation that is having this project behind you. hook_menu_alter() lets you grab and alter any menu item in the whole process. Looking a little higher in the call chain on the User.module I take a peek inside user_menu().

$items['user/reset/%/%/%'] = array(
	'title' => 'Reset password', 
	'page callback' => 'drupal_get_form', 
	'page arguments' => array('user_pass_reset', 2, 3, 4), 
	'access callback' => TRUE, 
	'type' => MENU_CALLBACK, 
	'file' => 'user.pages.inc',
);

So let's copy that user_pass_reset() into our module (the sweet_module in this case) and rename it sweet_module_user_pass_reset(). Then let's define my_menu_alter() to be something like this -

function sweet_module_menu_alter(&$items) {
	$items['user/reset/%/%/%'] = array(
	'title' => 'Reset password',
	'page callback' => 'drupal_get_form',
	'page arguments' => array('sweet_module_user_pass_reset', 2, 3, 4),
	'access callback' => TRUE,
	'type' => MENU_CALLBACK,
}

Note the new function name for the callback, and the removal of the 'file' bit at the end. Flush your menu cache and you should now be hooking into that damn function finally.

What you do now is totally up to you, but you can hack away at the entire function until it behaves properly. In my case it was sending this type of user this way and that type of user that way. And nobody to the stock drupal user edit path. And you didn't hack core, and you can keep upgrading your site like you always did with the flick of a drush command without ever having to worry.

You're welcome.

#drupal

So here I go again.

I've written at length on this blog over the years about Drupal. It's a great tool for getting things done right now. It's seen a huge uptake over the last couple years among government agencies and educational institutions, so being versed in Drupal development is a good career bet at the moment, meaning over the next couple years.

In the longer term though, I see it as pretty shaky and here's why.

Drupal's raison d'etre is that non-technical users (meaning – people who aren't programmers) can build fairly complex sites without writing a lick of code. It has seen massive growth, mainly because the fact that websites are actually computer applications with which users interact is a fact that is really just dawning on the majority of people who use the internet and/or need a website for their business. Most people don't have CS degrees, but every business needs a website. Thus, they either turn to someone who knows how to build websites, or they hook up with GoDaddy and do a one-click install of Wordpress.

However...

I think the world at large is rapidly getting used to the idea of writing code, and the proportion of people out there who are at least somewhat comfortable enough with that idea to hack together their idea is growing. And their idea might not be a good candidate for a Drupal site. The other thing about Drupal is that whatever your idea is, you can probably get pretty close without writing code, but chances are high that it's not going to be exactly what you want without writing some code (or hiring someone to write some code). And at that point, you either settle for something that isn't what you want or you teach yourself to write some code. And after you get comfortable with writing code, you start to wonder why you are dealing with all of this Drupal overhead that you didn't ask for in the first place. And some time after that you might find a language like Ruby, that makes infinite more sense to me than PHP, and looks a hell of a lot prettier to boot. And soon after that you might find it hard to get excited about Drupal work, because overriding other people's code is way less fun than writing your own to begin with, and that's the vast majority of working with Drupal code, at least form the backend.

#drupal

v0 – Blogger.

I think I got 3 or 4 posts in before realizing I wanted to try actually throwing up a website of my own.

v1 – Wordpress

One click installer at GoDaddy, my webhost for the first three months.

v2 – Drupal

I wanted to get more involved in the development side of it and was really loving the opportunities in the Drupal job market. Migrating a Wordpress blog was so predictable that there was a Drupal module to do so, and it brought all of my old posts, categories, everything. The setup of the categories was a little weird – it dumped everything into a Drupal Taxonomy called “Wordpress Categories”. I guess whomever wrote the module was tired of writing the module by the time they got to that point.

v3 – Back to Wordpress

Not really sure why. I have a vague recollection of blogging in Drupal just not feeling as fun, so I didn't do it as much. I'd moved into MarsEdit because it felt more “hacker-y”, but it didn't provide as fertile-seeming an environment as good ole Wordpress.

v4 – Back to Drupal

I was serious about Drupal now. I was starting to “get” Views and needed to put a portfolio together since I'd quit RRE by that point.

v5 – Jekyll

I was starting to get braver, even though this is the dead simplest tool out there. Some other soul put together a Ruby script that'd pull all my posts out of the Drupal DB and turn them into Markdown, the format that Jekyll required. Still, blogging just didn't seem quite as fun. I guess I didn't realize how much time I had in that tour bus after all.

v6 – Back to Drupal

I was pretty much a full time Drupalist by this point and put together a pretty decent portfolio site with it in a day or so. I was working on my Sass library and put together a “responsive” grid in a few hours. Good times. Lasted me a while but then the itch came again.

v7 – Rails

Finally came back to Rails about two months ago and rewrote this entire blog in about 6 hours from scratch. Not the trickiest of endeavors, but it took me 4 years to do that 6 hour rewrite. Wrote a Ruby script with Sequel to pull the posts out of the Drupal DB and put them into my Rails DB, URL aliases and all. The migration script took way longer than the actual build. Drupal likes to “normalize the fuck out of your data”, which means it scatters things all over the place in an attempt to store them in only one place. Did you know that the name of the column in the URL alias table is “src”, whereas everywhere else in the Drupal DB it's “source”. Shit like that, Drupal... I was able to put together with 4 MySQL tables what took Drupal something like 75 tables to do. Of course, the vast majority of those DB tables were never touched, which is a whole other thing about Drupal.

v7.1 – current – Rails and Mongo

I've been playing with Mongo for the last couple weeks and figured “fuck it” and did it yesterday. Took me 20 minutes to migrate the posts out of MySQL and into Mongo and replace ActiveRecord with MongoMapper. 20 minutes. It took me the rest of the night to get sessions and login working again since I dumped my entire user row into Mongo, so I had keys for :_id and :id in the same document. Once I realized that and played nicely with Mongo's idea of id (same for posts), everything worked out nicely.

Of course, for all that fun with cutting edge technology, there's going to be some sysadmin pain. And there was. I followed the wrong instruction to get Mongo going on this Debian server (followed the Ubuntu instructions. Whoops!) and spent the better part of this morning trying to untangle the mess. Never did, but typed mongo and it magically came up somehow. then spent the rest of the day migrating data and trying to figure why the hell ActiveRecord is still looking for a DB even though I ripped out every vestige of AR. Anyway, it's working now, and this will be the first post committed to a non-relational (aka NoSQL) database in my programming career.

Happy times. The amazing thing is that I've kept all of these posts with me through 8 or 9 different databases so far. Yay IBD.

#random

I see lots of these posts on Craigslist -

Meeting Planning firm is seeking a web designer on a freelance basis to work with provided art work in Photoshop/Illustrator and host onto closed invitation system.

Requirements:

Web designer must have design sense. Must code HTML/CSS — Java a plus.

I think they'd probably get taken more seriously if they replaced all instances of “designer” with “developer”.

So, it's pretty simple. A designer designs. A developer develops. “Web designer must have design sense.” Well, yeah. A designer must design.

So there are two parts to building anything on the web. See if you can guess what they are. I like to describe the difference to clients or my parents like this.


Think of your website project as building a house. Before you start building anything you probably want to meet with an architect. That architect will meet with you to find out what kind of house you want, will use their prior experience to help guide you with different ideas and options, and will ultimately deliver detailed plans of what your house will look like so that you can go hire someone who will actually build it.

The person who will actually build it is the general contractor. They have experience in building things from plans and can help guide you with difference options based on their experiences once in the building phase of the project.

Designer – architect. Developer – general contractor.

Do you already have artwork that you're happy with and need someone to help you build the darn thing? You need a web developer.

Are you just starting the planning phase and need to flesh out the ideas in your head? You probably want to meet with a web designer.

Note

This is a very loose metaphor. Many designers have some skills coding, and many developers have at least some clue about design. I am one that has some clue. I get layout, flow, what makes for good and bad user interface. I am a hell of a finish carpenter. I can make buttons like you wouldn't believe. What I struggle with is the “blank canvas”. I can't brand your idea. I can't come up with what I'd call a “design”. for that I call my buddy Bob. Bob is an artist. He does shit in Photoshop you wouldn't believe, but couldn't/wouldn't write a line of HTML if his life depended on it. We work really well together, and less well apart.

I sincerely hope this helps at least one person write a better Craigslist ad. Thank you.