Everything I think about, and more.

Pull your Google Buzz feed with PHP

Google Buzz is new, but you can still use good old coreylib to pull your buzz feed into your PHP application.

Step 1: Make sure you have PHP 5 with cURL and SimpleXML installed and enabled. (If you’re using MediaTemple or eApps, you’ve got it.)

Step 2: Get coreylib – http://github.com/collegeman/coreylib/zipball/v1.1.1

Step 3: Get src/coreylib.php out of the ZIP and put it in your project.

Parse! Here’s an example

<!-- load coreylib -->
<?php require_once('../src/coreylib.php') ?>
<!-- two levels of debugging, should something go wrong... -->
<?php
//clAPI::configure('debug', true);
//clAPI::configure('trace', false);
?>
<?php if (!clCache::cached('google.buzz.feed', '1 second')): ?>
	<!-- create a new API parser with the feed address -->
	<?php $api = new clAPI('http://buzz.googleapis.com/feeds/108964711519495307614/public/posted') ?>
	<!-- parse it  -->
	<?php if ($api->parse()): ?>
		<!-- uncomment this line if you want a pretty tree to explore -->
		<?php //$api->info() ?>
		<!-- use xpath to grab all of the <entry> elements -->
<ul>
		<?php foreach($api->xpath('//feed:entry') as $entry): ?>
			<!-- for each entry element, grab the alternate link and the content -->
			<?php
				$content = $entry->first('feed:content')->__toString();
				$content = substr($content, 5, strlen($content)-5);
				$href = $entry->first('feed:link[@rel="alternate"]/@href');
			?>	
<li><?php echo $content ?> <a href="<?php echo $href ?>">&raquo;</a></li>
 
		<?php endforeach; ?>
		</ul>
 
		<?php clCache::save() ?>
	<?php endif; ?>
<?php endif; ?>
copy code

To learn more about coreylib, check out the project page.

For testing, dynamically create default values for long forms

Sometimes Web forms are long. And the longer the form, the more frequently we are plagued by details like field name duplication and making sure the field values show up in the database record  or an e-mail.

So for a recent project I whipped together the following JavaScript snippet (for jQuery, of course).  The snippet does the following on page load

  • All text fields and text areas assume a value equal to their field names
  • All select boxes take the value of their first non-empty options
  • All radio buttons get the last option checked
  • All check boxes are checked

Additionally, radio buttons, select fields, and check boxes each have appended a span tag bearing their field name.

;(function($) {
  $(function() {
    // text field values = text field name
    $.each($("input[type='text']").add("textarea"), function(i, input) {
      var field = $(input);
      field.val(field.attr('name'));
    });
 
    // select field value = first option with non-empty value
    $.each($('select'), function(i, select) {
      var field = $(select);
      $.each(select.options, function(i, option) {
        if (!select.selectedIndex && option.value != '')
          select.selectedIndex = 1;
      });
      field.after("<span>"+field.attr('name')+"</span>");
    });
 
    // checkboxes = checked
    $.each($("input[type='checkbox']"), function(i, checkbox) {
      var field = $(checkbox);
      checkbox.checked = true;
      field.after("<span>"+field.attr('name')+"</span>");
    });
 
    // radio buttons = last checked
    $.each($("input[type='radio']"), function(i, radio) {
      var field = $(radio);
      radio.checked = true;
      field.after("<span>"+field.attr('name')+"</span>");
    });
  });
})(jQuery);
copy code

If you use this snippet in your project, there’s no need to credit me with it, but do leave a comment on the blog to let me know what you think.

Installing Java 6 and Tomcat 6 on MediaTemple Virtual Dedicated Server (Linux)

The instructions written here are based somewhat loosely on other blog articles I found here and here. At time of writing the Java JDK is at release 6 Update 16, and Tomcat is at version 6.0.20.

There don’t seem to be many hosts out there that support Java Web application hosting. Besides, I really like MediaTemple – their pricing is dead-on, their support is top-notch, and their attention to aesthetics puts them head-and-shoulders above every other Web host I’ve ever used.

But they don’t support Java. That is to say, their “(dv)” service line does not have Java installed by default. The Tomcat button in their Plesk control panel is nothing but a tease!

Fortunately, with full root access, we can add Tomcat to any old (dv).

Step 1: Enable root access

Start this process by enabling root access through your Account Center control panel – this is just easier than using sudo.  (If you don’t know what sudo is, this article is probably not for you.)

root-access-and-developer-tools

Step 2: Download Java

First, download the latest Java JDK RPM bin file to your local computer.  You can find this download on the Java developers Web site.  All we need here is the JDK – no Netbeans, no Java EE.  Make sure to download the file ending in .bin, otherwise you’ll have to use a package manager to install it (and I don’t know how to do that).

Since I’ll be using this Tomcat instance exclusively for one of my sites, I install Tomcat there.  You can install Tomcat anywhere you want, so long as you remember where you parked the Web server.

I like to keep my applications and their dependencies in close quarters, so I’m going to put my Java installation at /var/www/vhosts/collegeman.net/subdomains/myapplication/dependencies.  Upload your .bin file here with any old FTP program.

Step 3: Run the Java installation

Use an SSH client (I like Putty on Windows, and the native SSH client on the Mac) to jump onto your (dv). Switch to the dependencies path you created, and the change the permissions on the .bin file with the following command

chmod a+x *.bin
copy code

Now you can run the Java installation by typing the following command

./your-installation-file.bin
copy code

You’ll have to hold down the enter key for a while to scroll through the Java license agreement.  At the end you’ll be asked to agree to the terms: type ‘yes’ and press enter.  Assuming the installation completes successfully, you can move onto the next step.  (If it doesn’t complete successfully, contact @kennethreitz.)

Step 4: Download Tomcat

You can find the latest Tomcat release on the Tomcat Web site.  Download the zipped tar-ball (.tgz or .tar.gz), and make sure you’re downloading the Core, not the Deployer or the Source. (If you happen to need the Deployer, I have no experience with this version of Tomcat – sorry.)

This file you should be able to download directly to your (dv) with the following command

wget http://apache.inetbridge.net/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.tar.gz
copy code

Make sure that when you run this command, you’re in the folder into which you’d like the download saved.

Step 5: Unpack Tomcat

Once the file is on your (dv), unpack the zip file with the following two commands

gunzip apache-tomcat-6.0.20.tar.gz
tar -xf apache-tomcat-6.0.20.tar
copy code

This should create an folder named apache-tomcat-6.0.20. I prefer to have Tomcat live in a folder simply named tomcat, and I prefer to have this folder be a sibling to the httpdocs folder in my application root.  So I move the tomcat folder there with the following command

mv apache-tomcat-6.0.20.tar /var/www/vhosts/collegeman.net/subdomains/myapplication/tomcat
copy code

Step 6: Test Tomcat

Using my path for the example, run the following command

./var/www/vhosts/collegeman.net/subdomains/myapplication/tomcat/bin/startup.sh
copy code

Tomcat will report four pieces of information, boiling down to the location in which Tomcat is installed and the location in which Java is installed.  You will then be returned to the command prompt.  If you don’t see any other output from this command, you can assume Tomcat is running.  Test access to Tomcat with the following URL

http://yourdomain.com:8080

If what you see is the Tomcat Management interface, then Tomcat has been installed successfully.

Step 7: Create a Tomcat service

Using the command-line editor vim, create and open a new service file with the following command

vim /etc/init.d/tomcat
copy code

Use the following content to define the service file. Please note where you must configure this file to run on your personal (dv). Once in the editor, press the i key which will put the editor into insert mode.  Then paste the configuration below into the editor

# This is the init script for starting up the
#  Jakarta Tomcat server
#
# chkconfig: 345 91 10
# description: Starts and stops the Tomcat daemon.
#

# Source function library.
. /etc/rc.d/init.d/functions
 
# Get config.
. /etc/sysconfig/network
 
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 0
 
tomcat=/your/path/to/tomcat
startup=$tomcat/bin/startup.sh
shutdown=$tomcat/bin/shutdown.sh
export JRE_HOME=/usr
 
start(){
 echo -n $"Starting Tomcat service: "
 #daemon -c
 $startup
 RETVAL=$?
 echo
}
 
stop(){
 action $"Stopping Tomcat service: " $shutdown
 RETVAL=$?
 echo
}
 
restart(){
 stop
 start
}
 
# See how we were called.
case "$1" in
start)
 start
 ;;
stop)
 stop
 ;;
status)
 # This doesn't work ;)
 status tomcat
 ;;
restart)
 restart
 ;;
*)
 echo $"Usage: $0 {start|stop|status|restart}"
 exit 1
esac
 
exit 0
copy code

Save the file by pressing the esc key, entering wq, and the pressing enter.

Next change the permissions on your script to make the file executable

chmod a+x tomcat
copy code

Test the script by executing the following commands

./tomcat stop
./tomcat start
copy code

You may get an error when you run the stop command – this is normal.  As long as you can get one full succession (starting then stopping) without errors, then you’re fine.

Step 8 (Optional): Front Tomcat with Apache

There are many things that you do not want Tomcat to be serving, namely static binary (like images) and text files (like CSS and scripts).  Honestly, I think this wisdom harks back to older, more inefficient times Tomcat land, still it is the best practice.  Doing so does have the additional benefit of being able to use more than one language on a single domain, e.g., PHP + Java.  So it’s not all bad.

As I’m pretty sure this task requires some source code compilation, I’m going to document it in a later post.

So do me a favor and let me know if this was useful to you.  Was it written well? Did I skip any steps? And most important, were you able to get it to work?

Working around GORM, paginating one-to-many relationships with SimpleJdbcDaoSupport (Part 1)

This is Part 1 of a two-part series on solving a problem that I have with Grails and with ORM in general. Part 1 describes the problem; Part 2 will describe the solution. Grails is a first-rate Web development framework for Groovy.  Groovy is like Python, except that underneath Groovy is Java and every Java library you ever loved.  If you’re a Java Web developer, you must give Grails a try; but if you’re a Spring Framework developer, you’re in for a special treat because Grails is built on top of everything we know and love about Spring.

In the course of using Grails to develop a handful of government Web applications, I’ve discovered a small gap between my applications and my data.

Grails includes an incredible piece of software engineering they call GORM, which is short for Grails Object Relational Mapping and is essentially Groovy syntax for creating HibernateCriteriaBuilder instances. This is the best practice for writing database queries in Grails, and it goes something like this

def courses = Course.withCriteria {
  // only approved courses, please
  eq('approved', true)
  // in a category matching the keyword "database"
  categories {
    ilike('name', '%database%')
  }
  // with offerings occurring in the future
  offerings {
    gt('starts', '2009/09/29 21:12')
  }
}
copy code

This Groovy code is roughly equivalent to the following SQL statement

SELECT * FROM course c
INNER JOIN course_categories cc ON (cc.course_id = c.course_id)
INNER JOIN category cat ON (cat.id = cc.category_id)
INNER JOIN offering o ON (o.course_id = c.id)
WHERE
  c.approved = 1
  AND LCASE(cat.name) LIKE '%database%'
  AND o.starts > '2009-09-29 21:12'
copy code

Now if you don’t appreciate the difference between these two chunks of code, it’s probably because you either have no use for ORM tools (PHP developers, I’m talking to you), have never tried to use Hibernate, or have never had to write low-level data layer code with JDBC.  The rest of you are probably thinking, “Man, that’s pretty frickin’ cool.” Because it is.

As I’ve experienced it, there’s only one problem with the GORM way, and it’s actually a problem with the ORM way in general.

In our example above we reference three domain objects: Course, Category, and Offering. For the sake of our example, we will assume that there are one-to-many relationships between Courses and Categories, as well as between Courses and Offerings.  That means for every one Course in the system, we’ll have zero, one, or more than one Offerings related to it.

Relationships like these are exactly what RDBMSs and ORM are all about: taking flat relationships and turning them into hierarchies of objects.  The problem is that when we rely on these relationships for the purpose of querying data, we almost always introduce duplication into our result set.

Imagine a set of data in which there are two courses, each with two related offerings.  Imagine that all of these records satisfy our query above.  The result set for our SQL query would look something like this

COURSE.ID NAME             OFFERING.ID STARTS     ENDS
1         Tuning Your SQL  1           2009/10/26 2009/10/26
1         Tuning Your SQL  2           2010/01/01 2010/01/04
2         Hiring Good Help 3           2009/11/04 2009/11/05
2         Hiring Good Help 4           2009/12/06 2009/12/07
copy code

Take note of the duplication: two instances of a course record for each instance of the corresponding offering record. The problem has the potential to get worse when we introduce categories.

COURSE.ID NAME             CATEGORY            OFFERING.ID STARTS     ENDS
1         Tuning Your SQL  Database Management 1           2009/10/26 2009/10/26
1         Tuning Your SQL  Database Management 2           2010/01/01 2010/01/04
1         Tuning Your SQL  Databases, General  1           2009/10/26 2009/10/26
1         Tuning Your SQL  Databases, General  2           2010/01/01 2010/01/04
2         Hiring Good Help Database Personnel  3           2009/11/04 2009/11/05
2         Hiring Good Help Database Personnel  4           2009/12/06 2009/12/07
copy code

Where once there were two copies of Course #1 now there are four!

Now, in most circumstances, this really isn’t an issue. That’s right. I said isn’t an issue.

GORM and Hibernate both provide the means for eliminating this duplication at object instantiation, and it’s called distinct. All we have to do to implement this feature is change one line in our original GORM query (the first one):

def courses = Course.createCriteria().listDistinct {
copy code

Now if we were to loop over the contents of courses, we would find two objects instead of six: one for each unique Course is our result set.

One very common use case for Web applications is large result set pagination. While our own example result set doesn’t warrant pagination, one containing a thousand relationships between hundreds of courses, offerings, and categories, certainly would.

GORM includes two query features for pagination: firstResult, which should be a positive integer indicating the first row to return, and maxResults, which should be a positive integer indicating the page size.  When woven into our original GORM query, the code now looks like the following

def courses = Course.createCriteria().listDistinct {
  // only approved courses, please
  eq('approved', true)
  // in a category matching the keyword "database"
  categories {
    ilike('name', '%database%')
  }
  // with offerings occurring in the future
  offerings {
    gt('starts', '2009/09/29 21:12')
  }
  firstResult(x)
  maxResults(y)
}
copy code

So imagine a version of our result set that when raw contains 100 records.  That’s 100 instances of relationships between Courses and Categories, and Courses and Offerings.  Irrespective of the total number of distinct Courses, we decide that we’d like to paginate our result set 10 records at a time.  And this is where somewhere in the beautiful stack that is Grails, something goes ker-splat!

Check back soon for Part 2!

CustomInk: a great T-shirt printing experience

After reading Seth’s praise for custom printer CustomInk on more than one occasion, I decided I’d give them a shot.

Now, that’s not the whole truth.  The whole truth is that at first I couldn’t remember the name of the company.  I could, however, remember the name CafePress.  The funny thing is I’ve never used CafePress before – I’ve only ever heard of it.

What was it that made me consider CafePress before gritting my teeth and plundering Seth’s blog for the forgotten name?

Perhaps it is because I’ve heard so many people talk about CafePress, my mother in particular.  My mother is a pastel artist, and she does beautiful work.  She once considered using CafePress to distribute tiny prints of her work.  The samples we received in the mail weren’t any good.  Still, when it came time for me to put brand to cotton, I still went back to the inferior service first.

All I’m saying is that there is marketing at work here in a way that I don’t fully understand. I don’t typically find my mother in tribes to which I am a member.  Go figure.

Long story shorter, I was finally able to recall the name, and let me tell you: I am one satisfied potential customer.  The t-shirt design workshop CustomInk provides through their Web site is top-notch.  The interface is a little 2003; but the usability is unparalleled.  I had only one issue with the tool: it took me a while to figure out how to allow the white to stay in my uploaded art.  (There was a checkbox – I overlooked it.)

The t-shirts are for promoting coreylib – my universal API client (with caching built-in!). Ten t-shirts in two sizes for $251. That’s not bad, considering I’ll be creating ten community billboards the size of Large and Extra Large chests.

Best of all: the CustomInk workshop lets me share my designs with my audience ahead of time. Here’s hoping you guys like it.  Please note: I’ll probably be changing the tag line on the back – the current one is a bit too confrontational. (See, I’m trying to learn from my mistakes.)

customink

Decoding the GPL: can this be commercial?

I’ve been doing some research lately in preparation for a new project.  (Yes, another new project.) The goal of this project is ultimately to produce some software that my customers will license from me (monthly rate) and install on their own servers.

On the face of it, a simple task indeed; however, the task grows significantly more complex when I consider the ramifications of using some open source components in the development of my product.

A little back story. I do a lot of work in open source. I love open source. I have written code from scratch and open sourced it; and when I do, I license my open source with the the GNU GPL, version 2.

What the heck does that mean?

The GNU General Public License is a software license designed to protect licensee freedom. There is an important distinction to be made here, and the GNU folks do it quite nicely

The word “free” has two legitimate general meanings; it can refer either to freedom or to price. When we speak of “free software”, we’re talking about freedom, not price. (Think of “free speech”, not “free beer”.) Specifically, it means that a user is free to run the program, change the program, and redistribute the program with or without changes.

The armchair lawyer in me interprets this as follows.  Code licensed under the GPL must always be free – free to be executed, free to be modified, and free to be redistributed (though a distributor may charge money to his customers for the privilege of downloading it – this is relevant for big things like Linux distros).

So, if I acquire some GPL licensed open source software and I modify it, I am legally bound to allow those to whom I distribute the code to exercise the same rights I did under the protection of the license.

But what happens if I don’t modify the source code?

What if instead the open source component were simply that: a component of a larger system?  Surely the code I do write will be dependent on the open source in some way (or more likely, many ways). But if I am not modifying the open source programs, am I obligated to set my own code free?

Consider the specifics of my project. I’m writing a Web application that I want to distribute, to be run on my customer’s own hardware. (Running the software is actually one of the key features of the product, and offers enormous differentiation in this new age of so-called Cloud Computing.)

There will be four open source products comprising the application server stack: Tomcat, Quercus, HSQL, and CodeIgniter.  They don’t all play together out of the box, but getting them to that point is a matter of configuration not customization. So I put them all together and, voila!, I have a portable PHP Web Server with a built-in database and job scheduler.

From CodeIgniter up, the code I write will be 100% my own.  So the question becomes: if my application is dependent upon but not a derivative of my application server stack, does my application need to be released under the terms of the GPL? According to my interpretation of the GPL, the answer is no.

It is fully my intention to document and release the application server stack. It sounds a bit esoteric, I know: “a portable PHP server.” But trust me: it has its usefulness.  Don’t get me wrong, Java is a great language; but developing Web applications in Java or a Java-compiled language like Groovy is still more difficult and more tedious than it should be.  Challenges like writing an auto-updating mechanism and a plug-in framework seem down right easy in PHP, compared to what would likely be a solid month of trail and error engineering in Java.

So what do you think? Must my product be free, or will I be allowed to be the sole profiteer?

WP-CI: a CodeIgniter-based plug-in framework for WordPress

This article is about a new WordPress plug-in that I have just released in ALPHA.  Download and use at your own risk: it is far from finished.

I love WordPress. But writing plug-ins for WordPress sucks. There are a lot of plug-ins out there, all of them using WordPress’ smashing plugin API to create some great functionality. But at the end of the day, the native API leaves me wanting more.

I want to develop WordPress plug-ins using MVC principles. I want for security to be easy to remember and easy to implement. I want to be able to write plug-ins that provide body content on the front-end with minimal modification to my themes. I want to be able to utilize AJAX without implementing esoteric, hack-like features in my plug-in.

And I don’t want to have to refer to the gigantic Codex every time I need to one-off a new project: give me a manageable API.

With these goals in mind, I have written a plug-in for WordPress that creates a new plug-in framework. This framework, based on CodeIgniter, has far exceeded my personal expectations for the project (and it’s still in alpha!). Not only did I manage to satisfy my own requirements, I managed to do so without hacking either of the proven stacks, all while taking advantage of some very cool features of PHP 5 (annotations).

I named the plugin WP-CI.

A bit on how it works

Explaining the nuances of MVC development in CodeIgniter is beyond the scope of this article, and with good reason: they have some great documentation.  But for the uninitiated, know this: CodeIgniter divides application functionality into Controllers and Actions.  Each Controller gets its own PHP file, and each public function on the Controller is exposed to the Web as an Action – discreet units of application functionality, each with a specific purpose (like display a form, save some data, delete a record, or return some JSON).

In WP-CI, each controller file (stored in ./application/controllers) is, in effect, a special WordPress plug-in that I call a WPCI Plug-in.  Within the body of each PHP file you have complete access to the entire WordPress API, as well as complete access to the CodeIgniter framework.

To learn more about the structure of a WP-CI file, download the latest release and have a look at ./application/controllers/hellosparky.php.  A more complicated example exists in the WPCI Plug-in Administrator, which is itself a WPCI Plug-in.

Using annotations

Once again, for the uninitiated, annotations (in PHP) are special comments added at various locations in a PHP file.  This is a concept specific to PHP’s object-oriented programming syntax, and allows developers to add meta-data to class definitions.

WP-CI makes extensive use of this PHP 5 feature, making this framework incompatible with PHP 4 (sorry guys and gals: welcome to the future).

Annotations look like this

/**
 * @user_can(edit_plugins)
 */
class Admin extends WPCI_Controller {
  function index() { /* ... */ }
}
copy code

The annotation featured above, @user_can(edit_plugins), is a cue to our framework to require any user accessing this plug-in to have the built-in WordPress capability of editing plug-ins.  (This requirement implies a user be an administrator.  You can read more about user capabilities in the WordPress Codex.)

There are other annotations too, like @menu and @submenu which serve to create administrative menus and menu items from your plug-in actions.

For more examples of annotations in action, have a look at the WPCI Plug-in Administrator, ./application/controllers/admin.php.

Early adopters beware

The current release is ALPHA and so you should expect the core API to change with the next release, and possibly even break your application in complicated ways. You have been warned.

This software is not warranted in any way.

So, have you tried it out yet?

Crowdsourcing with crowdSPRING

While designing the Web site for Winchester’s Bright Cowork, my friend and colleague @coreyweb used a service called crowdSPRING to crowdsource the logo. As a spectator to the process, it seemed like an efficient and relatively inexpensive way to get some design work done. (You can see the final product here.)

For those of you unfamiliar with the concept:

Crowdsourcing is a neologism for the act of taking tasks traditionally performed by an employee or contractor, and outsourcing it to an undefined, generally large group of people or community in the form of an open call. For example, the public may be invited to develop a new technology, carry out a design task (also known as community-based design[1] and distributed participatory design), refine or carry out the steps of an algorithm (see Human-based computation), or help capture, systematize or analyze large amounts of data (see also citizen science).

Commissioning work through crowdSPRING (almost) couldn’t be easier: just describe the project, and set a competitive price. The price you set is what will be paid to the winning designer. crowdSPRING then charges buyers 15% on top of the stated price – for a $300 job, this fee is $45. All money is paid ahead of the launch of the project, and is held in escrow until the project’s close – by default, one week. “Creatives” submit designs, and at the end of the project, the buyer selects one to be the project winner.

I was encouraged by the results Corey got from his crowdSPRING experience, so I decided to create my own project there (a new logo for my coreylib project).  So far, so good: I am very excited about some of the responses I have received.

But despite what I would call success, it should come as no surprise that the design community is very vocal in their disapproval of crowdsourcing and services like crowdSPRING. There is a status quo being challenged here. Crowdsourcing introduces competition on a grand scale into what has traditionally been a very selective process.  While this does yield a net benefit to the buyers, the work generated does exhibit a few negative consequences of the community process: namely, degraded quality and consistently, and a drastic reduction in the value proposition for the designers.

Business analysts and the service brokers themselves are claiming that crowdsourcing is the future of design, given the reduction in cost and the buyer’s ability to be extremely selective and critical of the end result.  Wrapped too in this new capacity to criticize is a departure from a time of designers being treated like doctors: that is, rather than being given carte blanche, they are instead often forced to assimilate the sometimes-arbitrary opinions of their customers (”I think it would look better if it were more balanced: centered vertically.”).  While this assimilation probably does happen quite a bit in the old world of design, I imagine that this play comes at a much higher price than $345.

It is easy to understand how this new marketplace could be perceived as an assault on the authority of designers and their maintenance of common (and important) aesthetics: an assault that, were it authentic, certainly should lead to a very cynical reception.  But I completely disagree with the idea that crowdsourcing is the future and will replace the traditional marketplace for design. The community-driven process of a service like crowdSPRING could never surmount the true authority and expertise that comes with a trained hand and mind, and the dedicated consultation.

What crowdsourcing does achieve is the creation of a niche market: one at which someone like myself, with limited time and a tight budget, can easily and efficiently vet a large number of ideas.  But these services are far from perfect.  Of the two I know about – 99designs and crowdSPRING – I chose crowdSPRING simply because I knew of a local success story.  In hindsight I am relieved I chose crowdSPRING over 99designs, because the manner in which 99designs manages the purchasing process is completely unethical. Unlike buying designs from crowdSPRING, 99designs does not appear to require the buyer to award a project. This leaves designers highly vulnerable to idea theft, and nefariously forces many into providing free consultations. Frankly, for a thing like community-based design to be fair and productive, both the designers and the buyers must have some skin in the game.

So how could using crowdSPRING be easier?  Well, for one thing, it would be nice to be able to quickly view Creatives’ previous submissions.  It is possible to get to previous submissions from a Creative’s profile page (a feature built-into crowdSPRING), but once on the project page, the user’s submission is hidden amongst all the other submissions made.  Some more guidance given to Creatives on the process of submissions would be very helpful: rather than having to score and review seven small variations on a single concept, it would be far more efficient to have all seven submitted as a single submission.  It took me a while to discover that I could score and comment from the gallery page – making this feature more prominent, and adding more controls for navigating between zoomed pieces would dramatically increase the frequency with which buyers provide quality feedback.

So if you’re on the market for a new logo or t-shirt design, I recommend giving crowdSPRING a try.  Make sure to read and follow the tips given to buyers at the onset of the project, namely the one that advises buyers to send private messages to creatives inviting them to work on the new projects.  Using this push approach to getting traffic to your project definitely increases the frequency with which you receive submissions. That and providing as much feedback as possible – most of the crowdSPRING designers thrive on constructive criticism.

If you’re looking for a place to start, I recommend these Creatives:

Have you had success with crowdSPRING or crowdsourcing? Please share your experiences in the comments.

Tomorrow is the big day: B-Day

Wifey and I can scarcely contain ourselves. So to pass the time until 9/8 0730 to get here, we decided to take a short trip down memory lane and came up with this video of baby gyrations. We hope you enjoy it as much as we do.

Braggin’ on my new theme

I’m not a designer.  So when I have the opportunity to brag about something I designed, I try to take advantage.

One of my goals scheduled for before the birth of my first child (three days and counting!) was to get my blog design set.  I wanted to have something that was aesthetically appealing (to my personal aesthetics, anyway), and very functional.  Something I could pour my mind into reliably, if somewhat infrequently.

So today I give you the latest version of my blog.  The design borrows heavily from a personal project I’m working on (can’t tell you any more about it just yet, but it’s for project management). I like the soft corners, and Twitter colors: it feels homey to me – I’ve always thought blue was very comforting.

I’m using a custom WordPress plug-ins for Twitter/Bit.ly and Facebook comments – the latter being something that I open-sourced not long ago, but then withdrew (because it had a major flaw, and because I wanted to mix it into a more comprehensive tool – I’ll be releasing it again soon!).  I’ll be adding some more feature soon, mostly in an effort to turn some profit from my traffic (if I ever manage to develop any).

So, what do you think?

Older Posts »

Subscribe to Perseverance Trumps Talent