<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>The wishli.st blog</title>
	
	<link>http://blog.wishli.st</link>
	<description>News and updates from wishli.st HQ</description>
	<lastBuildDate>Fri, 14 May 2010 09:35:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/wishli-st" /><feedburner:info uri="wishli-st" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>wishli-st</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Getting CodeIgniter to play nicely with Facebook</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/fyodgAuNWAw/</link>
		<comments>http://blog.wishli.st/getting-codeigniter-to-play-nicely-with-facebook/#comments</comments>
		<pubDate>Tue, 11 May 2010 15:48:24 +0000</pubDate>
		<dc:creator>oli</dc:creator>
				<category><![CDATA[for the geeks]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[libraries]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/?p=99</guid>
		<description><![CDATA[Here at Wishli.st we love Code Igniter.  It&#8217;s a light weight PHP framework which doesn&#8217;t get in your way, but provides some great library funcitonality right out the box, as well as a suite of debugging tools and all the other things that make code frameworks a good idea.
Getting CI and Facebook to play together [...]]]></description>
			<content:encoded><![CDATA[<p>Here at Wishli.st we love <a href="http://codeigniter.com/">Code Igniter</a>.  It&#8217;s a light weight PHP framework which doesn&#8217;t get in your way, but provides some great library funcitonality right out the box, as well as a suite of debugging tools and all the other things that make code frameworks a good idea.</p>
<p>Getting CI and Facebook to play together nicely has not been a smooth ride however, and we&#8217;ve still not nailed all of the problems we&#8217;ve had, but now that a few of the giants are slain, we thought it was time to share the love.</p>
<p>Timing is against us however, because we&#8217;re <span style="font-size: 13.3333px;">running against all the old Facebook API, not the new Open Graph stuff that was kicked off at F8. </span></p>
<p><span style="font-size: 13.3333px;">We know we&#8217;re going to have to rip out the guts of all the FB API call bits in a few weeks, but I&#8217;ll update that when we do (and get it working).</span></p>
<p>Huge props to <a href="http://twitter.com/elliothaughin">Elliot Haugin</a> for his <a href="http://www.haughin.com/code/facebook/">library</a>, that was a massive help in getting us started.</p>
<p>A few things up front, which might affect how you build:</p>
<ul>
<li><span style="font-size: 13.3333px;">We&#8217;re working on an FBML based facebook application (not iFrame)</span></li>
<li><span style="font-size: 13.3333px;">It&#8217;s an actual FB app, not a separate website using Facebook Connect. </span></li>
<li><span style="font-size: 13.3333px;">All of this should also apply to iframe base FB apps too, but I thought I&#8217;d better be clear. </span></li>
<li><span style="font-size: 13.3333px;">Facebook Connect is a different beast, and I&#8217;ve not played with it yet.</span></li>
</ul>
<p>If this is your first attempt at building a FB app, have a go with a single file of vanilla code to make Hello World first rather than inside a code framework &#8211; much easier to get the hang of what a Canvas URL is etc etc without having to worry about whether or not CI is getting in the way or it&#8217;s your FB set up.</p>
<p>We&#8217;re running a base install of CI 1.7.2, and the first thing we did was install <a href="http://www.haughin.com/code/facebook/">Elliot Haugin&#8217;s Facebook Connect library</a>.  We followed his instructions to install the library and set up the config in /applicaitons/config/facebook.php.</p>
<p>The bit about xd_receiver.htm is not relevant if you&#8217;re doing a FB app, rather than a Facebook Connect powered site, but do it anyway.</p>
<p>At this point we battled with FB for a little whilst trying to get the examples to work and failing miserably.  There were a few things we needed to do to make it work, namely replace the php wrapper, and add a bit of config to handle $_GET.</p>
<h2>Call the library correctly in the controller</h2>
<p>In our constructor we call</p>
<blockquote>
<p>$this-&gt;load-&gt;library(&#8216;facebook_connect&#8217;);</p>
</blockquote>
<p>We could also do this inside the index function but we needed to have the Facebook User&#8217;s ID available in the constructor, so did it early.</p>
<p>When we want to access the library we then do it like this..</p>
<blockquote>
<p>//<span style="font-size: 13.3333px;">to get the user&#8217;s Facebook ID<br />
</span><span style="font-size: 13.3333px;">$this-&gt;facebook_connect-&gt;user['uid']</span></p>
<p><span style="font-size: 13.3333px;">//</span><span style="font-size: 13.3333px;">to find if this application has permission to access the user&#8217;s email address<br />
</span><span style="font-size: 13.3333px;">$this-&gt;facebook_connect-&gt;client-&gt;users_hasAppPermission(&#8220;email&#8221;); </span></p>
<p><span style="font-size: 13.3333px;">//To run some FQL</span></p>
<p>$this-&gt;facebook_connect-&gt;client-&gt;fql_query(&#8220;SELECT email FROM user WHERE uid=12345678&#8243;);</p>
</blockquote>
<h2>The PHP Wrapper</h2>
<p>The Facebook PHP wrapper used to change reasonably frequently, and to  make things that little bit harder wasn&#8217;t version managed, so I don&#8217;t know what version we&#8217;re currently (or ever have been) using.</p>
<p>When Elliot&#8217;s examples didn&#8217;t work, we tried dropping the latest facebook.php and facebookapi_php5_restlib.php into /application/libraries/facebook-client and things got a lot better.</p>
<p>We just downloaded the latest ones from <a href="http://wiki.developers.facebook.com/index.php/PHP">http://wiki.developers.facebook.com/index.php/PHP</a> though these will now not be available because of the Open Graph updates.</p>
<h2>$_GET</h2>
<p>FB throws you lots of stuff in the URL, and whilst we&#8217;d love to make use of it (track referrers etc) we had to stop it to make CI play nicely. FB will stuck things like ?id=2579980995&amp;ref=ts on the end of your URLS, and then CI will 404.</p>
<p>To ditch all the information being passed by get we added a hook.  Basically every request to the app now gets it&#8217;s $_GET ditched.  Eventually we&#8217;ll handle this more gracefully. In /application/hooks we created Querystring.php with the following content</p>
<blockquote>
<p>&lt;?php</p>
<p>class Querystring  {</p>
<p>public function rewrite () {</p>
<p>$_GET = array(); <span style="font-size: 13.3333px;">}</span></p>
<p>}</p>
<p>?&gt;</p>
</blockquote>
<p>An at this point, we were up and running.  We need to construct purely directory based URLs, such as http://apps.facebook.com/wishli-st/wishlist/100001071971681 and not http://apps.facebook.com/wishli-st/wishlist/?fbid=100001071971681  but thats just good URL structures anyway right?</p>
<p>All will have to change with Open Graph becomes the only way to connect, but it should just be a case of switching out th PHP wrappers.</p>
<h2>A multi-site tangent</h2>
<p>We have also implemented a very rough form of multi-site config, just to make our lives easier.  Because Facebook relies on callback URLs, developing locally on your machine is tricky, and we&#8217;ve ended up with an app per developer.</p>
<p>The problem being that each app needs it&#8217;s own config, and with a junior team only just getting to grips with version management, people kept standing on each others toes and checking their personal config in over the live app.   The fix &#8211; more education, but also a &#8220;contact aware app&#8221;, which switches config settings depending on what domain it finds itself sitting on.  This is all pretty rough at the moment, but is up and running.</p>
<p>It works by detecting the host that the application is running on ($_SERVER['HTTP_HOST']) and setting a site wide constant based on it.  This constant is then used in config.php, database.php and facebook.php to switch between config arrays.  We also define a boolean constact for &#8220;quick switching&#8221; so we can turn logging on in dev, tracking on in live etc etc.</p>
<p>We made changes to the following files:</p>
<p><strong>/index.php (the root index file)</strong></p>
<p>Added the following lines near the top (domains changed to protect the innocent)</p>
<blockquote>
<p>switch ($_SERVER['HTTP_HOST']) {</p>
<p>case &#8220;live.wishli.st&#8221;:</p>
<p>define(&#8217;site_identifier&#8217;, &#8216;live&#8217;, TRUE);</p>
<p>break;</p>
<p>case &#8220;test.wishli.st&#8221;:</p>
<p>define(&#8217;site_identifier&#8217;,'test&#8217;, TRUE);</p>
<p>break;</p>
<p>case &#8220;dev1.wishli.st&#8221;:</p>
<p>define(&#8217;site_identifier&#8217;,'dev1&#8242;, TRUE);</p>
<p>break;</p>
<p>case &#8220;dev2.wishli.st&#8221;:</p>
<p>define(&#8217;site_identifier&#8217;,'dev2&#8242;, TRUE);</p>
<p>break;</p>
<p>}</p>
<p>if (site_identifier == &#8216;live&#8217;)</p>
<p>{</p>
<p>//we are in live!</p>
<p>define(&#8216;SITE_LIVE&#8217;, TRUE);</p>
<p>}</p>
<p>else</p>
<p>{</p>
<p>//somewhere else &#8211; could be dev or indeviduals test</p>
<p>define(&#8216;SITE_LIVE&#8217;, FALSE);</p>
<p>}</p>
</blockquote>
<p>We can now use &#8217;site_identifier&#8217; in case switches as follows:</p>
<p><strong>/application/config/config.php</strong></p>
<p>-to switch the base_url and the the logging levels (base_url example shown only)</p>
<blockquote>
<p>//default to test, so if something goes wrong we don&#8217;t screw live</p>
<p>$config['base_url']	= &#8220;http://apps.facebook.com/xxxxxxx/&#8221;;</p>
<p>switch (site_identifier) {</p>
<p>case &#8220;live&#8221;:</p>
<p>$config['base_url']	= &#8220;http://apps.facebook.com/wishli-st/&#8221;;</p>
<p>break;</p>
<p>case &#8220;test&#8221;:</p>
<p>$config['base_url']	= &#8220;http://apps.facebook.com/xxxxxxx/&#8221;;</p>
<p>break;</p>
<p>case &#8220;dev1&#8243;:</p>
<p>$config['base_url']	= &#8220;http://apps.facebook.com/yyyyyyyy/&#8221;;</p>
<p>break;</p>
<p>case &#8220;dev2&#8243;:</p>
<p>$config['base_url']	= &#8220;http://apps.facebook.com/zzzzzzz/&#8221;;</p>
<p>break;</p>
<p>}</p>
</blockquote>
<p><strong>/application/config/database.php</strong></p>
<p>-to switch between database config sets</p>
<blockquote>
<div>//default to test</p>
<p>$active_group = &#8220;test&#8221;;</p>
<p>// now choice correct one</p>
<p>switch (site_identifier) {</p>
<p>case &#8220;live&#8221;:</p>
<p>$active_group = &#8220;live&#8221;;</p>
<p>break;</p>
<p>case &#8220;test&#8221;:</p>
<p>$active_group = &#8220;dev&#8221;;</p>
<p>break;</p>
<p>case &#8220;dev1&#8243;:</p>
<p>$active_group = &#8220;dev1&#8243;;</p>
<p>break;</p>
<p>case &#8220;dev2&#8243;:</p>
<p>$active_group = &#8220;dev2&#8243;;</p>
<p>break;</p>
<p>}</p>
<p>And then define an active group for each environment</p>
<p>$db['dev1']['hostname'] = &#8220;xxx&#8221;;</p>
<p>$db['dev1']['username'] = &#8220;yyyy&#8221;;</p>
<p>$db['dev1']['password'] = &#8220;zzzz&#8221;;</p>
<p>$db['dev1']['database'] = &#8220;aaaaaa&#8221;;</p>
<p>&#8230;etc etc</p>
<p>$db['dev2']['hostname'] = &#8220;bbb&#8221;;</p>
<p>$db['dev2']['username'] = &#8220;ccc&#8221;;</p>
<p>$db['dev2']['password'] = &#8220;ddd&#8221;;</p>
<p>$db['dev2']['database'] = &#8220;eee&#8221;;</p>
<p>/application/config/facebook.php</p>
<p>- the same trick as above &#8211; change the config array based on the switch.</p>
<p>/default is test</p>
<p>$config['facebook_api_key'] = &#8216;aaaaa&#8217;;</p>
<p>$config['facebook_secret_key'] = &#8216;bbbbb&#8217;;</p>
<p>// now switch based on site_identified</p>
<p>switch (site_identifier) {</p>
<p>case &#8220;live&#8221;:</p>
<p>$config['facebook_api_key'] = &#8216;ccccc&#8217;;</p>
<p>$config['facebook_secret_key'] = &#8216;dddd&#8217;;</p>
<p>break;</p>
</blockquote>
<p>&#8230;etc etc</p>
<p>Eventually I&#8217;ll clean this up and make it into a CI mod of some kind, for the moment, it&#8217;s how we roll.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/getting-codeigniter-to-play-nicely-with-facebook/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/getting-codeigniter-to-play-nicely-with-facebook/</feedburner:origLink></item>
		<item>
		<title>Leaving gifts for Gordon Brown</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/wy7Qzp5Z0_E/</link>
		<comments>http://blog.wishli.st/leaving-gifts-for-gordon-brown/#comments</comments>
		<pubDate>Tue, 11 May 2010 08:54:39 +0000</pubDate>
		<dc:creator>oli</dc:creator>
				<category><![CDATA[company]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/?p=95</guid>
		<description><![CDATA[With all of the excitement here in the UK about the election it&#8217;s easy to forgot that politicians are people too, and that all people like presents.  The big question is what do you buy the Prime Minister as a leaving present?
Luckily the man himself seems to have provided the answer.  Imagine our surprise when [...]]]></description>
			<content:encoded><![CDATA[<p>With all of the excitement here in the UK about the election it&#8217;s easy to forgot that politicians are people too, and that all people like presents.  The big question is what do you buy the Prime Minister as a leaving present?</p>
<p>Luckily the man himself seems to have provided the answer.  Imagine our surprise when we found this little gem on Wishlist last night:</p>
<p><a href="http://blog.wishli.st/wp-content/uploads/2010/05/Screen-shot-2010-05-11-at-09.48.14.png"><img class="aligncenter size-full wp-image-96" title="GB's wishlist" src="http://blog.wishli.st/wp-content/uploads/2010/05/Screen-shot-2010-05-11-at-09.48.14.png" alt="Gordon Brown's Wishlist screenshot" width="611" height="389" /></a></p>
<p>That&#8217;s right, the big man has clearly made a choice and is preparing to go, queuing up the things that he&#8217;ll need on the next stage of his life including <a href="http://wishli.st/490">The Backpacker&#8217;s Bible Revised Edition</a>, <a href="http://wishli.st/489">Just for Men Shampoo-in Hair Colour Dark Brown</a>, <a href="http://wishli.st/484">The Bogleheads&#8217; Guide to Retirement Planning </a> and <a href="http://wishli.st/485">Hardwood WideBoy Deckchair</a>.</p>
<p>You can find his full list <a href="http://apps.facebook.com/wishli-st/wishlist/100001071971681">over on the Facebook app</a>, we&#8217;ve even included a special tab to celebrate our first celebrity wishlist.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/leaving-gifts-for-gordon-brown/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/leaving-gifts-for-gordon-brown/</feedburner:origLink></item>
		<item>
		<title>Making use of Facebook’s fb:typeahead-input</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/8axepRMJ6N0/</link>
		<comments>http://blog.wishli.st/making-use-of-facebooks-fbtypeahead-input/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 18:57:23 +0000</pubDate>
		<dc:creator>oli</dc:creator>
				<category><![CDATA[for the geeks]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[fbml]]></category>
		<category><![CDATA[geek]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/?p=81</guid>
		<description><![CDATA[One of the things we&#8217;ve got a bit over excited about this week is the new auto-suggest present lister we&#8217;ve rolled into the Wishli.st FB app.  It means that if we already know about a gift, you don&#8217;t need to do all the leg work to add it, just start typing it&#8217;s name, pick [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things we&#8217;ve got a bit over excited about this week is the new auto-suggest present lister we&#8217;ve rolled into the Wishli.st FB app.  It means that if we already know about a gift, you don&#8217;t need to do all the leg work to add it, just start typing it&#8217;s name, pick it off the list, and away you go.</p>
<p>The magic is all done by the FBML tag  tag, which is sadly not brilliantly documented.  However, after lots of Googling and experimenting, we got it working, and here&#8217;s how&#8230;</p>
<p>There are three bits</p>
<ol>
<li>The backend to generate the data for auto populating with</li>
<li>The FBML selector (this is what the user will see)</li>
<li>The backend to handle the request once somebody selects something</li>
</ol>
<h2>The backend&#8230;</h2>
<p>Needs to produce an array of id&#8217;s and names.  The id will be set as the value that the form submits, the name will be the bit people see.  We&#8217;re pulling data about products, so we did a quick database call to get unique names (there are lots of duplicates) and then format this up as a nice flat array:</p>
<blockquote><p>SELECT distinct (name), id FROM [tablename] group by name order by name</p></blockquote>
<p>We threw this to an array called $names.</p>
<h2>The FBML selector&#8230;</h2>
<p>Is actually really simple, despite what the documents might make you think. Note the &lt;fb:fbml tag which you have to include (and specify this version) or it doesn&#8217;t seem to work.</p>
<p>I take the $names array and iterate through adding an option for each product like so&#8230;</p>
<blockquote>
<div id="_mcePaste">&lt;form action=&#8221;path/to/handler&#8221; method=&#8221;post&#8221;&gt;</div>
<div id="_mcePaste">&lt;fb:fbml version=&#8221;1.1&#8243;&gt;</div>
<div id="_mcePaste">&lt;fb:typeahead-input name=&#8221;name&#8221; autocomplete=&#8221;off&#8221; size=&#8221;50&#8243;&gt;</div>
<div id="_mcePaste">&lt;?php foreach ($names as $item){?&gt;</div>
<div>&lt;fb:typeahead-option value=&#8221;&lt;?php echo $item['id'];?&gt;&#8221;&gt;&lt;?php echo $item['name'];?&gt;&lt;/fb:typeahead-option&gt;</div>
<div id="_mcePaste">&lt;?php } ?&gt;</div>
<div id="_mcePaste">&lt;/fb:typeahead-input&gt;</div>
<div id="_mcePaste">&lt;/fb:fbml&gt;</div>
<p>And FB will take care of turning the FBML into HTML and JavaScripting it up nicely.</p></blockquote>
<h2>The backend handler&#8230;</h2>
<p>Should be really simple, but there are a few edge cases, namely what you do when somebody managed to fill in your lovely autosuggestor with something new (who would do such a thing?).</p>
<p>Because we&#8217;re passing a number (the id) as the value, if what it is passed is not a number, we know that it wasn&#8217;t an option, and then we can do something with the input they did enter.  Here&#8217;s our actual code (minus a few secrets):</p>
<blockquote><p>function addbymagicsuggest()<br />
{<br />
$id = $this-&gt;input-&gt;post(&#8216;name_val&#8217;);<br />
$name = $this-&gt;input-&gt;post(&#8216;name&#8217;);<br />
if(is_numeric($id)){<br />
// they submitted something we know about<br />
echo &#8220;thanks for submitted item&#8221;.$id;<br />
}else{<br />
//handle the new item<br />
echo &#8220;you submitted&#8221;.$name;<br />
}<br />
}</p></blockquote>
<p>And amazingly thats it &#8211; you&#8217;d never believe it was that simple from the docs, but it really is.  Here&#8217;s a picture in action to prove it.</p>
<p><a href="http://blog.wishli.st/wp-content/uploads/2010/04/Screen-shot-2010-04-22-at-19.55.45.png"><img class="aligncenter size-medium wp-image-82" title="Autosuggest at work" src="http://blog.wishli.st/wp-content/uploads/2010/04/Screen-shot-2010-04-22-at-19.55.45-300x100.png" alt="Autosuggest at work" width="300" height="100" /></a></p>
<p><br style="clear:both;" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/making-use-of-facebooks-fbtypeahead-input/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/making-use-of-facebooks-fbtypeahead-input/</feedburner:origLink></item>
		<item>
		<title>The technologies that power wishli.st</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/uxiBB8dd-SM/</link>
		<comments>http://blog.wishli.st/the-technologies-that-power-wishli-st/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 09:04:34 +0000</pubDate>
		<dc:creator>oli</dc:creator>
				<category><![CDATA[for the geeks]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[shell script]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/?p=73</guid>
		<description><![CDATA[Almost all of my favourite posts over the last few years have been tech companies posting about what actually powered theirs sites and servers.   Reading their stuff has really helped me get my head around how to do some really really complex things, as well as how to dodgy a few bullets in the [...]]]></description>
			<content:encoded><![CDATA[<p>Almost all of my favourite posts over the last few years have been tech companies posting about what actually powered theirs sites and servers.   Reading their stuff has really helped me get my head around how to do some really really complex things, as well as how to dodgy a few bullets in the really simple stuff too (have a look at how Flickr <a href="http://code.flickr.com/blog/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/">serves up unique id numbers for example</a>.)</p>
<p>So, after being here at wishlil.st for a little over a month, I thought it was time to get some of the little things we&#8217;ve done out into the world, and maybe help a few other people.  Developing Facebook applications has it&#8217;s own interesting infrastructure problems, and whilst we&#8217;ve not solved everything (there&#8217;s no equivalent of using a local MAMP install as I would for website development for example) we have solved a few things.</p>
<h2>Using a code framework</h2>
<p>We&#8217;ve ported all of our facebook app across to run on top of the amazing <a href="http://codeigniter.com/">CodeIgniter</a>.  As a PHP house it was all to easy to hack about in our own handrolled structure, but there comes a time to bite the bullet and use an MVC structure.  We chose CI because I had worked with it in the past, and loved the way it didn&#8217;t get under your feet.   It&#8217;s lightweight, and nicely flexible, but comes with lots of freebies for developers.</p>
<p>Getting CI to play nicely with FB will get a separate post later (you have to set lots of config right to stop FB killing your app with it&#8217;s crazy request strings) but <a href="http://www.haughin.com/code/facebook/">the library from Elliot Haughin</a> was a good starting point.  We&#8217;ve hacked it about a little and replaced it&#8217;s core FB wrapper with the latest one, but it got us off the ground.</p>
<h2>Version management</h2>
<p>We started with a Subversion repository on <a href="http://www.beanstalkapp.com">Beanstalkapp.com</a> running a trunk for live, and a branch for development work.  Once we got Coda integrated with SVN and SFTP (you have to edit on a &#8220;live&#8221; server to develop FB apps) it was all running pretty smoothly.  I build a couple of deployment scripts, and all ways well until we had to merge the dev branch back into live, and then the version management hell started.  Merging is hard, should be hard, and will always be hard, but it shouldn&#8217;t be this hard.  We bit another bullet, and moved to Mercurial.</p>
<p>We&#8217;d heard a lot about it over the last few months and it was a quote from Joel Spolsky that encouraged us to go for it&#8230;</p>
<blockquote><p>Or, to put it another way, I’d go back to C++ before I gave up on Mercurial. -Joel Spolsky</p></blockquote>
<p>In the end it wasn&#8217;t that hard.  We&#8217;ve taken up a hosted Mercurial account with <a href="http://www.fogcreek.com/Kiln/">Kiln</a> to get started (I&#8217;ll in-house this at some point) with a single repository for live.  We&#8217;ve branched this for dev.</p>
<p>Importing SVN to Mercurial turned out to be reasonably easy.  You create your local clone of the live repository (which is empty), run an &#8220;svn export&#8221; to flatten you SVN trunk of it&#8217;s history, and then &#8220;hg add&#8221; &#8220;hg commit&#8221; and &#8220;hg push&#8221;.  Job done.  The <a href="http://hginit.com">HGInit</a> guide is a good starting place too.</p>
<p>So now we bug fix live on the equivalent of trunk, and &#8220;push&#8221; branches back up to the trunk when we&#8217;re ready to go live.  Command line all the way, but that&#8217;s just how we roll.</p>
<h2>Deployment scripts</h2>
<p>One of the big lessons I learned, and Flickr&#8217;s notes re-enforced as the need for easy deployment.  Gone are the days of me spending 3 days deploying code into a live environment, living on coffee and Haribo for a week and risking it all.</p>
<p>You really must be able to deploy the majority of your environment from a single script, and thus a single mouse click.</p>
<p>At the moment we do it in the easiest dirtiest way possible, we &#8220;hg clone&#8221; the repository into a fresh directory, and then symlink to it from the Apache document root.  You don&#8217;t even need to restart Apache (but it&#8217;s a good idea).  It&#8217;s a single command (./push_live.sh) and takes about 30 seconds.</p>
<h2>A dose of monitoring</h2>
<p>Having an idea of what is trending on your server is really really important.  I love <a href="http://munin-monitoring.org/">Munin</a> for it&#8217;s chronological view of the world, letter you see what has happened in the short term (why have we got 4 gigs more memory committed that 2 minutes ago) and whats going on over a more meaningful time frame (oh &#8211; we do this everyday about the same time &#8211; might be connected to a scheduled process).  Munin lets you be proactive, spotting things that are creaping up over time.  It&#8217;s also handy during a crisis.</p>
<div id="attachment_76" class="wp-caption aligncenter" style="width: 160px"><a href="http://blog.wishli.st/wp-content/uploads/2010/04/single.png"><img class="size-thumbnail wp-image-76" title="Hourly" src="http://blog.wishli.st/wp-content/uploads/2010/04/single-150x150.png" /></a><p class="wp-caption-text">Oh man - what&#39;s going on?</p></div>
<div id="attachment_75" class="wp-caption aligncenter" style="width: 160px"><a href="http://blog.wishli.st/wp-content/uploads/2010/04/week.png"><img class="size-thumbnail wp-image-75" title="week" src="http://blog.wishli.st/wp-content/uploads/2010/04/week-150x150.png" alt="" /></a><p class="wp-caption-text">Oh no, it&#39;s ok.</p></div>
<p>Munin is a good partner to <a href="http://www.nagios.org/">Nagios</a>.  I&#8217;ve not got Nagios up and installed yet.  Munin lets you stop things going wrong, Nagios will tell when they have (and it&#8217;s a amazing how often you don&#8217;t know).</p>
<h2>Development scripts</h2>
<p>There are lots of things you end up doing during dev which can really benefit from a drop of scripting.  One we run several times a day on our personal instances, and every night on a schedule, is cloning our live database across to the development instances.  It&#8217;s not hard, in fact it&#8217;s a one liner really.  We run mysqldump to drop the database out to sql files, and then mysql &lt; dumpfile.sql to import it into the dev databases.  Call it and you can have a fresh new cut of live with all the crazy data people have sneaked past the filtering for you to play with.</p>
<h2>Backups</h2>
<p>Backing up is a pain in the neck, but so import it&#8217;s unreal.  Eventually I&#8217;d like to get to a point where we can deploy everything including server config form a central point, but until then we backup two things, the code and the data.</p>
<p>Database backups are a simple matter of mysqldump being run, and a little bit of tar, gzip and scp to bundle them up with the date and move them off site.  We keep an on site copy too for fast access though.</p>
<p>The live code is backed up using rsync to a mount point that is mounted before the rsync and unmounted afterwards (no accidental rm -rf).  Getting it to work well was a bit of a nightmare, and we only had FTP access to the backup space, but <a href="http://curlftpfs.sourceforge.net/">curlftpfs</a> came to the rescue letting us mount a remote ftp connection as a local mount.</p>
<h2>A bunch of silly things that save you time</h2>
<p>If you find yourself doing the save thing ten times a day, stop it, and script it.  You remove the chances of you screwing it up because you&#8217;re tired.  Here&#8217;s <a href="http://tldp.org/LDP/abs/html/">a handy guide to get you started</a>, and do remember to make yours scripts check their input before they run, kickout if something goes wrong, and log (so you can tell what went wrong)</p>
<p>Set yourself up  SSH keys between your trusted boxes and laptops.  Mistyping a password at 1am is frustrating, and sorting your passwords in a text file is worse.  It&#8217;s not hard , though it does vary between install types but <a href="http://bashcurescancer.com/setting_up_ssh_keys_for_access_without_password.html">Bush Cures Cancer</a> had a great guide.</p>
<p>We&#8217;ll write up some more detailed insights into some fo the stuff we&#8217;re doing with time, but if you&#8217;re stuck, drop us a line.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/the-technologies-that-power-wishli-st/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/the-technologies-that-power-wishli-st/</feedburner:origLink></item>
		<item>
		<title>7 Steps to Gift Nirvana</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/1irbbyZsr7A/</link>
		<comments>http://blog.wishli.st/7-steps-to-gift-nirvana/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 18:28:49 +0000</pubDate>
		<dc:creator>David Haywood Smith</dc:creator>
				<category><![CDATA[on gift giving]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/?p=56</guid>
		<description><![CDATA[A couple of weeks ago a friend of Oli&#8217;s &#8211; Meri Williams &#8211; suggested that there might be a scale of gift giving: from the perfect gift at the top down to the worst possible gift at the bottom. We rather liked that idea, here&#8217;s our attempt to elaborate.
As we wrote this post we noticed [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago a friend of Oli&#8217;s &#8211; <a title="Meri Williams" href="http://blog.meriwilliams.com/">Meri Williams</a> &#8211; suggested that there might be a scale of gift giving: from the perfect gift at the top down to the worst possible gift at the bottom. We rather liked that idea, here&#8217;s our attempt to elaborate.</p>
<p>As we wrote this post we noticed a few key factors including: thought, effort and money. The more thought you put into choosing a present (or effort put into making/finding one) the better. In many cases the more money spent the better too. However thought and effort will always trump money spent. Grandparents, for example, always appreciate home-made gifts and care little for how much has been spent.</p>
<p><strong>1. The &#8220;Halcyon&#8221; Gift</strong></p>
<p>Right at the top of the tree is gift giving nirvana: the perfect gift that you didn&#8217;t know you needed. A thoughtful and inspired choice that was appropriately priced. The halcyon gift is usually something you can use and appreciate time many times over. Perfect timing can also make a good present great &#8211; giving a gift when someone really needs a pick-me-up counts for a lot.</p>
<p>Examples include: a more expensive laptop or gadget (we&#8217;re thinking <a title="Expensive laptop - MacBook air" href="http://www.apple.com/macbookair/">Macbook Air</a> and <a title="iPod touch" href="http://www.apple.com/ipodtouch/">iPod touch</a>) than you would ever buy for yourself, a <a title="Mr Frosty" href="http://www.cutegadgets.co.uk/mr_frosty.htm">Mr Frosty</a> ice lolly maker that your kid can use all summer long to make delicious lollies, or even a delicious homemade cake!</p>
<p><strong>2. The &#8220;Decent&#8221; Gift</strong></p>
<p>A perfectly good gift that you will use and enjoy counts as a &#8220;Decent&#8221; gift. It misses the level of inspiration required to make it a &#8220;Halcyon&#8221; gift. It can also sometimes be a carefully chosen &#8220;Generic&#8221; gift. Most good presents fit in this category.</p>
<p>Examples include: <a title="Slanket" href="http://www.firebox.com/product/2249/The-Slanket">the Slanket</a>, most books, DVDs and computer games.</p>
<p><strong>3. The &#8220;Asked For&#8221; Gift</strong></p>
<p>The easiest way to get what you want is to ask for it. Of course, your requests have to be reasonable and presented in a friendly way. This type of gift lacks the suprise element required to reach higher levels but, despite that, it beats all of the lower levels!</p>
<p>Examples include: gifts bought from a <a href="http://j.mp/FBwishlist">wishlist</a>.</p>
<p><strong>4. The &#8220;Duplicate Decent&#8221; Gift</strong></p>
<p>The &#8220;Duplicate Decent&#8221; gift is a frustrating one. It is a well thought through present but you already have one and enjoy it! Clearly a good choice by the buyer but completely useless to the recipient. Half marks for effort.</p>
<p>Examples include: your <a title="Another Slanket" href="http://www.firebox.com/product/2249/The-Slanket">second Slanket</a>.</p>
<p><strong>5. The &#8220;Generic&#8221; Gift</strong></p>
<p>The result of a last minute panic the &#8220;Generic&#8221; gift is an uninspiring item that rouses little emotion in the recipient.</p>
<p>Examples include: Jeremy Clarkson books, socks, novelty gifts.</p>
<p>NB. Many &#8220;Generic&#8221; gifts are perceived as much better by the buyer than the recipient. For example: <a title="Name a star" href="http://www.iwantoneofthose.com/name-a-star/index.html">stars</a>, <a title="Lordship in a box" href="http://www.geniegadgets.com/gadgets_uk/laird-or-lady.html">lordships</a> and <a title="Oxfam goat" href="http://www.oxfam.org.uk/shop/oxfam-unwrapped-animal-lovers/OU4007LS">Oxfam goats</a>.</p>
<p><strong>6. The &#8220;Duplicate Generic&#8221; Gift</strong></p>
<p>One worse than a &#8220;Generic&#8221; gift is a generic gift that you have already been given! How many socks, <a title="Name a star" href="http://www.iwantoneofthose.com/name-a-star/index.html">stars</a> and <a title="Lordship in a box" href="http://www.geniegadgets.com/gadgets_uk/laird-or-lady.html">lordships</a> does a person really need!?</p>
<p><strong>7. The &#8220;Awkwardly Wrong&#8221; Gift</strong></p>
<p>This is without doubt the worst kind of gift. Imagine your grandmother spends an hour driving to the shops and after trawling round <a title="HMV" href="http://hmv.com/">HMV</a> and comes out with an Eminem box-set. The wasted time, effort and money make it a painful and embarrassing gift. One giveaway of an &#8220;Awkwardly Wrong&#8221; gift is that it&#8217;s virtually impossible to write a nice thank you letter without lying.</p>
<p>Examples include: a camel-skin bag from your mother-in-law or anything you just can&#8217;t stand whatsoever.</p>
<p>We think every gift ever bought fits into one of these categories (or did we miss a category?). It also seems that the higher up the scale you can get the better. We&#8217;re going to keep this in mind as we build <a title="wishli.st Facebook app" href="http://j.mp/FBwishlist">wishli.st</a>!</p>
<p>If you have two minutes &#8211; we&#8217;d love to hear the best and worst presents you&#8217;ve ever received!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/7-steps-to-gift-nirvana/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/7-steps-to-gift-nirvana/</feedburner:origLink></item>
		<item>
		<title>Tyne Twestival March 2010</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/Mp1lKqfJ6MA/</link>
		<comments>http://blog.wishli.st/tyne-twestival-march-2010/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 13:28:33 +0000</pubDate>
		<dc:creator>David Haywood Smith</dc:creator>
				<category><![CDATA[community]]></category>
		<category><![CDATA[charity]]></category>
		<category><![CDATA[newcastle upon tyne]]></category>
		<category><![CDATA[north east]]></category>
		<category><![CDATA[twestival]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/?p=46</guid>
		<description><![CDATA[The third Tyne Twestival was held last night in Newcastle at the Tyne Bar (just a short 1.5hr walk from our Gateshead office &#8211; woops!). wishli.st were out in force with the rest of our Difference Engine friends. Some of us shared a lift up from Middlesbrough thanks to Geogoer&#8217;s nifty ride sharing service!
It was great [...]]]></description>
			<content:encoded><![CDATA[<p>The third <a href="http://newcastle.twestival.com/">Tyne Twestival</a> was held last night in Newcastle at the <a href="http://www.thetyne.com/">Tyne Bar</a> (just a short 1.5hr walk from our Gateshead office &#8211; woops!). wishli.st were out in force with the rest of our <a href="http://differenceengine.eu/">Difference Engine</a> friends. Some of us shared a lift up from Middlesbrough thanks to <a href="http://geogoer.com/">Geogoer</a>&#8217;s nifty ride sharing service!</p>
<p>It was great to see some familiar faces (<a href="http://twitter.com/digates">Di</a>, <a href="http://twitter.com/leesimpson">Lee</a>, <a href="http://twitter.com/philpyj">Jonny</a> and <a href="http://presencemultimedia.co.uk/">Team Presence</a>) as well as to put some faces to Twitter handles (Kat and Jim of <a href="http://twitter.com/sonodrome">Sonodrome</a>)! Our genial MC for the night was <a href="http://twitter.com/paul_a_smith">Paul Smith</a> also known as the world-famous <a href="http://twitter.com/twitchhiker">twitchhiker</a>. The highlight of the night was definitely the raffle. Our <a href="http://twitter.com/coldclimate">Oli</a> gave himself away to cook a meal for a lucky winner in their own home. <a href="http://twitter.com/spoutingshite">Ross Cooney</a> scooped this special treat! And Oli went on to win a massive bag of goodies from the <a href="http://www.balticmill.com/">Baltic</a> courtesy of <a href="http://twitter.com/davidcoxon">David Coxon</a>!</p>
<p>All in all a great night in Newcastle with a really friendly crowd and lots of money raised for <a href="http://www.concern.net/">Concern</a>. Well done to organiser <a href="aoifebeefah">Aoife</a> and team!</p>
<p>PS. Apologies to any unfortunate victims of our enthusiastic cupcake sales campaign!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/tyne-twestival-march-2010/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/tyne-twestival-march-2010/</feedburner:origLink></item>
		<item>
		<title>Starting a Social Network</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/Q_HUyZPTGcY/</link>
		<comments>http://blog.wishli.st/column-starting-a-social-network/#comments</comments>
		<pubDate>Sat, 23 May 2009 15:06:00 +0000</pubDate>
		<dc:creator>David Haywood Smith</dc:creator>
				<category><![CDATA[community]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/column-starting-a-social-network/</guid>
		<description><![CDATA[Have you ever thought about starting your own social network? It&#8217;s a great way to connect with people with similar interests or with potential customers.
Also, with the group features on sites like Facebook and LinkedIn, you can test whether there is any demand for your idea for free!
I wrote a column in the Journal recently [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever thought about starting your own social network? It&#8217;s a great way to connect with people with similar interests or with potential customers.</p>
<p>Also, with the group features on sites like <a href="http://facebook.com/">Facebook</a> and <a href="http://linkedin.com/">LinkedIn</a>, you can test whether there is any demand for your idea for free!</p>
<p>I wrote a column in the Journal recently explaining how to get started. Check it out: <a href="http://www.nebusiness.co.uk/business-news/science-and-technology/2009/04/30/start-your-own-social-network-site-51140-23509954/">Start your own social network site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/column-starting-a-social-network/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/column-starting-a-social-network/</feedburner:origLink></item>
		<item>
		<title>If We Can You Can</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/cwYQ5vx60I4/</link>
		<comments>http://blog.wishli.st/if-we-can-you-can/#comments</comments>
		<pubDate>Thu, 21 May 2009 13:07:00 +0000</pubDate>
		<dc:creator>David Haywood Smith</dc:creator>
				<category><![CDATA[company]]></category>
		<category><![CDATA[Entrepreneurs Forum]]></category>
		<category><![CDATA[If We Can You Can]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/if-we-can-you-can/</guid>
		<description><![CDATA[I was honoured to be shortlisted for the If We Can You Can Challenge 2009! I was invited to pitch wishli.st to a panel of judges and answer their questions.
Unfortunately I wasn&#8217;t selected as a finalist but we&#8217;ve got a few friends among the finalists so if you have a moment to email in your [...]]]></description>
			<content:encoded><![CDATA[<p>I was honoured to be shortlisted for the <a href="http://www.ifwecanyoucan.co.uk/">If We Can You Can</a> Challenge 2009! I was invited to pitch wishli.st to a panel of judges and answer their questions.</p>
<p>Unfortunately I wasn&#8217;t selected as a finalist but we&#8217;ve got a few friends among <a href="http://www.ifwecanyoucan.co.uk/Challenge">the finalists</a> so if you have a moment to <a href="mailto:voting@entrepreneursforum.net">email in your votes</a> please consider the following:</p>
<p>Emma Reilly &#8211; <a href="http://iyosh.wordpress.com/">iYosh</a><br />
Mark Easby &#8211; <a href="http://www.betterbrandagency.com/">Better Brand Agency</a><br />
Rob Earnshaw &#8211; <a href="http://www.thecastingwebsite.com">The Casting Website</a></p>
<p>Good luck guys!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/if-we-can-you-can/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/if-we-can-you-can/</feedburner:origLink></item>
		<item>
		<title>wishli.st on BBC Radio Newcastle!</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/LEvCBvNbyuQ/</link>
		<comments>http://blog.wishli.st/wishli-st-on-bbc-radio-newcastle/#comments</comments>
		<pubDate>Thu, 04 Dec 2008 10:52:00 +0000</pubDate>
		<dc:creator>David Haywood Smith</dc:creator>
				<category><![CDATA[company]]></category>
		<category><![CDATA[BBC]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/wishli-st-on-bbc-radio-newcastle/</guid>
		<description><![CDATA[Yesterday wishli.st got a mention on BBC Radio Newcastle!  They picked up on the story about us in the Journal and called up to find out more information.  The clip is available here for the next 6 days:http://www.bbc.co.uk/programmes/p001lqgjThe interview can be found at 48:00.
]]></description>
			<content:encoded><![CDATA[<p>Yesterday wishli.st got a mention on BBC Radio Newcastle!  They picked up on <a href="http://www.nebusiness.co.uk/business-news/technology-news/2008/11/20/phelan-is-helping-wishli-st-come-true-51140-22298440/">the story about us in the Journal</a> and called up to find out more information.  The clip is available here for the next 6 days:<br /><a href="http://www.bbc.co.uk/programmes/p001lqgj">http://www.bbc.co.uk/programmes/p001lqgj</a><br />The interview can be found at 48:00.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/wishli-st-on-bbc-radio-newcastle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/wishli-st-on-bbc-radio-newcastle/</feedburner:origLink></item>
		<item>
		<title>wishli.st nominated in the Open Web Awards!</title>
		<link>http://feedproxy.google.com/~r/wishli-st/~3/ODJW_XumOdA/</link>
		<comments>http://blog.wishli.st/wishli-st-nominated-in-the-open-web-awards/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 21:22:00 +0000</pubDate>
		<dc:creator>David Haywood Smith</dc:creator>
				<category><![CDATA[company]]></category>
		<category><![CDATA[open web]]></category>
		<category><![CDATA[social shopping]]></category>

		<guid isPermaLink="false">http://blog.wishli.st/wishli-st-nominated-in-the-open-web-awards/</guid>
		<description><![CDATA[wishli.st has been nominated in the &#8216;Social Shopping&#8217; category of the Open Web Awards!  Many thanks to everyone who nominated us &#8211; we&#8217;re thrilled to be through to the next round!
Now we need your support again as we push for the next stage of the competition. If you could vote for us every day [...]]]></description>
			<content:encoded><![CDATA[<p>wishli.st has been nominated in the &#8216;Social Shopping&#8217; category of the <a href="http://mashable.com/openwebawards/">Open Web Awards</a>!  Many thanks to everyone who nominated us &#8211; we&#8217;re thrilled to be through to the next round!</p>
<p>Now we need your support again as we push for the next stage of the competition. If you could vote for us every day between now and midnight on the 30th November we&#8217;d be extremely grateful indeed!</p>
<p>Thanks to <a href="http://counterknowledge.com/">Counterknowledge.com</a> for <a href="http://counterknowledge.com/?p=829">endorsing us</a> and thanks to all of you for your continued support. It means a lot to us.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wishli.st/wishli-st-nominated-in-the-open-web-awards/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.wishli.st/wishli-st-nominated-in-the-open-web-awards/</feedburner:origLink></item>
	</channel>
</rss>

