<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Coffee on the Keyboard &#187; Projects</title>
	<atom:link href="http://coffeeonthekeyboard.com/tag/projects/feed/" rel="self" type="application/rss+xml" />
	<link>http://coffeeonthekeyboard.com</link>
	<description>by James Socol</description>
	<lastBuildDate>Fri, 20 Apr 2012 22:17:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/>		<item>
		<title>So You Wanna Help Mozilla?</title>
		<link>http://coffeeonthekeyboard.com/so-you-wanna-help-mozilla-316/</link>
		<comments>http://coffeeonthekeyboard.com/so-you-wanna-help-mozilla-316/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 00:45:22 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[amo]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[sumo]]></category>
		<category><![CDATA[support]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web dev]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://coffeeonthekeyboard.com/?p=316</guid>
		<description><![CDATA[A common theme we heard in responses to our web developer survey was: &#8220;I wish I could help Mozilla, but I&#8217;m just a web developer.&#8221; Well, fellow web ninjas, you can put your skills to work with Mozilla and help make the web a better place. Our web projects are open, just like Firefox, and [...]]]></description>
			<content:encoded><![CDATA[<p>A common theme we heard in responses to our <a href="http://hacks.mozilla.org/2009/11/web-developer-survey-update/">web developer survey</a> was: &#8220;I wish I could help Mozilla, but I&#8217;m just a web developer.&#8221;</p>
<p>Well, fellow web ninjas, you <em>can</em> put your skills to work with Mozilla and help make the web a better place. Our web projects are open, just like Firefox, and we&#8217;d love your help!</p>
<p>If you&#8217;re a web developer and want to help Mozilla and Firefox users while working on sites that see millions of visitors every day, follow me through the jump and I&#8217;ll show you around our shop and introduce you to the tools we use.<span id="more-316"></span></p>
<h3>Our Projects</h3>
<p>Mozilla Web Dev is responsible for pretty much every web site at Mozilla, from <a href="https://addons.mozilla.org/">Addons</a> to <a href="http://support.mozilla.com/">Support</a> to <a href="http://www.mozilla.com/">Mozilla.com</a> to <a href="http://www.spreadfirefox.com/">Spread Firefox</a>. We also take care of web services like the <a href="https://wiki.mozilla.org/AUS">Application Update Service</a>, <a href="https://wiki.mozilla.org/PFS2">Plugin Finder Service</a> and the <a href="https://wiki.mozilla.org/Socorro">Crash Report Beacon</a>.</p>
<p>Almost all of our code (everything except Socorro—the crash report beacon—I think) is available on <a href="http://viewvc.svn.mozilla.org/vc/">svn.mozilla.org</a>. You can browse around the server and see the source right now. It will all basically run on the standard LAMP (where P is PHP or Python) stack.</p>
<h3>Our Tools</h3>
<p>The control center of web development at Mozilla is <a href="http://bugzilla.mozilla.org/">Bugzilla</a>. All our work takes the form of &#8220;bugs&#8221; here. A &#8220;bug&#8221; is not necessarily a problem with the software. A new feature or a software update would also be called a &#8220;bug.&#8221; I&#8217;ll talk about the life-cycle of a web development bug below.</p>
<p>IRC is just as important as Bugzilla. Both our staff and our contributors are geographically diverse, and IRC gives us a good way to coordinate and talk to each other around the globe. If you&#8217;re new to IRC, <a href="https://addons.mozilla.org/en-US/firefox/addon/16">ChatZilla</a> is an easy place to start. Most projects have their own channel on <a href="http://irc.mozilla.org/">irc.mozilla.org</a>, like <a href="irc://irc.mozilla.org/sumo">#sumo</a> for Support and <a href="irc://irc.mozilla.org/amo">#amo</a> for Addons. We&#8217;re also usually in <a href="irc://irc.mozilla.org/webdev">#webdev</a>.</p>
<p>As web developers, are chief weapon is HTML. HTML and CSS. HTML, CSS, and JavaScript. <em>No one expects the&#8230;</em> (Sorry.) On the front-end, we chiefly work in HTML, CSS, and JavaScript, and occasionally other technologies like XML. On the back-end, nearly all of our projects are in PHP or Python.</p>
<p>For version control we mostly use Subversion, though git (and git-svn) has gained a bunch of ground lately. (Addons will be <a href="http://micropipes.com/blog/2009/11/17/amo-development-changes-in-2010/">moving to git</a> sometime next year.)</p>
<p>To work on your own computer, you&#8217;ll probably need to set up Apache, MySQL, and PHP or Python. <a href="http://www.apachefriends.org/en/xampp.html">XAMPP</a> can be incredibly helpful here. Working on Linux (or Mac OS) is usually easier than Windows, and closer to our server environment. A tool like <a href="http://www.virtualbox.org/">VirtualBox</a> will let you run a Linux virtual machine on most other operating systems. It&#8217;s a little slower but switching back and forth is easy. I&#8217;ll try to write about my local development set up soon.</p>
<h3>Our Workflow</h3>
<p>Let&#8217;s go over the life of a bug. This is a little long-winded.</p>
<p>A bug is born either when someone describes a problem or when we decide to add a new feature. (Every project has its own way of doing the latter.) Sometimes our Web <abbr title="Quality Assurance">QA</abbr> team finds problems, sometimes community members do. Then the bug is created, or filed, usually by the person who discovers it—that could be you!</p>
<p>Once a bug has been filed, possibly after some discussion of the best way to fix it, a developer—and that could be you, too—will &#8220;take&#8221; the bug, accepting responsibility for fixing it. Fixing a bug means changing the application in some way: changing a behavior, adding a localization, etc.</p>
<p>When the developer believes they&#8217;ve fixed the problem in their copy, they generate a patch (Subversion&#8217;s &#8220;diff&#8221; command is useful). They then upload that patch as a new attachment, and request review (r?) from someone else. Who does the review will depend on the project and how busy everyone is. If you&#8217;re not sure who to ask, ask in IRC.</p>
<p>The patch will either get an r+ or an r-. An r+ means it&#8217;s good to go, and it can usually be checked in to Subversion (unless there are reasons to wait). An r- means there&#8217;s something wrong. This can range from a patch containing some extraneous data to a patch not solving the problem, and an r- almost always includes a description of the problem.</p>
<p>When a patch with a positive review (r+) gets checked in to Subversion, the developer will include the revision in the bug and change it from <em>new</em> to <em>resolved: fixed</em>. In a few minutes, the change will appear on a staging server that&#8217;s updated frequently with the latest code. Our Web QA staff and contributors will test the bug, compare expected to actual behavior, and with either <em>reopen</em> the bug, if it&#8217;s not fixed, or set the status to <em>verified</em>. Then the bug is considered done. Verified bugs rarely reopen.</p>
<p>Once all the bugs for a milestone are done, we &#8220;freeze&#8221; the source against new commits while Web QA does a final check that everything is in good shape. When QA signs off on the current code, we push the new version onto our production web servers.</p>
<p>So that&#8217;s the life of a bug, from filed to production. When it gets to production, your code can be seen or used by millions of people every day.</p>
<h3>Join Us</h3>
<p>So if you&#8217;re a web developer and want to help Mozilla and Firefox, head over to Bugzilla or IRC and get started. We hope to see you soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://coffeeonthekeyboard.com/so-you-wanna-help-mozilla-316/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>WP Plugin: Better Search Widget</title>
		<link>http://coffeeonthekeyboard.com/wp-plugin-better-search-widget-113/</link>
		<comments>http://coffeeonthekeyboard.com/wp-plugin-better-search-widget-113/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 18:30:23 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Back-end]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://coffeeonthekeyboard.com/?p=113</guid>
		<description><![CDATA[Today I upgraded from WordPress 2.3.3 to 2.6.1. I&#8217;m such a late adopter sometimes. I had to go through and repeat a few hacks. For example, 2.3.x didn&#8217;t allow you to do get_sidebar($name), so I&#8217;d hacked the &#8220;get_sidebar()&#8221; function. And I replaced the still-broken Atom feed reading widget with James Wilson&#8217;s Google Reader Widget. Then [...]]]></description>
			<content:encoded><![CDATA[<p>Today I upgraded from WordPress 2.3.3 to 2.6.1. I&#8217;m such a late adopter sometimes.</p>
<p>I had to go through and repeat a few hacks. For example, 2.3.x didn&#8217;t allow you to do <code>get_sidebar($name)</code>, so I&#8217;d hacked the &#8220;get_sidebar()&#8221; function. And I replaced the still-broken Atom feed reading widget with James Wilson&#8217;s <a href="wordpress.org/extend/plugins/google-reader-widget/">Google Reader Widget</a>.</p>
<p>Then I finally got fed up with the default &#8220;Search&#8221; widget, which doesn&#8217;t look like the other widgets at all (no title), so I started hacking into that one. Then I realized &#8220;why hack, when I can extend?&#8221;</p>
<p>So, here it is, <a href="http://jamessocol.com/projects/better-search-widget.php">Better Search Widget</a>.</p>
<p>All it does is add a search widget with a customizable title, submit button, and field size. Quick-and-useful. You can see the results in the sidebar.</p>
<p>If you decide to use it, leave a comment and I&#8217;ll check out your blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://coffeeonthekeyboard.com/wp-plugin-better-search-widget-113/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Help Me Scale</title>
		<link>http://coffeeonthekeyboard.com/help-me-scale-97/</link>
		<comments>http://coffeeonthekeyboard.com/help-me-scale-97/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 14:58:38 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Back-end]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[load]]></category>
		<category><![CDATA[microblog]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[social messaging]]></category>
		<category><![CDATA[subquery]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://coffeeonthekeyboard.com/help-me-scale-97/</guid>
		<description><![CDATA[I&#8217;ve been reading Eran Hammer-Lahav&#8217;s intelligent posts on microblog scalability, and now I&#8217;m concerned about my own &#8220;microblog&#8221; site, Picofiction. Similar to social networks, social updates, social messaging, social&#8230; Like many social web sites—amongst our weaponry&#8230;—Picofiction lets you &#8220;follow&#8221; your favorite authors, displaying all their posts along with yours. I handle this very naïvely: everything [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been reading Eran Hammer-Lahav&#8217;s <a href="http://www.hueniverse.com/hueniverse/2008/04/scaling-a-micro.html">intelligent</a> <a href="http://www.hueniverse.com/hueniverse/2008/03/scaling-a-micro.html">posts on</a> <a href="http://www.hueniverse.com/hueniverse/2008/03/on-scaling-a-mi.html">microblog scalability</a>, and now I&#8217;m concerned about my own &#8220;microblog&#8221; site, <a href="http://picofiction.com/">Picofiction</a>.</p>
<p>Similar to social networks, social updates, social messaging, social&#8230; Like many social web sites—amongst our weaponry&#8230;—Picofiction lets you &#8220;follow&#8221; your favorite authors, displaying all their posts along with yours.</p>
<p>I handle this very naïvely: everything is offloaded to the database. There are three tables involved here, one of users, one of posts, and one of follower/followee bindings.</p>
<p>Here&#8217;s the basic structure of this query:</p>
<pre>SELECT post_id, post_body, post_date, post_type,
  user_name AS author_name, user_id AS author_id
FROM posts
LEFT JOIN users
ON posts.author_id = users.user_id
WHERE author_id = '<var>CURRENT_USER</var>'
OR author_id IN (
  (SELECT followed_id
   FROM followers
   WHERE following_id = '<var>CURRENT_USER</var>')
  )
ORDER BY post_date DESC
LIMIT <var>PAGE_START</var>,20;</pre>
<p>Here&#8217;s where I need help: this works great on a single database, but it does not scale horizontally.</p>
<p>Since this horizontal scalability is such a hot topic right now, I&#8217;m asking for ideas. I&#8217;d like to put in the infrastructure <em>before</em> there is a need for it.</p>
<p>Eran points out that caching is not as simple a solution as we&#8217;d like to think. What do you cache? How do you keep caches in sync?</p>
<p>Does anyone have experience with MySQL Cluster Servers? It seems like the best way of scaling is to make the process as <a href="http://en.wikipedia.org/wiki/Amdahl%27s_law">parallelizable</a> as possible. The database then handles the parallelization, so the less I can do in the program the better, right?</p>
]]></content:encoded>
			<wfw:commentRss>http://coffeeonthekeyboard.com/help-me-scale-97/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Better Living through Memcached</title>
		<link>http://coffeeonthekeyboard.com/better-living-through-memcached-85/</link>
		<comments>http://coffeeonthekeyboard.com/better-living-through-memcached-85/#comments</comments>
		<pubDate>Mon, 19 May 2008 15:00:54 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[instructions]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[useful]]></category>
		<category><![CDATA[Web 2.0]]></category>

		<guid isPermaLink="false">http://coffeeonthekeyboard.com/better-living-through-memcached-85/</guid>
		<description><![CDATA[I wanted to put something specific in the title, like &#8220;Speed up your service&#8221; or &#8220;Reduce server load&#8221; or &#8220;Limit database calls&#8221; or&#8230; You see why I chose &#8220;Better Living.&#8221; Memcached is a memory caching system with an obvious name. It allows you to store basically any data that can be serialized into a giant, [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to put something specific in the title, like &#8220;Speed up your service&#8221; or &#8220;Reduce server load&#8221; or &#8220;Limit database calls&#8221; or&#8230; You see why I chose &#8220;Better Living.&#8221;</p>
<p><a href="http://danga.com/memcached/">Memcached</a> is a memory caching system with an obvious name. It allows you to store basically any data that can be serialized into a giant, memory-resident hash, then retrieve it with its unique key.</p>
<p>Imagine not querying your database on every request, and you only begin to get a sense of how useful this is.</p>
<p>Let&#8217;s go through a simple, single-server setup.<span id="more-85"></span></p>
<h3>Installing Memcached</h3>
<p>First you&#8217;ll need to make sure <a href="http://www.monkey.org/~provos/libevent/">libevent</a> is installed. Easy enough through yum or apt-get.</p>
<p><a href="http://danga.com/memcached/download.bml">Download Memcached</a> and untar it. Run the <code>configure</code> script. You can probably do this with no arguments. I used <code>--prefix=/usr</code> to change from the default of<code>/usr/local</code>. On your system you may want to add <code>--enable-64bit</code> or <code>--enable-threads</code>, depending on your configuration and expected load.</p>
<p>Run a quick <code>make &amp;&amp; make install</code> and you&#8217;re done.</p>
<h3>Running Memcached</h3>
<p>You can run Memcached from the command line but sticking the <code>-d</code> parameter to run as a daemon. If you&#8217;re still root, you&#8217;ll need to add <code>-u<em>nobody</em></code>, where &#8220;nobody&#8221; is some unprivileged user. And that&#8217;s it. Memcached is up and running on your server and ready to connect.</p>
<p>If you&#8217;re on a system with chkconfig, I&#8217;ve put together a <a href="http://coffeeonthekeyboard.com/wp-content/uploads/2008/05/memcache-chkconfig.zip" title="Memcached Chkconfig Scripts">simple chkconfig script</a> for it. The zip file contains two files, <code>etc/rc.d/init.d/memcached</code> and <code>etc/sysconfig/memcached</code>. Copy them to those locations, <code>chmod +x /etc/rc.d/init.d/memcached</code> and then run <code>chkconfig --add memcached</code>, and <code>chkconfig memcached on</code> to run Memcached when the server starts. You can type <code>service memcached start</code> to get it up and running.</p>
<p>Typing <code>memcached -h</code> will show you all the options, including which ports and IP addresses to listen on, or which socket to use, how much memory to allocate, and others. You can add any of these command line options to the <code>$OPTIONS</code> variable in the <code>/etc/sysconfig/memcached</code> file to set the default options for the Memcached service.</p>
<h3>Using Memcached (Finally!)</h3>
<p>Memcached is installed and running. Now what? Well it sort of depends on your language—there are Memcached bindings for Perl, PHP, Ruby, Java, Python, C, C#, Lua, and even Postgres and MySQL—and your program. I&#8217;m not going to go through the specific implementation, but here&#8217;s the basic idea. (In PHP. Ok, so I lied about that specific-implementation thing.)</p>
<p>Let&#8217;s say our goal is to reduce database load. Then we want to try to preempt as many SELECT queries as we can.</p>
<p>If your original code was like this: (Please! Be safe about SQL-injection.)</p>
<blockquote>
<pre>// What post do we want?
$id = get_current_id();

// Query the database
$query = "SELECT * FROM posts WHERE id = '$id';"
$result = $db-&gt;query($query);

// Now we have the post data
$post = $result-&gt;fetch_assoc();</pre>
</blockquote>
<p>What we&#8217;re doing is getting an ID, possibly from a user, then getting the associated table row and returning it. Now to speed that up with Memcached:</p>
<blockquote>
<pre>// Create a new Memcache object
$m = new Memcache;
$m-&gt;<a href="http://s.hort.cc/D">connect</a>('localhost');

// Check Memcache for the data, first
if ( !$post = $m-&gt;get("post:$id") ) {
  // Not in the cache, get from the database
  $query = "SELECT * FROM posts WHERE id = '$id';";
  $result = $db-&gt;query($query);

  // Get the post data
  $post = $result-&gt;fetch_assoc();

  // If we expect this data to be used again soon,
  // we can store it in the cache
  $m-&gt;set("post:$id", $post);
}</pre>
</blockquote>
<p>There we have all the basics. The string <code>"post:$id"</code> is the Memcached key. The post data is serialized and stored (with <a href="http://s.hort.cc/E">Memcache::set</a>) as a key-value pair. If it&#8217;s in the cache, which we can check with <a href="http://s.hort.cc/F">Memcache::get</a> (unless the stored value was boolean <code>false</code>, then it gets confusing) then we don&#8217;t need to waste a database query.</p>
<p>If you expect data to be used as soon as it&#8217;s created, you can do your database <code>INSERT</code> statements and then store the same data in the cache immediately. (Or <a href="http://s.hort.cc/G">Memcache::replace</a>, whichever is necessary.)</p>
<h3>So, what?</h3>
<p>To be fair, my Memcached example made the code much longer, and required instantiating another object, another TCP connection&#8230; What&#8217;s the payoff?</p>
<p>Memcached was written to improve performance over at LiveJournal when they hit the 20+ million page view/day mark. Imagine that database call was in a loop, or if, instead of serializing one post, we built an array of all the posts from one user, and stored that. You can quickly see how many database queries we eliminate.</p>
<p>For fun, I ran a test that generated a random number, then tried to pull the associated row out of a database. (I only generated numbers for which I knew there was a row.) I iterated over this 3,000 times and did 10 trials each.</p>
<p>In PHP with a MySQL database, the Memcached version was around 60% faster, averaging 0.315 seconds vs. 0.820 seconds without Memcached.</p>
<h3>But Wait! There&#8217;s More</h3>
<p>Since Memcached was designed for a site that already existed on dozens of servers, it&#8217;s based on the idea that you&#8217;d run Memcached on all your web servers, and then treat them like a pool. You can connect to several servers simultaneously to spread the Memcaching around. Data gets hashed to a particular server and, if it&#8217;s available on any of them, gets pulled back.</p>
<p>Memcached can also compress data on the fly with zlib, so if you did plan on storing the last 20 posts of every user, you wouldn&#8217;t be out quite so much space.</p>
<p>Finally, Memcached will keep adding data until it hits its memory limit, and which point it drops the Least Recently Used stuff to make room. So even though you can set data not to expire, you can&#8217;t trust that it will be in the cache forever.</p>
<p>For sites that rely on database reads, Memcached can help a lot. If you&#8217;re site depends more on writes or updates, it will probably do very little, or even cause unnecessary overhead.</p>
<p>But since most data-driven sites are significantly bigger readers than writers, Memcached is a great way to improve response time and quality of service, and to reduce load on those databases for when you really do need to read or write to it.</p>
<h3>Do You Memcached?</h3>
<p>So, do you use Memcached? How? Does it speed up your service or have no noticeable effect?</p>
]]></content:encoded>
			<wfw:commentRss>http://coffeeonthekeyboard.com/better-living-through-memcached-85/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>s.hort.cc makes s.hort.cuts</title>
		<link>http://coffeeonthekeyboard.com/shortcc-makes-shortcuts-84/</link>
		<comments>http://coffeeonthekeyboard.com/shortcc-makes-shortcuts-84/#comments</comments>
		<pubDate>Sat, 17 May 2008 01:21:47 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[short]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://coffeeonthekeyboard.com/shortcc-makes-shortcuts-84/</guid>
		<description><![CDATA[Yet Another Short URL. I just launched s.hort.cc to offer something that TinyURL and Tiny.cc didn&#8217;t: an easy API for creating short URLs, or &#8220;s.hort.cuts,&#8221; and returning them in a format my program could use. You can visit the s.hort.cc website, of course, but you can also create a short URL and have it returned [...]]]></description>
			<content:encoded><![CDATA[<p>Yet Another Short URL.</p>
<p>I just launched <a href="http://s.hort.cc/">s.hort.cc</a> to offer something that TinyURL and Tiny.cc didn&#8217;t: an easy API for creating short URLs, or &#8220;s.hort.cuts,&#8221; and returning them in a format my program could use.</p>
<p>You can visit the <a href="http://s.hort.cc/">s.hort.cc </a>website, of course, but you can also create a short URL and have it returned to you in XML, JSON, YAML, or plain text. (Even if you decide to parse the whole XHTML page, it&#8217;s easy to find the s.hort.cut with the DOM or an XPath parser.) I&#8217;ll gladly add other formats if people suggest them.</p>
<p>I&#8217;m working on a Firefox extension, but in the meantime, drag this link: <a href="javascript:void(window.open('http://s.hort.cc/create.php?url='+escape(window.location), 'shortcut', 'status=0,toolbar=0,location=0,menubar=0,scrollbars=0,height=320,width=400'));" title="s.hort.cut">s.hort.cut</a> to your bookmarks toolbar to automagically turn the current page into a s.hort.cut.</p>
<p>Read more technical info below the break.<span id="more-84"></span></p>
<h3>Technical Things!</h3>
<p>To use the API, you just need to send a request to <code>http://s.hort.cc/create.php</code>, via GET or POST, with two parameters:</p>
<ul>
<li><code>url</code> — contains the URL-escaped long URL you want to shrink, and</li>
<li><code>format</code> — one of &#8220;<code>json</code>&#8220;, &#8220;<code>xml</code>&#8220;, &#8220;<code>yaml</code>&#8220;, or &#8220;<code>text</code>&#8221; or &#8220;<code>plain</code>&#8220;, depending on what you need.</li>
</ul>
<p>s.hort.cc returns the new URL in the correct format and with the correct Content-type heading. (For JSON, the content is available both in the response body and in the X-JSON header.)</p>
<p>If possible, please try to set a unique and meaningful User-Agent header, just so I can track usage, and so your app won&#8217;t be subject to rate limiting because of someone else&#8217;s problem.</p>
<p>Not that there <em>is</em> rate limiting. You can use the API as much as you want. But if you&#8217;re going to access it more than 60 times per minute, or once per second on average, please let me know.</p>
<p>On the server-side, s.hort.cc is written in <a href="http://www.php.net/">PHP</a> and backed by <a href="http://www.mysql.com/">MySQL</a> and <a href="http://danga.com/memcached/">Memcached</a> to speed up requests and reduce server load.</p>
]]></content:encoded>
			<wfw:commentRss>http://coffeeonthekeyboard.com/shortcc-makes-shortcuts-84/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Picofiction</title>
		<link>http://coffeeonthekeyboard.com/picofiction-55/</link>
		<comments>http://coffeeonthekeyboard.com/picofiction-55/#comments</comments>
		<pubDate>Wed, 26 Sep 2007 21:20:00 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[fiction]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[short]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[stories]]></category>

		<guid isPermaLink="false">http://coffeeonthekeyboard.com/picofiction-55/</guid>
		<description><![CDATA[Picofiction is new project: telling stories in 140 characters. Picofiction is a combination of microfiction, text messaging and Twitter. If you can write a story in a two-page spread, and tell the world what you&#8217;re doing in 140 characters, maybe you can tell a story in 140 characters. Why 140? 140 characters is the length [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://picofiction.com/" title="Visit: Picofiction.com, my newest project.">Picofiction</a> is new project: telling stories in 140 characters.</p>
<p>Picofiction is a combination of <a href="http://en.wikipedia.org/wiki/Microfiction" title="Read Wikipedia's article on microfiction.">microfiction</a>, text messaging and <a href="http://twitter.com" title="Visit Twitter.">Twitter</a>. If you can write a story in a two-page spread, and tell the world what you&#8217;re doing in 140 characters, maybe you can tell a story in 140 characters.</p>
<h4>Why 140?</h4>
<p>140 characters is the length of a standard text message. Text messaging has its own vocabulary to deal with the limit, but story telling can be even more flexible with words.</p>
<p>The site is up and running and you can <a href="http://picofiction.com/post.php" title="Start posting on Picofiction.">start sharing stories</a> right now! Some features haven&#8217;t been finished yet but I&#8217;m working on it.</p>
<p>And remember that this Saturday is MSU&#8217;s <a href="http://ott.educ.msu.edu/ctt/techconf/" title="Visit and register for the Technology Conference">Technology Conference 2007</a>. If you&#8217;re a teacher in Michigan you should come!</p>
]]></content:encoded>
			<wfw:commentRss>http://coffeeonthekeyboard.com/picofiction-55/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

