drupal

Managing per Project Installation Profiles

Unbeknown to many users, installation profiles are what is used to install a Drupal site. The two profiles that ship with core are standard and minimal. Standard gives new users a basic, functional Drupal site. Minimal provides a very minimal configuration so developers and site builders can start building a new site. A key piece of a Drupal distro is an installation profile.

I beleive that developers and more experienced site builders should be using installation profiles as part of their client sites builds. In Drupal 7 an installation profile is treated like a special module, so it can implement hooks - including hook_update_N(). This means that the installation profile is the best place for controlling turning modules on and off, switching themes or any other site wide configuration changes that can't be handled by features or a module specific update hook.

In an ideal world you could have 1 installation profile that is used for all of your projects and you just include it in your base build. Unfortunately installation profiles tend to evolve into being very project specific. At the same time you are likely to want a common starting point. I like to give my installation profiles unique names, rather than something generic like "my_profile", I prefer to use "[client_prefix]_profile". I'll cover project prefixes in another blog post.

After some trial and error, I've settled on a solution which I think works for having a common starting point for an installation profile that will diverge overtime using a unique namespace. My solution relies on some basic templates, a bash script with a bit of sed. I could have written all of this in PHP and even made a drush plugin for it, but I prefer to do this kind of thing on the command line with bash. I'm happy to work with someone to port it to a drush plugin if you're interested.

Here is a simple example of the templates you could use for creating your installation profile. The version on github is closer to what I actually use for clients, along with the build script.

base.info

name = PROFILE_NAME
description = PROFILE_DESCRIPTION
core = 7.x
dependencies[] = block
dependencies[] = dblog

base.install

<?php
/**
 * @file
 * Install, update and uninstall functions for the the PROFILE_NAME install profile.
 */

/**
 * Implements hook_install().
 *
 * Performs actions to set up the site for this profile.
 *
 * @see system_install()
 */
function PROFILE_NAMESPACE_install() {
  // Enable some standard blocks.
  $default_theme = variable_get('theme_default', 'bartik');
  $values = array(
    array(
      'module' => 'system',
      'delta' => 'main',
      'theme' => $default_theme,
      'status' => 1,
      'weight' => 0,
      'region' => 'content',
      'pages' => '',
      'cache' => -1,
    ),
    array(
      'module' => 'user',
      'delta' => 'login',
      'theme' => $default_theme,
      'status' => 1,
      'weight' => 0,
      'region' => 'sidebar_first',
      'pages' => '',
      'cache' => -1,
    ),
    array(
      'module' => 'system',
      'delta' => 'navigation',
      'theme' => $default_theme,
      'status' => 1,
      'weight' => 0,
      'region' => 'sidebar_first',
      'pages' => '',
      'cache' => -1,
    ),
    array(
      'module' => 'system',
      'delta' => 'management',
      'theme' => $default_theme,
      'status' => 1,
      'weight' => 1,
      'region' => 'sidebar_first',
      'pages' => '',
      'cache' => -1,
    ),
    array(
      'module' => 'system',
      'delta' => 'help',
      'theme' => $default_theme,
      'status' => 1,
      'weight' => 0,
      'region' => 'help',
      'pages' => '',
      'cache' => -1,
    ),
  );
  $query = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache'));
  foreach ($values as $record) {
    $query->values($record);
  }
  $query->execute();

  // Allow visitor account creation, but with administrative approval.
  variable_set('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL);

  // Enable default permissions for system roles.
  user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content'));
  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content'));
}

// Add hook_update_N() implementations below here as needed.

base.profile

<?php
/**
 * @file
 * Enables modules and site configuration for a PROFILE_NAME site installation.
 */

/**
 * Implements hook_form_FORM_ID_alter() for install_configure_form().
 *
 * Allows the profile to alter the site configuration form.
 */
function PROFILE_NAMESPACE_form_install_configure_form_alter(&$form, $form_state) {
  // Pre-populate the site name with the server name.
  $form['site_information']['site_name']['#default_value'] = $_SERVER['SERVER_NAME'];
}

Some developers might recognise the code above, it is from the minial installation profile.

The installation profile builder script is a simple bash script that relies on sed.

build-profile.sh

#!/bin/bash
#
# Installation profile builder
# Created by Dave Hall http://davehall.com.au
#

FILES="base.info base.install base.profile"
OK_NS_CHARS="a-z0-9_"
SCRIPT_NAME=$(basename $0)

namespace="my_profile"
name=""
description="My automatically generated installation profile."
target=""

usage() {
  echo "usage: $SCRIPT_NAME -t target_path -s profile_namespace [-d 'project_descrption'] [-n 'human_readable_profile_name']"
}

while getopts  "d:n:s:t:h" arg; do
  case $arg in
    d)
      description="$OPTARG"
      ;;
    n)
      name="$OPTARG"
      ;;
    s)
      namespace="$OPTARG"
      ;;
    t)
      target="$OPTARG"
      ;;
    h)
      usage
      exit
      ;;
  esac
done

if [ -z "$target" ]; then
  echo ERROR: You must specify a target path. >&2
  exit 1;
fi

if [ ! -d "$target" -o ! -w "$target" ]; then
  echo ERROR: The target path must be a writable directory that already exists. >&2
  exit 1;
fi

ns_test=${namespace/[^$OK_NS_CHARS]//}
if [ "$ns_test" != "$namespace" ]; then
  echo "ERROR: The namespace can only contain lowercase alphanumeric characters and underscores ($OK_NS_CHARS)" >&2
  exit 1
fi

if [ -z "$name" ]; then
  name="$namespace";
fi

for file in $FILES; do
  echo Processing $file
  sed -e "s/PROFILE_NAMESPACE/$namespace/g" -e "s/PROFILE_NAME/$name/g" -e "s/PROFILE_DESCRIPTION/$description/g" $file > $target/$file
done

echo Completed generating files for $name installation profile in $target.


Place all of the above files into a directory. Before you can generate your first profile you must run "chmod +x build-profile.sh" to make the script executable.

You need to create the output directory, for testing we will use ~/test-profile, so run "mkdir ~/test-profile" to create the path. To build your profile run "./build-profile.sh -s test -t ~/test-profile". Once the script has run you should have a test installation profile in ~/test-profile.

I will continue to maintain this as a project on github.

GitList and my TODO List

Months ago I was searching for a good web front end for git for doing code reviews and browsing repos. My short list ended up being Gitweb and GitLab.

Gitweb is a Perl based web front end for git that is a sub project of the official git project. Out of the box Gitweb is pretty ugly and I have never found it to be very user friendly. Even with all of its problems, it does what it does pretty well.

GitLab is a Rails based github clone that is being actively developed and shows a lot of promise. If you want a fully blown ready to go basic github clone to setup and run for your dev team, GitLab looks great. Unfortunately trying to install it on RHEL5 wasn't an easy task. GitLab offered a lot more functionality than I needed and my lack of Ruby experience meant that it was adding more complexity than I wanted.

I ended up reluctantly recommending that we use Gitweb but I have since changed my mind.

Over the last few weeks I've been playing with GitList by Klaus Silveira. GitList is a web front end for browsing git repos, that looks a little like github. Klaus describes GitList as:

GitList is an elegant and modern web interface for interacting with multiple git repositories. It allows you to browse repositories using your favorite browser, viewing files under different revisions, commit history, diffs. It also generates RSS feeds for each repository, allowing you to stay up-to-date with the latest changes anytime, anywhere. GitList was written in PHP, on top of the Silex microframework and powered by the Twig template engine. This means that GitList is easy to install and easy to customize. Also, the GitList gorgeous interface was made possible due to Bootstrap.

It is nice having an open source side project to contribute to that gets me out of the Drupal ghetto. GitList also gives me an excuse to play with Symfony components and twig more, both things that are already in Drupal 8 core. Silex has been on my "to play with list" for some time too.

I have been searching for an alternative to Gitweb that is easy to use, has a nice UI and the basic features I want in a web front end for git - commit history, diffs, blame and branch comparison. GitList ticked all the boxes, except blame was a bit broken and branch comparison wasn't implemented.

I now run GitList on my laptop for offline repo browsing and find it very useful. I will be deploying it for a client in the next few weeks as part of a broader Drupal workflow management system.

This isn't a review of GitList and I won't be providing any feature comparison of GitList vs (Gitweb|GitLab|github). Instead this post is inspired by a discussion on twitter between Klaus (@klaussilveira), Fabien Potencier (@fabpot), Peter Droogmans (@attiks) and myself (@skwashd). I want outline how we are using GitList and the underlying git library, my vision for GitList and what I can do to make it happen.

Missing Features

Based on the project description I think that GitList is almost feature complete. There are a few TODO items in the README. In my time using GitList I haven't found myself going "if only it did X (and Y and Z)" - except branch diff support. I have been working on a branch diff patch, and I hope to clean up that code this weekend and submit a pull request. I think it is good when something does one thing and does it well.

Library and App Separation

As part of the workflow management system for Drupal we're developing we needed a solid git library for PHP. The one that ships with GitList is pretty nice. I've been working with my fellow Technocrat developer, James Harvey, on extracting the git library from GitList. We still have some work to do on this, but it is usable today. We have added some enhancements to the library for our purposes and removed the Silex dependency. Our vision is to have a generic OO git library for PHP 5.3+ and that GitList use this as a sub module.

Although I am currently hosting the code in my github repo, I would love to see Klaus create a new primary repo for the library and that James, myself and others would continue to develop and support his library. It is not my intention to fork the library from GitList and maintain it myself in isolation - that is a waste of energy and resources.

Git Module for Drupal

Following on from our creation of a generic git library for PHP, we have created a git wrapper module for Drupal. We plan to release this module in the next week or so on drupal.org - we've already reserved the project namespace. As part of this change the features git module will now depend on the new library wrapper module. We will release other modules that use this library as they pass QA.

Releases

I have a hacker mentality, I am happy to clone a repo, create a branch or tag and start playing. If I find something that it broken, then there is a good chance that I'll fix it and post a patch. At the same time I understand that not everyone can work that way and that in some environments there is a focus on only using official stable releases. It is also difficult tracking bugs against git commit hashes. GitList is moving quickly, but I think that it could benefit from having official releases.

If the library and app are separated, they can have separate and independent release cycles. I am happy to work with Klaus to work out a plan for GitList releases. One of my first roles in an open source project was as a release manager.

Discussion Space

I have posted this on my blog because I don't know what the real audience is for this conversation. I know that there are 3 people interested in participating in the conversation but are there others? I know others contribute patches to GitList. I could have emailed Klaus directly, but that would have excluded others who are interested. Even though in some ways email is on the way out, some discussions require more than 140 characters. Is it worth setting up a mailing list, google group, a forum or some other channel of communication to discuss these issues?

The Future

I am already dependent on GitList for a significant piece of work. I want to work with Klaus and the rest of the GitList community to make a kick arse web front end for git, I also need a rock solid PHP lib for git. I think GitLib provides a solid foundation for both. Fabien wants to use it as a good Silex example. What do others want to do with GitList? Let the discussion begin ...

Upadte: Klaus has asked that we move the discussion to the recently created GitList mailing list/google group, so I have created a new thread to continue this conversation. I can cross an item off my list - discussion space.

Your Site Should be Full of BEANs*

From: Dave Hall
To: boxes <[email protected]>
Subject: Our Relationship

Dear boxes,

I'm sorry but things just aren't working out between us. It's not you, it's me. I need some time to myself. I need to think things through. I'm not sure what I want. We should spend some time apart. We should try new things. I will miss you, but this is for the best. Let's meet for coffee in a couple of weeks.

Love

Dave
xox

Breaking up is never easy, but recently I broke up with the boxes module. I'd been with boxes for a long time, we'd done a lot of good things together. Over time I'd become oblivious to some of boxes' flaws, such as giving black eyes to sys admins who run features reverts on sites where users can edit boxes. Life was pretty good, but my life still felt somewhat empty and incomplete.

One day I was standing in a crowded room with lots of modules on drupal.org and across the room I spotted BEAN. I feel in love instantly. BEAN was decked out in all the latest Drupal 7 gear - fields, Entity API and CTools. The way BEAN moved make me weak at the knees. After another beer I got my courage up, crossed the room and asked if BEAN would like to come back to my site. I was shocked, BEAN wanted to hang out with me and it wasn't just a one night fling. I've been going steady with BEAN for a couple of months now.

Just before BEAN moved in permanently to my dev environment I had to find a way of removing all the remnants of boxes from my life (aka existing sites). It took me less than an hour. I created a new BEAN type and called it "box", I then wrote a little "drush scr" script which converted all of my boxes to BEANs and even updated my contexts to use the newly created BEANs. I hope neither bean or boxes finds my work on github. I chose github hoping neither of them would find my work and also because I don't want to maintain this as a module on d.o.

On a serious note - BEAN is awesome! If you haven't tried it, you really should. BEAN treats blocks as content, not config which is really useful for most sites. For new sites BEAN is a drop in replacement for core blocks or boxes making it super easy to get started. To learn more check out the docs.

If you're interested in seeing the full power of the BEAN module, and other cool stuff I've been working on recently, please comment on my DrupalCon session proposal - An Enterprise Scale Drupal Workflow. It will be a more technical version of my session at Drupal Business Days a couple weeks ago.

* "Full of beans" is phrase commonly used in Australia to describe energetic children.

Drupal in the Enterprise (aka Vote for my DrupalCon Session)

TL; DR: [spam]Please vote for my DrupalCon Denver proposal on Drupal workflows in the enterprise.[/spam]

For the last few months I've been working for Technocrat on a new Drupal based site for the Insurance Australia Group's Direct Insurance brands. The current sites are using Autonomy Teamsite.

The basics of the build are relatively straight forward, around 1000 nodes, a bunch of views and a bit of glue to hold it all together. Where things get complicated is the workflow. The Financial services sector in Australia is subject to strict control of representations being made about products. The workflow system needs to ensure IAG complies with these requirements.

During the evaluation we found that generally Drupal workflows are based around publishing a single piece of content on the production site. In the IAG case a collection of nodes need to be published as a piece of work, along with a new block. These changes need to be reviewed by stakeholders and then deployed. This led us to build a job based workflow system.

We are using the Features module to handle all configuration, deploy for entities and some additional tools, including Symfony, Jenkins and drush to hold it all together.

I've proposed the session for Drupal Downunder in January and will refine the session based on feedback from there in preparation for Denver. If you want to learn more about Drupal Workflows in the Enterprise, please vote for my session.

Drush Make and Module Dependencies

Drush make is a wonderful tool for constructing Drupal platforms. A lot of Drupal developers are used to adding a list of modules, a few libraries and theme or 2 then running drush make to build their platform. It all seems pretty easy. What if I told you module developers could make things even easier for site builders?

Some contrib modules depend on third party libraries, and due to various reasons they can't always be stored in git repositories on drupal.org and included in the module release. To solve this problem module developers can include a .make file for their module. Drush recursively processes make files, so the module make file would be processed once found by drush make.

A good example of where this could be useful is the SMTP module, which depends on the LGPL licensed PHPMailer library. The module also requires a patch to be applied to the library, which drush make can apply for us. The following .make file could be included in the SMTP module as smtp.make:

core = 6.x
api = 2

libraries[phpmailer][download][type] = "get"
libraries[phpmailer][download][url] = "http://downloads.sourceforge.net/project/phpmailer/phpmailer%20for%20php5_6/Previous%20Versions/2.2.1/phpMailer_v2.2.1_.tar.gz"
libraries[phpmailer][download][md5] = "0bf75c1bcef8bde6adbebcdc69f1a02d"
libraries[phpmailer][directory_name] = "phpmailer"
libraries[phpmailer][destination] = "modules/contrib/smtp"

libraries[phpmailer][patch][drupal-compatibility][url] = "http://drupalcode.org/project/smtp.git/blob_plain/2acaba97adcad7304c22624ceeb009d358b596e3:/class.phpmailer.php.2.2.1.patch"
libraries[phpmailer][patch][drupal-compatibility][md5] = "2d82de03b1a4b60f3b69cc20fae61b76"

Now when the SMTP module is included a normal drush make file it will be downloaded, the PHPMailer library will be downloaded and patched ready for use.

Unfortunately there are some limitations to this approach. Firstly it assumes that the SMTP module will be installed under the modules/contrib directory, which is accepted best practice, but may not suit everyone's needs. When I tested this with the current stable version of drush make (6.x-2.2) it failed, and drush make 6.x-3.x from git needed to be patched. Hopefully a fix for this can be backported to the 6.x-2.x branch and included in a future release.

Update: I have posted the make file for the SMTP module as patch in issue #1159080.

Help a Drupal Geek Earn his Way to DrupalCon Chicago

I really want to attend DrupalCon Chicago, which kicks off in just over 4 weeks. The problem is that since DrupalCon Copenhagen business has been pretty quiet and so I find that I can't really afford to fund it myself. After deciding I had to be in Chicago I got creative about how to make it happen. The buy a line project was born.

Instead of just asking people to kick in some cash to get me to Chicago, I felt it was only right to earn my keep. People can buy a line of code, or sentence of documentation for Drupal. All code and docs created will be contributed to drupal.org. Buyers are free to specify where the lines are to be contributed, or leave me to decide. I'm looking forward to writing some of the lines on the Drupal Bus.

Recently I have been working on porting the UUID module to Drupal 7. I hope to get this module into Drupal 8 core. To make this happen I have to be in Chicago! Improvements to UUID will mean that content can be packaged up and moved around like configuration can be using the Features module.

All buy a line issues will be tagged so people can watch my progress. The first lines of code have been contributed to the getID3() module, so Drupal Commons can be installed by Aegir.

Thanks to everyone who has contributed so far. I have almost covered the DrupalCon ticket I bought from the Gizra team.

Please consider buying a line (or more) to help get this Drupal geek to Chicago. This is a great way of getting a module ported to Drupal 7, better documentation or even just a bug fixed. I have a decent track record of contributing to the project.

When deciding how many lines to buy, think about this - if I don't make it to Chicago, who will lock themselves out of their hotel room at 4am - naked!

Looking Back at Drupal Downunder

I spent the weekend at Drupal Downunder in Brisbane. The venue was excellent. I'm a fan of not using "traditional" venues for conferences, to help make them even more memorable for attendees.

I managed to catch up with a bunch of people. The relaxed feel about the event was great. Most conferences I've attended recently have either been large or I've helped organise them, this time I could relax and enjoy.

On the Saturday I presented Building Distributions with Drupal 7, which had a small turn out as I was up against Josh Koenig and his Pantheon presentation. My presentation was hampered by lack of internet connectivity, but I think it went well. I used Lego, Duplo and Quatro blocks to demonstrate the evolution of Drupal distros.

Saturday night involved a pub crawl with various DDU and LCA folks. The highlight of the crawl was the Mana Bar, which is a gamers bar, that has a good collection of retro consoles and games on display.

I spent a fair bit of Sunday in the hallway track. I discussed the D7 port of UUID with Dries, which helped confirm the direction I was heading with it. Several people wanted to discuss my $100 Drupal site blog series. I also gave my Horizontally Scaling Drupal presentation, which was very well attended. Unfortunately due to people torrenting there was no usable internet access for my presentation. I had to skip the post event BBQ so I could fly back to Melbourne.

The lack of mobile signal and wifi made it frustrating to prepare and present. I would have liked to have seen an inclusive social event organised on the Saturday night. Overall I really enjoyed DDU and the organisers are to be congratulated. The vegetarian food options were excellent.

Thanks for Four Kitchens for funding me to get to DDU. I have just started contracting with them, so I really appreciated them covering my trip.

Keyword Bookmarking

When doing development work, from time to time it is handy to be able to look up documentation. Bookmarking manuals is handy, but often you still need to search for the function you're after. Firefox, and possibly other browsers (not Chrome or Chromium), allows you to setup a keyword bookmark linked to a search.

I've setup a few search bookmarks for development resources. This is how I've done it:

  1. Select Bookmarks > Organise Bookmarks... from the menu.
  2. Right click on the bookmarks menu (or any folder) on the left pane
  3. Select New Bookmark... from the context menu
  4. Drupal bookmark example
    Fill in the information for the bookmark, the import piece is the keyword, that will allow us to search.
  5. Click save and return to the browser

Now when we want to search the Drupal 7 API, we can just type "dapi Example Drupal API search in location bar

Now we should see the appropriate page from the Drupal API documentation.

Example Drupal API page

The same method can be used for other PHP web app developer resources, here are some which I'm using.

I could have implemented this using OpenSearch plugins, but that requires changing the search provider every time I want to look for something. By using keyword bookmarks I just type the keyword and the search term into the location bar.

Feel free to share your keyword bookmarks in the comments.

$100 Drupal Site Series: Part 7 - Wrapping it Up

Thanks to everyone who read the posts in my $100 Drupal site series. Today I will be responding to some of the points people have raised in comments and via email as well as adding a few closing comments.

Undervaluing Labour

Some have suggested that the only way to make a venture like this work is to work for a few dollars an hour. I completely disagree with that! If you are building every project from scratch and only charging your clients 100USD, you will be working for peanuts, but I'm not advocating that model. I'm encouraging people to rethink how they manage their development workflow. Although there are initial costs in learning new tools, over time you will end up spending less time on site builds and so increase your profits.

$100 is too Cheap

I agree that 100USD is very cheap for a high quality Drupal site and in most western markets it is probably too cheap. Sure you can do it and make the profit on the margin, but you have to sell a lot of sites to recover your initial investment. The "$100 Website" can be a useful sales pitch. Don't charge 100USD per site if the market will happily pay 5 or 10 times that. It doesn't matter if you are charging 10USD per site or 250kUSD per site, the same basic rules apply - understand your client's requirements and know the market.

There is a growing list of freemium services out there too, including Drupal Gardens and WordPress.com. Depending on your business model you may want to have a basic freemium offering.

What Does the Competition Offer?

Investigate what the competition is offering. There is a large market for hosted CMSes these days, go see what some of them are doing. What do you think they are doing right? What do you think they lack or could do better? A quick list of services I'd recommend you check out are (in alphabetical order):

I'd recommend spending some time searching for hosted CMS solutions. Sign up for the free or trial services and see what they're like.

Do I Need a lot of Money to do this?

Although in the Resources and Infrastructure post I outlined the positions I thought your team needed to make this happen, it wasn't a list of must haves. You need to figure out what works with you. It would be possible for a couple of switched on people to do this as a basement startup, so long as you have the skills and connections to get everything you need in place. If you can only drive a server using cPanel, then you need to find a sysadmin. If you can't even draw stick figures, then you will need to hire a designer. Your staffing costs are really going to dictate how much money you will need to get this up off the ground.

Why did you do this?

I wanted to put the idea out there. I wanted to see how people would react. It wasn't that long ago that people could build a profitable business selling websites built using Dreamweaver, and some people still do, but the market is changing, so too is the Drupal market.

For some time I have been thinking about how you'd develop a low cost Drupal based hosted CMS solution. There are 2 main reasons why I haven't just gone and built it already. The primary reason is I hate being on call and running a hosting service such as this requires me to never be out of range of a 3G tower for more than 30 minutes, customers won't accept that the server crashed 15 minutes after I hoped on a flight to the US or Europe. Secondly building such a solution takes time and I have a family to feed, I don't think my landlord would cop me not paying the rent until this thing started to turn a buck.

I have very consciously put enough information into this series to allow someone to head off in the right direction. At the same time I've held back on some of my execution specifics, because if I was to go build something like this I want to have some things which make my service unique.

I was hoping to present a session at DrupalCon Chicago on this topic, but I found out yesterday that my proposal hasn't been accepted. As I understand it, there will be a small number of sessions announced sometime in the next 2 weeks, but I'm not holding out much hope of being selected then. There is always London.

Can you Build this for me? / I need Help!

If you are serious about building a service like this or using some of the tools I've discussed, I'd be happy to talk to you. I have about a decade's worth of experience running my own business and developing web apps. I have offered training and consulting around many of the topics I have discussed in this series.

So neither of us waste our time, I will be up front about how I see things working on my end. I expect to be paid for my time, I'm happy to take some equity, but I've got bills to pay. I have put a lot of thought and energy into this, so I am very unlikely to sign a contract which gives you ownership of my IP. If you can live with the above, then please contact me.

It didn't Work for me

Sorry that just the way things go in business sometimes. Not everything I've tried over the years has worked either. Learn from the failure and try again, maybe doing something completely different.

Disclaimer: Don't sue me if this doesn't work out, do your own research and seek professional advice before acting on anything on this site.

Will you Write More on these Topics?

Maybe. I will probably turn some of the content from Horizontally Scaling Drupal workshops and talks into blog posts, and possibly a book. I tend to blog when I feel passionate about something. Subscribe to my RSS feed, or follow me on twitter to find out what I'm working on.

In the mean time, I'd recommend you subscribe to the following blogs / follow these people on twitter:

I welcome comments, feel free to leave one below.

$100 Drupal Site Series: Part 6 - Business Considerations

During this series on creating a profitable business around the concept of building Drupal sites for $100 I have attempted to demonstrate that there is a viable business model here. I don't believe it is a business that will suit everyone and nor do I believe every developer will want to work on such a project, but for some this will be an excellent opportunity. Today I will cover some of the things that I think you should consider before investing too much in this business model. Some of this is just basic business sense which isn't specific to this project.

Dollars and Sense

Oscar Wilde once wrote "What is a cynic? A man who knows the price of everything and the value of nothing". If you want to build this type of business, be frugal, but not a Scrooge. Generally a good developer will cost you more in salary than an average one, but the good developer will work out cheaper in the longer term. A similar thing goes for hosting, avoid Virtuozzo based VPS and look for someone offering the more expensive Xen or KVM based platforms, they are less likely to oversell capacity. At the same time keep an eye on the markets you are buying services in to ensure you are always getting the best value for money.

Recognise when you have to pay for something. Spending a little now might save you a lot in the long run.

In House vs Outsourcing

It makes sense to outsource some services, for example email. You want to focus on offering a high quality Drupal driven SaaS, having to support email too is a lot of hassle, use Google Apps for Domains or similar service.

Some things are better performed in house, such as design and themeing. There are businesses around who offer cheap PSD to Drupal theme conversion services, but these services usually cut corners which will cost you more in the longer term. Having someone in house means that they can learn from others on your team and do things the right way for your business.

Pricing

Although the theme of this series is "$100 Drupal site", that doesn't mean every site you sell should be $100. You need to research your target market/s and make sure you are pricing your product/s appropriately. I would seriously consider offering 3 levels of service, each level should offer more options, bandwidth and storage. Some customers will be drawn by the initial $100 price tag, but when they see the feature list, the $250 product might be more appealing. Give customers a sense of choice.

Options and Up Selling

Find opportunities to sell extras to your clients. Not everything needs to be included in the base level package. I discussed enhanced support offering in my previous post, which could provide additional revenue.

Most of the clients who sign up for this service will have no interest in paying for a custom theme and/or development, but once you have them through the door you have more chance of selling such extras to them. Find the higher traffic clients and connect with them, see if they want more. The price jump is likely to be significant, but if they can see value in it, they may pay for it.

Domain Names

Domain names is a great opportunity to generate extra revenue. By default customers should get biz-name.example.net, and charge them a fee if they want to use another domain, such as mybiz.com. Most people know that GoDaddy sells domains for around 10USD, while Melbourne IT charge around 75USD. Sign up for a reseller account with one of various domain registrars and offer customers domains directly from your service. If a customer brings their own domain charge them a fee, if they buy the domain through you advertise that you waive the setup fee, but then include it in the pricing of the domain name.

Partners

Seek out partners. If you can find a company which offers a service which is a good fit with your business, work out a deal with them. Be it bulk licensing, reseller, commissions, find something that works for both parties. Your customers can benefit from such arrangements too.

Giving Back

Previously I mentioned that you will be benefiting from the great work of the Drupal community, you should acknowledge this benefit by contributing back to the community where it is appropriate. Not only does this help build the profile of your business in the community, it can reduce your maintenance workload. For example if you have a patch which fixes a bug or adds generically useful functionality to a module, push it back up stream, so you don't have to maintain the patch. Consider having a budget for sponsoring community events to help build good will.

Data Exports

Allow customers to export their site and go host it with someone else. This might sound counter intuitive, but if they are just a base package customer and you are hosting them, they have paid you. If they are only 2 months into 12 month service, which should be non refundable, then let them take their site, that frees up server resources. It is also the ethical thing to do, don't make your money because people are locked into your service, they will eventually resent you for it.

Licensing

Drupal itself is licensed under the terms of the GPLv2 (or later) with some contrib modules depending on GPL compatible code. If you are contributing code back to drupal.org it must be under the terms of the GPLv2. You could choose to offer the non PHP parts of your code under CC-BY with an attribution in the footer, you could release your features under the terms of the AGPLv3. These are business decisions you must make in the context of the rest of your business.

Pay for Expert Advice

There are times when you need an expert. Get a lawyer to check your Terms of Service and any significant contracts. Use an accountant to get your financial affairs right from the start. If your servers are performing poorly and your Sys Admin can't work it out, pay for someone who can. Sometimes it is better to pay for something than trying to learn how to do it yourself.

Share

Blog about your experiences, share the knowledge. I'm not advocating putting your entire business plan online, but discuss problems you've solved, code you've created so others can benefit from your experiences. Don't be afraid to share, Scott Adams sums this up perfectly "Ideas are worthless. Execution is everything". I have nothing to fear in publishing this blog series, after all it is just my ideas.

What's Next?

This is the last substantial post in this series. I have tried to break it up into digestible chunks. Thanks for taking the time to read my posts and I welcome any comments you may have.

I plan to let things sit for a few days. Over the weekend I plan to review the comments posted and emails received as part of preparing a summary response and conclusion. Anything else I think of will get tacked onto that post.