<?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>Max Cutler &#187; Max</title>
	<atom:link href="http://www.maxcutler.com/author/admin/feed" rel="self" type="application/rss+xml" />
	<link>http://www.maxcutler.com</link>
	<description>WebDev, Tech, and Life</description>
	<lastBuildDate>Fri, 12 Mar 2010 20:23:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Courant no longer…</title>
		<link>http://www.maxcutler.com/2010/02/21/courant-no-longer</link>
		<comments>http://www.maxcutler.com/2010/02/21/courant-no-longer#comments</comments>
		<pubDate>Sun, 21 Feb 2010 20:48:09 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[College News]]></category>
		<category><![CDATA[Courant News]]></category>
		<category><![CDATA[Yale Daily News]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=238</guid>
		<description><![CDATA[On October 26, 2008, the first bits were committed to the private Courant News project repository. At the time, Rob, Paul and I were going to offer a hosted SaaS product for college news organizations, freeing them from the grasps of College Publisher and providing a stable foundation for the future. In February 2009, we [...]]]></description>
			<content:encoded><![CDATA[<p>On October 26, 2008, the first bits were committed to the private <a href="http://www.courantnews.com">Courant News</a> project repository. At the time, <a href="http://rsbaskin.com">Rob</a>, <a href="http://zpao.com">Paul</a> and I were going to offer a hosted <a title="Software as a Service" href="http://en.wikipedia.org/wiki/Software_as_a_service">SaaS</a> product for college news organizations, freeing them from the grasps of <a href="http://www.collegepublisher.com/">College Publisher</a> and providing a stable foundation for the future. In February 2009, we decided not to pursue the project as a business, but agreed to continue development as an open-source project. On April 7, 2009, we <a href="http://code.courantnews.com/blog/welcome">opened</a> our code to the public. After launching the <a href="http://www.yaledailynews.com/">Yale Daily News</a> on Courant in September 2009, we finally started to pick up steam in the past month. But after deep reflection, we have decided to cease development of the project.</p>
<p><span id="more-238"></span></p>
<h3>Context</h3>
<p>During the fall semester we made significant progress with Courant: <a href="http://code.courantnews.com/changeset/94">switched</a> to <a href="http://haystacksearch.org/">Haystack</a> for search, improved <a href="http://code.courantnews.com/changeset/95">multimedia browse-ability</a>, added the <a href="http://code.courantnews.com/changeset/101">headers app</a> for improved mobile and alternative versions of a site, implemented powerful automated <a href="http://code.courantnews.com/changeset/108">caching</a> <a href="http://code.courantnews.com/changeset/110">busting</a>, <a href="http://code.courantnews.com/changeset/117">refactored</a> the staff app, added <a href="http://code.courantnews.com/changeset/118">OpenX integration</a>, added <a href="http://code.courantnews.com/changeset/122">mapping and basic geo functionality</a>, <a href="http://code.courantnews.com/changeset/112">started</a> <a href="http://code.courantnews.com/changeset/113">work</a> <a href="http://code.courantnews.com/changeset/116">on</a> <a href="http://groups.google.com/group/courantnews/browse_thread/thread/890dc88b05c45e7b">Nando</a>, added <a href="http://code.courantnews.com/changeset/129">batch uploading of photos</a>, and continuously increased performance.</p>
<p>But in early January, Rob and I had a serious conversation about whether it still made sense to develop Courant. Although the YDN was using it, no other developers had joined the team, and we had doubts about the project’s long-term survivability.</p>
<p>Our last best hope was to convince the team at <a href="http://www.copress.org/">CoPress</a> to help support clients running on Courant. I met with them at their team meet-up in Philadelphia over MLK weekend and tried to feel out their intentions and plans for the next year. There was still some glimmer of hope, and I considered joining their support team to make this a reality.</p>
<p>Two weeks later, the YDN Business and Online departments hosted a conference for college news organizations, at which I gave a presentation about Courant. Two of the attendees were enthusiastic about the idea of migrating to Courant, and I’ve been in talks with them in the intervening weeks. We even wrote a CP4 to Courant data migration script while working on a prototype installation for one of the potential partners.</p>
<h3>The Decision</h3>
<p>Shortly thereafter, CoPress decided to <a href="http://www.copress.org/2010/02/16/copress-is-closing-down-operations/">shut down their operations</a>. Without CoPress, and without any other potential developers to take over the reins, we had to make a tough decision: continue developing the project and potentially transition these two new sites to the platform without long-term support plans, or abandon the project.</p>
<p>Having worked on this project for over 16 months, pouring countless hours of my life into its development, it was an extraordinarily difficult decision. But, in the end, I feel it would be irresponsible to continue, especially knowing that I am going to have to leave anyways after my term at the YDN expires in October.</p>
<p>I’m currently working to transition the YDN off of Courant to a commercial system; although the front-runner is currently <a href="http://www.ellingtoncms.com/">Ellington</a> (from which <a href="http://www.djangoproject.com/">Django</a> was originally extracted), a final decision has yet to be made and it will likely be several months before I can talk publicly about our choice.</p>
<p>In the meantime, there may be occasional bug fixes to Courant, but substantial development of new features will not occur. We will leave the website and code online at least through the summer, and will likely move the code to <a href="http://code.google.com">Google Code</a> or <a href="http://www.github.com">Github</a> before retiring the website. Please feel free to use the code, but know that we will no longer be providing support of any form.</p>
<h3>Conclusion</h3>
<p>Had we pursued grant funding or other avenues of development, perhaps Courant could have lived up to its full potential. I truly believe it could have been a major player in changing the landscape of college news. I’m very proud of the work we did to create a generic and customizable, yet still very powerful, solution tailored specifically to the needs of college news organizations. Components like the <a href="http://docs.courantnews.com/ref/core/gettag.html#ref-core-gettag">get tag</a>, <a href="http://maxcutler.com/blog/2009/05/23/courant-news-model-customization">dynamic/custom fields</a>, the <a href="http://rsbaskin.com/2009/11/introducing-the-courant-headers-app/">headers app</a>, and the <a href="http://maxcutler.com/blog/2009/11/07/courant-news-caching">cache system</a> are beyond the scope of most existing college news CMSes, and represent months of analysis and planning. The system was <a href="http://maxcutler.com/blog/2009/09/23/keeping-courant-with-annie-le-coverage">battle-tested</a> against outrageous traffic spikes and proved to be quite resilient. We are not the first, and will surely not be the last, team to attempt to create a new CMS option for the college news world, and I wish others the best of luck.</p>
<p>I owe immense thanks to Rob and Paul for their contributions to the project over the last 18 months; their support has been invaluable, and I hope to work with them again in the future. I also want to thank <a href="http://www.andrewspittle.net/">Andrew Spittle</a> for his assistance on designs for Nando, it’s unfortunate that they never saw the light of day. Thanks to everyone who has been supportive and encouraging over the past year, especially those who contributed to discussions on our mailing list and privately via email or IM.</p>
<p>I look forward to seeing how college news organizations respond to the  current crisis in the media industry, and I hope they learn to adapt and  look forward instead of backwards. My stint in the college news world has been enjoyable and a great learning experience, but I’m ready to apply my skills to new areas of interest. If you need an experienced developer for your software or robotics project, please <a href="mailto:maxcutler@gmail.com">get in touch</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2010/02/21/courant-no-longer/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Business Models for News</title>
		<link>http://www.maxcutler.com/2009/12/08/new-business-models-for-news</link>
		<comments>http://www.maxcutler.com/2009/12/08/new-business-models-for-news#comments</comments>
		<pubDate>Tue, 08 Dec 2009 16:35:30 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=234</guid>
		<description><![CDATA[For my Introduction to Law &#38; Technology class this semester, I worked with two of my classmates on a survey of new business models for journalism and news organizations. The results can be found on the website we have created, including a full recap and notes of the Knight Media conference held at the Yale [...]]]></description>
			<content:encoded><![CDATA[<p>For my <a href="http://www.yalelawtech.org">Introduction to Law &amp; Technology class</a> this semester, I worked with <a href="http://twitter.com/jakobdorof">two</a> of my <a href="http://twitter.com/sduboff">classmates</a> on a survey of new business models for journalism and news organizations. The results can be found on the <a href="http://yalelawtech.maxcutler.com">website</a> we have created, including a full <a href="http://yalelawtech.maxcutler.com/kmedia-conference/">recap</a> and notes of the Knight Media conference held at the Yale Law School in November.</p>
<p>We performed survey research on <a href="http://yalelawtech.maxcutler.com/new-business-models/">eight</a> of the most discussed new business models for news, although we tried not to prescribe any of them as “the” solution. As countless others have pointed out, there will not be any single solution that will work for any or all news organizations, so it is instead important to understand how each might contribute to a new news organization structure. We hope to update the site periodically as events unfold in the industry, and will continue to <a href="http://yalelawtech.maxcutler.com/links/">post</a> to our Publish2 <a href="http://www.publish2.com/newsgroups/yale-law-tech---new-journalism-business-models/">newsgroup</a> as we come across relevant new content.</p>
<p>We hope our research and summaries are useful to interested observers, especially those who may not have been following the issues at hand as closely as we have. Feel free to give feedback and let us know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/12/08/new-business-models-for-news/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Who will pay the messengers?</title>
		<link>http://www.maxcutler.com/2009/11/13/who-will-pay-the-messengers</link>
		<comments>http://www.maxcutler.com/2009/11/13/who-will-pay-the-messengers#comments</comments>
		<pubDate>Fri, 13 Nov 2009 17:03:08 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=227</guid>
		<description><![CDATA[Following are my notes from the “Journalism and the New Media Ecology: Who will pay the messengers?” conference hosted by Yale Law School and the Yale Information Society Project.
Session #1: Who Uses the News and How?
Session #2: Preserving Local Journalism
Session #3: Publicly Owned and Operated Media
Session #4: Quest for Pay Models (minus most of Q&#38;A)
This [...]]]></description>
			<content:encoded><![CDATA[<p>Following are my notes from the <a href="http://www.law.yale.edu/intellectuallife/10123.htm">“Journalism and the New Media Ecology: Who will pay the messengers?” conference</a> hosted by Yale Law School and the <a href="http://www.yaleisp.org">Yale Information Society Project</a>.</p>
<p><span id="more-227"></span>Session #1: <a href="http://www.scribd.com/doc/22515771/Who-Uses-the-News-and-How">Who Uses the News and How?</a></p>
<p>Session #2: <a href="http://www.scribd.com/doc/22522800/Preserving-Local-Journalism">Preserving Local Journalism</a></p>
<p>Session #3: <a href="http://www.scribd.com/doc/22527434/Publicly-Owned-and-Operated-Media">Publicly Owned and Operated Media</a></p>
<p>Session #4: <a href="http://www.scribd.com/doc/22530397/The-Quest-for-Pay-Models">Quest for Pay Models</a> (minus most of Q&amp;A)</p>
<p>This page will be updated throughout the day.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/11/13/who-will-pay-the-messengers/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Courant News: Caching</title>
		<link>http://www.maxcutler.com/2009/11/07/courant-news-caching</link>
		<comments>http://www.maxcutler.com/2009/11/07/courant-news-caching#comments</comments>
		<pubDate>Sun, 08 Nov 2009 02:26:31 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Courant News]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=197</guid>
		<description><![CDATA[The key to performance for high-traffic websites is caching. Facebook is famous for being a prolific memcached user, with 28 terabytes of memcached servers as of December 2008. Part of why the Yale Daily News was able to survive massive traffic spikes during the Annie Le coverage was our judicious use of caching. Read on [...]]]></description>
			<content:encoded><![CDATA[<p>The key to performance for high-traffic websites is caching. Facebook is famous for being a prolific <a href="http://www.danga.com/memcached/">memcached</a> user, with 28 <strong>terabytes</strong> of memcached servers as of <a href="http://www.facebook.com/note.php?note_id=39391378919">December 2008</a>. Part of why the Yale Daily News was able to survive massive traffic spikes during the <a href="http://maxcutler.com/blog/2009/09/23/keeping-courant-with-annie-le-coverage">Annie Le coverage</a> was our judicious use of caching. Read on to learn more about the caching strategies employed by the Courant News platform.</p>
<p><span id="more-197"></span></p>
<h3>Full-page caching</h3>
<p>The simplest caching strategy is to cache the output of entire pages and serve them directly to users before they hit your real code.</p>
<p>The recommended deployment strategy for Courant News employs an <a href="http://www.nginx.net/">nginx</a> proxy server in front of <a href="http://www.apache.org">Apache</a> running <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a>. Fortunately, nginx has a <a href="http://wiki.nginx.org/NginxHttpMemcachedModule">module</a> for memcached integration which can be used to return objects directly from memcached without hitting Apache (and all the relatively heavy Python code) at all.</p>
<p>Our nginx config file might contain the following:</p>
<pre>location /
{
  if ($request_method = POST) {
    proxy_pass http://backend;
    break;
  }

  if ($http_cookie ~* "sessionid=.{32}") {
    proxy_pass http://backend;
    break;
  }
  add_header Memcached True;
  default_type "text/html; charset=utf-8";
  set $memcached_key "/ydn-$uri";
  memcached_pass localhost:11211;
  error_page 404 502 = /django;
}

location /django {
  proxy_pass http://backend;
  include /etc/nginx/proxy.conf;
  break;
}</pre>
<p>What this does is check memcached for a fullpage cache if this is not a POST request (form submission) and the user is not logged in (has a session cookie). If it can’t find the entry in the cache, it just passes it along to Apache.</p>
<p>When the YDN got Drudge’d, all the users were anonymous users, and nginx could serve them the cached pages in its sleep. The site remained responsive for the logged-in staff members who had to update content and moderate comments.</p>
<p>Full-page caching is great, but most sites customize the site for visitors with site accounts.</p>
<h3>Template Caching</h3>
<p>If nginx doesn’t serve up a full-page cache, the request gets passed on to the actual code powering the site. The final HTML is generated by processing template files and then returned to the visitor’s browser.</p>
<p>Because there is often a fair amount of logic and database querying involved with processing the templates, the server load can be high if every visitor had to regenerate the final HTML every time. So we can cache fragments of our templates that we know involve alot of work and avoid that overhead.</p>
<p>Django has a <a href="http://docs.djangoproject.com/en/dev/topics/cache/#template-fragment-caching">template tag</a> to handle this, and it does a pretty good job. The tag is given an expiration time, a name, and a set of extra variables that the cache should vary on. Courant News’ caching system is based on Django’s, but includes two extra pieces of functionality: anti-dogpiling and automatic cache invalidation.</p>
<h3>Anti-Dogpiling</h3>
<p>Caching can help performance greatly, but the cache itself has to be created before it can be used. Generally, one wants a cache to be created the first time it is viewed.</p>
<p>However, page views are not instantaneous; it may take several tens or hundreds of milliseconds to process a page and create a cached version of it. During this time, many more visitors will hit the same page, not find a cached entry, and want to create the cache themselves. All of a sudden, you have dozens of people generating the same cache, until eventually one of them finishes and subsequent visitors can use the cached version.</p>
<p>This can cause undue burden on the server and lead to performance troubles if a cache expires in the middle of a large traffic spike. Often we are simply invalidating an existing cache instead of creating a new one from scratch. In that case, we can do soft-expiration of the cache.</p>
<p>Normally when a cache is invalidated, it is simply deleted altogether, and future requests for it will cause it to be regenerated. Instead, we can have only the first person after a cache expiration generate a new version, while giving subsequent visitors the old cache until the new one is done being generated.</p>
<p>This is what we have implemented in Courant News, originally based on this <a href="http://www.djangosnippets.org/snippets/614/">snippet</a>. It essentially uses an additional cache key to create a second, earlier, soft expiration time, and uses some logic to determine whether a given user should generate the new cache or be served the stale copy.</p>
<h3>Cache Invalidation</h3>
<p>Most sites don’t stay the same forever, so at some point it is necessary to clear the caches so that new content or modifications can appear on the site.</p>
<p>There’s a famous quote by Phil Karlton that “[t]here are only two hard things in Computer Science: cache invalidation and naming things.”</p>
<p>Because there may be links to a given article on dozens of pages on your site, there is no easy way to know which of those pages need to be regenerated when that article’s headline changes or a new article should replace it.</p>
<p>One solution is to simply set a low cache duration, so that the cache expires in a short amount of time (e.g., 30 minutes or an hour). However, what if you have breaking news that needs to appear immediately? Or what if you have an embarrassing typo in an article that you need to fix ASAP?</p>
<p>A really simple answer is to have the ability to flush the entire site cache. This indiscriminately deletes all entries in the cache, which can cause a sudden spike in server usage as all your visitors cause the caches to be regenerated.</p>
<p>This is what we’ve been using at the YDN for the past few years, and this is workable but a bit overkill.</p>
<h3>Automated Template Fragment Cache Invalidation</h3>
<p>Ideally, we would prefer that the system magically know what pages contained what content objects, and then whenever those objects changed would invalidate all of those caches. This is an extraordinarily difficult problem to solve for all cases, but we have attempted to solve the most common cases, and leave full cache clearing as a fallback for the unusual cases.</p>
<p>Our implementation hinges on the concept of tracking the “dependencies” of each template fragment. Because it is impossible to algorithmically inspect a template’s output and determine which content objects were used to generate it, we instead rely on the template author to provide some explicit help.</p>
<p>If a template cache block depends on only a single object, template authors can use an extra ‘for’ clause on the end of the cache tag:</p>
<pre>{% cache 3600 article_page article.id for article %}
...
{% endcache %}</pre>
<p>This tells the caching system that, if the object called ‘article’ changes, it should invalidate this cache block.</p>
<p>However, often a block will contain many objects, such as a section listing or most popular box. In those cases, additional ‘cache_dep’ template tags can be used inside the ‘cache’ tag to register these additional objects.</p>
<pre>{% cache 3600 section_age section.id for section %}
  &lt;ul&gt;
    {% for article in section.articles.all %}
      {% cache_dep article %}
      &lt;li&gt;{{ article.heading }}&lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% endcache %}</pre>
<p>In this case, if ‘section’ or any of its articles get changed, this template fragment cache will be invalidated and regenerated.</p>
<p>While this adds some extra clutter to templates, we feel it is a reasonable trade-off if performance is of importance to a site.</p>
<p>In any case, the caching system will listen for post_save <a href="http://docs.djangoproject.com/en/dev/topics/signals/#topics-signals">signal</a>s from objects and then look them up in a special database table. If we find any template fragments depending on this object, we invalidate them, and we invalidate the full-page cache for that fragment’s page.</p>
<p>We have also included an <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#ref-contrib-admin-actions">admin action</a> that allow editors to manually tell an object to expire its caches.</p>
<h3>Conclusion</h3>
<p>If there is anything I’ve learned from my time at the YDN the past 2+ years, it’s been that caching is one of the most important aspects of designing a high traffic website. We’ve taken our years of experience optimizing caching for a news site and implemented a system for Courant News that will allow other sites using the platform take advantage of our experience and ensure their sites can survive large traffic spikes with aplomb.</p>
<p>In the future I’ll write more about our recommended deployment environment for Courant News and how that can influence site performance. If you are curious, you can find the Courant News caching code on our <a href="http://code.courantnews.com/browser/trunk/courant/core/caching">code site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/11/07/courant-news-caching/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>October Code Sprint Results</title>
		<link>http://www.maxcutler.com/2009/10/24/october-code-sprint-results</link>
		<comments>http://www.maxcutler.com/2009/10/24/october-code-sprint-results#comments</comments>
		<pubDate>Sun, 25 Oct 2009 03:13:13 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Courant News]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Yale Daily News]]></category>
		<category><![CDATA[headers]]></category>
		<category><![CDATA[multimedia]]></category>
		<category><![CDATA[search]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=190</guid>
		<description><![CDATA[Today Rob and I did a Courant News code sprint to get momentum building again. I did some YDN work first and then worked on finishing search functionality, while Rob focused on a new “headers” app that we’ve been brainstorming for the past week.

Multimedia
Being both an early riser and three hours ahead by virtue of [...]]]></description>
			<content:encoded><![CDATA[<p>Today <a href="http://www.rsbaskin.com">Rob</a> and I did a <a href="http://www.courantnews.com">Courant News</a> code sprint to get momentum building again. I did some YDN work first and then worked on finishing search functionality, while Rob focused on a new “headers” app that we’ve been brainstorming for the past week.</p>
<p><span id="more-190"></span></p>
<h3>Multimedia</h3>
<p>Being both an early riser and three hours ahead by virtue of time zones, I started my day working on some YDN tasks and left Courant for the afternoon. First order of business was finishing the new <a href="http://www.yaledailynews.com/multimedia/">multimedia landing page</a>. We’ve been without that page since launching on Courant at the beginning of the semester, and the version before was barely functionality as it was. Zeke Miller, the new Online Editor, was the driving force for the design while brainstorming and gathering feedback from the rest of the Online desk. I’m very pleased with the results, but have opened a <a href="http://www.copress.org/forum/weekly-discussion-topics/multimedia-landing-page-design/">thread</a> over at the CoPress forums to get feedback from the wider college news community.</p>
<h3>Search</h3>
<p>Next on the docket was finishing the transition from Sphinx to Haystack for the Courant News search system. Sphinx was very nice, but Haystack opens new doors and fits better with the Courant News project philosophy; it allows for the use of multiple search engine backends, so that sites can use whatever is most appropriate for their situation.</p>
<p>For example, if a site cannot install a powerful Java system like <a href="http://lucene.apache.org/solr/">Solr</a>, then they can use the pure-Python <a href="http://whoosh.ca/">Whoosh</a> backend (which is also nice for development use). In practice, I ran into problems while trying to use the <a href="http://xapian.org/">Xapian</a> (fast C++ engine) backend and had to switch back to the resource-heavy Solr. Hopefully as Haystack and its Xapian backend mature the situation will improve.</p>
<p>By the end of the afternoon, I had finished implementing it in Courant and had completed the templates for the YDN search system. Please feel free to <a href="http://www.yaledailynews.com/search/">explore</a>. I’m especially proud of the filtering options, which allowing for filtering of the query results by section, staff members, content type (article, photo, video, etc.), and date range. It makes it very easy to find specific content that you are looking for, or even to just get a broader sense of how popular a given topic is.</p>
<p>Solr’s relevancy engine is giving disproportionate weight to photos because they aren’t as long as articles, which is not very desirable. However, I’m still a Solr newbie and am trying to explore options for resolving that issue. Once I figure out how to do it with Solr, I’ll have to push the Haystack folks to expose any requisite functionality.</p>
<h3>Headers App</h3>
<p>Rob’s big project, and his first major code contribution in several months, was the implementation of an app we’ve been designing for the past few days. He’s going to write a more in-depth post, so I won’t step on his toes too much and go too deeply into it right now; essentially, it allows you to vary the display of your news site based on HTTP header values, most importantly User-Agent and Referer [sic].</p>
<p>The biggest example is to show a different set of templates to visitors with mobile User-Agent strings by showing them .mobile templates (using the FileExtension middleware and render() function in Courant News). You can also define a cascade of extensions, so that you only have to customize certain parts of your site if you want, and show the standard .html version elsewhere; this could be interesting if you wanted to take advantage of new HTML5 functionality in browsers (User-Agents) that support it, while not having to duplicate templates on other pages (or if you want to customize only certain pages on your mobile site for iPhone users).</p>
<p>It also lets you simply set extra template context variables, so that you can show special content to people coming from certain referrers (e.g., Facebook or Twitter). There are countless uses for such functionality, I’ll let you come up with your own.</p>
<p>You can <a href="http://code.courantnews.com/browser/trunk/courant/core/headers">browse the headers app in our code repository</a>; it only requires a bit more work before we will declare it complete, hopefully that will happen in the next several days. When Rob writes his post, I’ll update with a link.</p>
<h3>Conclusion</h3>
<p>Today was a productive day, with <a href="http://code.courantnews.com/timeline?from=10%2F24%2F09&amp;daysback=1">9 commits</a> to the Courant News repository. Hopefully the pace will keep up, and once these last few features are finalized the path will be clear to begin work on Nando, which will be the real cornerstone of the Courant News platform.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/10/24/october-code-sprint-results/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Keeping Courant with Annie Le Coverage</title>
		<link>http://www.maxcutler.com/2009/09/23/keeping-courant-with-annie-le-coverage</link>
		<comments>http://www.maxcutler.com/2009/09/23/keeping-courant-with-annie-le-coverage#comments</comments>
		<pubDate>Thu, 24 Sep 2009 04:18:01 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Courant News]]></category>
		<category><![CDATA[Yale Daily News]]></category>
		<category><![CDATA[annie le]]></category>
		<category><![CDATA[drudge report]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[templates]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=163</guid>
		<description><![CDATA[On September 2nd, the Yale Daily News published its first issue of the fall 2009 semester. Although appearing to the casual observer to be just another issue, there was one huge difference: it was running on the new Courant News online publishing platform. Just one week later, Yale graduate student Annie Le went missing. The [...]]]></description>
			<content:encoded><![CDATA[<p>On September 2nd, the Yale Daily News published its <a href="http://www.yaledailynews.com/issues/2009/09/02/">first issue</a> of the fall 2009 semester. Although appearing to the casual observer to be just another issue, there was one huge difference: it was running on the new <a href="http://www.courantnews.com">Courant News</a> online publishing platform. Just one week later, Yale graduate student <a href="http://www.yaledailynews.com/news/city-news/2009/09/09/medical-student-goes-missing/">Annie Le went missing</a>. The following ten days resulted in enormous national and international coverage of the case and a record surge in traffic to our website. Courant News played a huge role in our outstanding coverage and lack of downtime during the traffic spikes.</p>
<p><span id="more-163"></span></p>
<h3>Chronology</h3>
<p>After being a missing persons case for almost 5 days, Annie Le’s body was <a href="http://www.yaledailynews.com/news/university-news/2009/09/13/remains-found-10-amistad-street/">found</a> and suddenly it became a homicide investigation. When we published the breaking news at 8:51pm, our server was immediately slammed by an unusually large swell in traffic; in the few hours remaining in that Sunday night, we had twice as many website visitors as we typically get in an entire weekday. As the night wore on, I kept updating our editorial staff on the impressive numbers: 6,000; 8,000; 13,000 hits in 70 minutes. I eventually went to bed proud that we had survived the spike without any problems, but I was in for a surprise.</p>
<p>Out of curiosity before heading to breakfast on Monday morning, I decided to check on the server’s health. Server utilization was at 100%, and the server was really straining. I immediately went to the <a href="http://www.drudgereport.com">Drudge Report</a> and found that they had placed a link to us at the top of their front page. Out of all the national coverage available, the editor(s) at the Drudge Report had decided linked to us, and the flood gates were opened.</p>
<p style="text-align: center;"><a href="http://maxcutler.com/wp-content/uploads/2009/09/drudge_ydn.png"><img class="aligncenter size-medium wp-image-164" style="border: 0pt none;" title="Annie Le coverage on Drudge Report" src="http://maxcutler.com/wp-content/uploads/2009/09/drudge_ydn-300x185.png" alt="Annie Le coverage on Drudge Report" /></a></p>
<p>For the first six hours after Drudge posting the link, we received over 70,000 pageviews per hour before traffic slowly declined to “only” 30,000 pageviews per hour by the end of the day. In the 48 hours following, we handled a total of 1.1 million pageviews; in the 10 day period starting when she went missing, we saw over 2 million pageviews. At peak traffic, we were serving 30Mbps in data from our server, which continued for several hours. Despite the 3000% increase in traffic, we had zero downtime and our site was fully operational the entire time.</p>
<h3>Courant News’ Role</h3>
<p>In the last week of August, the YDN Editor-in-Chief and I decided to make the switch to Courant News for our first issue instead of waiting a bit longer to refine it a bit more. One of the aspects of Courant that had not yet been properly tested was performance; Courant News was designed with the lessons learned from operating a high traffic site and <a href="http://online.yaledailynews.com/2008/04/25/the-day-the-music-died/">surviving Drudge’s in the past</a>, but no special effort had been made to optimize performance yet. Fortunately, the few steps that we had taken in the spring were sufficient, and the system performed like an absolute champ throughout the spikes.</p>
<p style="text-align: center;">
<div id="attachment_176" class="wp-caption aligncenter" style="width: 410px"><a href="http://maxcutler.com/wp-content/uploads/2009/09/drudge_spike.png"><img class="size-medium wp-image-176   " style="border: 0pt none;" title="Drudge Traffic Spike" src="http://maxcutler.com/wp-content/uploads/2009/09/drudge_spike-300x34.png" alt="Hourly traffic during Drudge Report coverage" width="400" height="45" /></a><p class="wp-caption-text">Hourly traffic during Drudge Report coverage (blue); Typical weekday traffic (green)</p></div>
<p style="text-align: left;">One of the tricks that Courant employs is a full-page cache for anonymous (non-logged-in) users: when an anonymous user attempts to access a page, our <a href="http://www.nginx.net">load balancer (nginx)</a> serves them a cached version directly from RAM using <a href="http://www.danga.com/memcached/">memcached</a>. Nginx is amazing, and can handle enormous amounts of traffic with minimal server resource usage; however, Django (served by an <a href="http://www.apache.org">Apache server</a> instance), is more resource intensive, and would quickly be bogged down by too many simultaneous requests. Having nginx serve the full page caches to the swarms of anonymous Drudge Report referrals meant that very few requests were being passed through to Courant (mostly our EIC and MEs who were adding new content as the day went on).</p>
<div id="attachment_166" class="wp-caption aligncenter" style="width: 310px"><a href="http://maxcutler.com/wp-content/uploads/2009/09/yaledailynews_017.png"><img class="size-medium wp-image-166  " style="border: 0pt none;" title="Log of nginx requests during Drudging" src="http://maxcutler.com/wp-content/uploads/2009/09/yaledailynews_017-300x164.png" alt="Nginx requests/second log during Drudge Report spike" width="300" height="164" /></a><p class="wp-caption-text">Nginx requests/second log during Drudge Report spike</p></div>
<p>No downtime is great, but ultimately it’s all about the content, and our editors and reporters did an outstanding job covering the Annie Le case. Unlike many main stream media outlets that published unsubstantiated rumors, the Yale Daily News supplied top notch coverage and provided unique angles that only Yale students can provide (such as <a href="http://www.yaledailynews.com/news/university-news/2009/09/15/crime-scene-unsealed/">photos from inside the basement</a> before it was identified as the scene of the crime).</p>
<p>One of the new features that Courant News brought to the YDN site was the ability to post multiple media elements in a given article. We made judicious use of this capability, including upwards of three or four items on many articles. Our old system only allowed a single photo on each article, which would have crippled our ability to cover this story.</p>
<p>Another key capability was the ability to use multiple templates for articles and the homepage. We created a new <a href="http://www.yaledailynews.com/news/university-news/2009/09/14/body-identified-annie-le-med-13/">“Big Photo”</a> article template to highlight the top media item on many of our stories. We also created a number of new <a href="http://www.yaledailynews.com/issues/2009/09/14/">homepage</a> <a href="http://www.yaledailynews.com/issues/2009/09/16/">templates</a> to highlight our breaking news coverage (note: because we only archive one version of the homepage per day, I cannot show  some of the additional templates we used).</p>
<p>To support the amount of content we were publishing, Courant News allowed us to give limited access to the administrative interface to our Photo Editors and some Production &amp; Design staffers, who helped the EIC and MEs upload content and publish new information in a timely manner. This distribution of work is something that we would like to continue going forward, eliminating the excuse of publishing extra content online being too much work at the end of the night.</p>
<p>Finally, Courant News included new <a href="http://maxcutler.com/blog/2009/07/19/courant-news-email-engine">email</a> and <a href="http://maxcutler.com/blog/2009/08/12/portland-courant-news-short-urls">analytics</a> tracking systems, which allowed us to push breaking news updates to our email subscribers and track engagement from emails and our Twitter updates. Such data nicely complements our Google Analytics reports regarding readership engagement and has provided insight into ways we can improve our coverage in the future.</p>
<h3>Conclusion</h3>
<p>Moving to a new CMS and publishing platform can be a risky endeavor, but Courant News has pulled its weight and played a critical supporting role in our ability to cover this story and survive the massive influx of traffic it brought us. With a promising future ahead of it, including the <a href="http://groups.google.com/group/courantnews/browse_thread/thread/890dc88b05c45e7b">digital newsroom</a> and other <a href="http://code.courantnews.com/wiki/ProjectIdeas">exciting new features</a>, Courant News will help us at the Yale Daily News innovate and experiment with our website in the coming years. I see many interesting projects in our future this year, and I look forward to helping other news organizations take the next step and join us in developing the Courant News platform for the betterment of all college news organizations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/09/23/keeping-courant-with-annie-le-coverage/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Seeking Web/UX Designer</title>
		<link>http://www.maxcutler.com/2009/09/10/seeking-webux-designer</link>
		<comments>http://www.maxcutler.com/2009/09/10/seeking-webux-designer#comments</comments>
		<pubDate>Thu, 10 Sep 2009 14:14:24 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[College News]]></category>
		<category><![CDATA[Courant News]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[nando]]></category>
		<category><![CDATA[ux]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=161</guid>
		<description><![CDATA[Last night I posted a cryptic job offering on Twitter, even offering to pay for the work. After getting a number of private queries for more information, I thought I’d make my request public instead of privately emailing half a dozen people.

Background
As you might have gathered from my other blog posts, I am, first and [...]]]></description>
			<content:encoded><![CDATA[<p>Last night I posted a <a href="http://twitter.com/maxcutler/status/3879867359">cryptic job offering</a> on Twitter, even offering to <a href="http://twitter.com/maxcutler/status/3879874902">pay</a> for the work. After getting a number of private queries for more information, I thought I’d make my request public instead of privately emailing half a dozen people.</p>
<p><span id="more-161"></span></p>
<h3>Background</h3>
<p>As you might have gathered from my other blog posts, I am, first and foremost, a developer. I’ve done stints as the combo designer-and-developer for sites, but I’ve learned that my design skills are lacking and have tried to find more talented partners when working on projects that require interfaces.</p>
<p>Last week, the <a href="http://www.yaledailynews.com">first site</a> was launched on the Courant News platform. There are still a slew of template bugs that I’m working through, but the platform has performed admirably over the past week. It currently uses a more-or-less stock Django admin interface with the <a href="http://code.google.com/p/django-grappelli/">grappelli</a> skin. However, the ultimate goal is that of the digital newsroom and <a href="http://groups.google.com/group/courantnews/browse_thread/thread/890dc88b05c45e7b">Nando</a>.</p>
<h3>The Job</h3>
<p>I am seeking a web/UX designer to work with me on designing the Nando interface. For those not familiar, Nando is the codename for the admin interface in the Courant News publishing platform for college news sites; it combines standard CRUD content management with a digital newsroom and the ability to manage an organization’s site from the web interface without touching code. For full details, you can read through the <a href="http://groups.google.com/group/courantnews/browse_thread/thread/890dc88b05c45e7b">spec and the first round of community comments</a>.</p>
<p>Because Courant News is an open source project, we don’t have the money to pay a huge amount for this work, but I am willing to work out monetary and other forms of compensation and negotiate terms of the work with interested individuals. When Nando is complete, Courant News will represent one of the best options for college news sites who embrace the web-first mentality and want to push the boundaries of online journalism; by working on designing Nando, your mark will be left on all of these endeavors and will touch members of the next generation of journalists.</p>
<h3>Contact Me</h3>
<p>So if you are interested or have questions, please send me an email (maxcutler AT gmail DOT com) or find me on AIM (S/N: Goaliexam).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/09/10/seeking-webux-designer/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Portland &amp; Courant News: Short URLs</title>
		<link>http://www.maxcutler.com/2009/08/12/portland-courant-news-short-urls</link>
		<comments>http://www.maxcutler.com/2009/08/12/portland-courant-news-short-urls#comments</comments>
		<pubDate>Thu, 13 Aug 2009 03:44:39 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Courant News]]></category>
		<category><![CDATA[portland]]></category>
		<category><![CDATA[short urls]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=156</guid>
		<description><![CDATA[This past Saturday I joined Daniel Bachhuber and David Estes in Portland to talk journo dev projects. We talked about workflow engines, news wikis, virtual assignment desks, and other miscellaneous topics, but eventually Daniel and I got to work on building a simple short URL app for Django/Courant News.

There is certainly no shortage of short [...]]]></description>
			<content:encoded><![CDATA[<p>This past Saturday I joined <a href="http://www.danielbachhuber.com">Daniel Bachhuber</a> and <a href="http://www.davidme.com">David Estes</a> in Portland to talk journo dev projects. We talked about workflow engines, news wikis, virtual assignment desks, and other miscellaneous topics, but eventually Daniel and I got to work on building a simple short URL app for Django/Courant News.</p>
<p><span id="more-156"></span></p>
<p>There is certainly no shortage of short URL services in existence, with <a href="http://bit.ly">bit.ly</a> currently being the most popular. However, as the recent existential crisis at tr.im has shown, trusting these services is sometimes not the best idea. In addition, there are numerous advantages (enumerated elsewhere) to hosting your short URLs on your own domain name.</p>
<h3>Referral Tracking</h3>
<p>As news orgs strive to find ways of attracting traffic to their websites, evaluating the effectiveness of distribution through different mediums is critical. How much traffic comes from email newsletters? Twitter? Facebook? the print edition?</p>
<p>Some or all of such mediums will not pass HTTP referrer headings, which means it is difficult or impossible to track using normal methodology. If you are using Google Analytics or similar service, the best you can likely do is add an HTTP GET parameter to the end of the link and convert that on the server side. However, it is easy for users to strip this off and is far from foolproof.</p>
<p>Alternatively, we can generate a different short URL for each of the target mediums and then track hits before/during the redirection step. That’s the route we chose for our app.</p>
<h3>Short URL Types</h3>
<p>There are a few strategies to generating actual short URL strings. Most of the popular services just use incremental keys that are encoded in base-32 or similar (converts a number to a string consisting of A-Z, a-z, 0–9 and perhaps some punctuation characters).</p>
<p>That works well with huge volume, as a single individual is unlikely to generate consecutive URL tokens. However, when you host your own URL shortener, all URLs generated on a given day will look very similar using this approach, which may or may not be problematic.</p>
<p>I, personally, prefer more diverse URLs for tokens created in a sequence. Since the point of per-medium URLs is to reliably track referrers, we don’t want users to easily guess what the URL for another medium is and thus spoof our service (or just accidentally mistype them).</p>
<p>Therefore, our short URL app supports both generation types: consecutive sequence (GHn8n, GHn8o, GHn8p) or a pseudo-random generator (GHn8n, SfMgo, ednto).</p>
<p>If you want a custom URL for a special case, you can manually create a new short URL through the admin interface and manually specify whatever URL value you desire.</p>
<h3>Primary vs. Secondary Domain</h3>
<p>The YDN has a very long domain name, so we want to use a shorter domain name (goydn.com) for our short URLs. However, some orgs, such as David’s DailyUW.com may want to just use their normal domain. Thus our app supports both scenarios.</p>
<p>If you want to use your primary domain, we recommend you put it under some prefix, such as /go/ or /g/, to avoid collisions with other valid URLs (e.g., /news/). However, if you want to play with fire, you can configure your short URLs to work at the top level of your primary domain without problems.</p>
<p>Do note that short URLs will only get checked if the page requested would have otherwise returned a 404 error.</p>
<h3>App Models</h3>
<p>The first model in our app is <em>ShorturlMedium</em>, which is simply a named object representing a given medium like “Print”, “Twitter” or whatever your org needs.</p>
<p>The core of our app is the <em>Shorturl</em> model, which maps a <em>ShorturlMedium</em> to a content object (using Django’s content type app) and stores the actual short URL.</p>
<p>Finally, we have the <em>ShorturlHit</em> model, which tracks hits for a given per-medium short URL. I have not yet generated any report generation tools, but that should be an easy work item in the future and will surely be a part of Nando.</p>
<h3>Template Tags</h3>
<p>To put short URL links on your pages, we have a simple template tag to get (and generate, if necessary) one for a given content object (article, page, event, etc.).</p>
<pre>{% load shorturls %}
{% shorturl obj Twitter %}</pre>
<p>That’s it. The first parameter is the content object variable, and the second is the medium you want it to run in.</p>
<h3>Conclusion</h3>
<p>Our short URL app is pretty simple, but is configurable to meet the needs of most college news deployment scenarios. Because it ties into your content behind the scenes, it won’t break when you change your normal URL structures and supports any new models you add to the system. In a few months, after we use the system in production, I’ll post a followup analyzing the analytics data we gather from it.</p>
<p>Code can be found in the Courant News <a href="http://code.courantnews.com/browser/trunk/courant/contrib/shorturls">code repo</a>. Parts were based on <a href="http://code.google.com/p/django-ittybitty/">django-ittybitty</a>, but we strayed far enough away in purpose and implementation that it didn’t make sense to just treat our code as a patch. Let me know if you have any questions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/08/12/portland-courant-news-short-urls/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Courant News: Email Engine</title>
		<link>http://www.maxcutler.com/2009/07/19/courant-news-email-engine</link>
		<comments>http://www.maxcutler.com/2009/07/19/courant-news-email-engine#comments</comments>
		<pubDate>Sun, 19 Jul 2009 18:18:29 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Courant News]]></category>
		<category><![CDATA[chronograph]]></category>
		<category><![CDATA[email]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=142</guid>
		<description><![CDATA[As I work on the last pieces needed to launch the YDN on Courant next month, I finally got around to implementing the email engine for Courant and the YDN site.

Goals/Requirements
There were a few basic requirements necessitated by the quantity of emails that the YDN handles on a daily basis (on the order of several [...]]]></description>
			<content:encoded><![CDATA[<p>As I work on the last pieces needed to launch the YDN on Courant next month, I finally got around to implementing the email engine for Courant and the YDN site.</p>
<p><span id="more-142"></span></p>
<h3>Goals/Requirements</h3>
<p>There were a few basic requirements necessitated by the quantity of emails that the YDN handles on a daily basis (on the order of several thousand subscribers):</p>
<ol>
<li>Process the email queue asynchronously from the web server process. Sending thousands of emails takes a long time, and we don’t want to tie up our web server during that time.</li>
<li>When administrators/editors submit new mass email jobs (e.g., daily headlines), they should not have to wait around for the server to process that request. The page should quickly load and the processing should be done async/out-of-band.</li>
<li>Since emails could potentially be customized, avoid reliance on bcc: field. Essentially, each user gets their own email object in the system.</li>
</ol>
<h3>Implementation</h3>
<p>For the email engine itself, I started with the <a href="http://github.com/brosner/django-mailer/tree/master">django-mailer</a> app as my foundation. It stores emails in a queue in the database, and a command-line management command is run by cron every x minutes to process queued emails. I also took some patches from various forks to handle <a href="http://github.com/istruble/django-mailer/commit/50bd5fd56e83d975f5c0aadb03be17fc49261e60">reuse of the SMTP connection</a>, <a href="http://github.com/istruble/django-mailer/tree/simple_html_mail">streamlined HTML+Text email creation</a>, and a <a href="http://github.com/pmclanahan/django-mailer/commit/f713e47c2fe8ebd1e89f2e39d2d0a0e6f2afa2a5">limit on the number of emails</a> the management command processes at one time.</p>
<p>On the interface side, I created a Django <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#ref-contrib-admin-actions">admin action</a> for both issues and articles that will render templates for the text and HTML versions and then create  a django-mailer Message instance for each subscriber. I quickly discovered that this only meets the above requirements for very small subscriber sets. With 5000 subscribers, it took about 45 seconds on my dev VM to generate all the emails and save them in the database; while that was happening, the browser would wait for a response, possibly timing out in the interim.</p>
<p>This clearly didn’t meet requirement #2, so I had to add another step to the process. When the admin action executes, it would create the email contents and store that in a new model, MessageJob, which had a simple TextField containing a delimited list of email addresses to send to. Then I created a new management command that will process MessageJobs into all the individual Messages when called by cron.</p>
<p>So now the execution flows looks like this (see images at end of post):</p>
<ol>
<li>Editor checks box next to an issue, selects “Send email update” admin action option, and hits “Go” (submits the action form)</li>
<li>A MessageJob is generated containing the text and HTML versions of the email, the subject line, from address, and delimited list of recipients. Page loads for editor and displays message confirming that job has been queued.</li>
<li>System cron soon calls “manage.py process_mail_jobs”, which pulls out any unprocessed MessageJobs and creates a new Message instance for each recipient.</li>
<li>System cron soon calls “manage.py send_mail” which attempts to send all the Messages in the queue in the database. If any fail to send, they will be retried when cron calls “manage.py retry_deferred” (standard django-mailer behavior).</li>
</ol>
<p>Those three cron jobs get called every minute (configurable if you want less frequently, though there is almost no penalty for calling them if the queues are empty), either by manually setting your user crontab or by using an app like <a href="http://code.google.com/p/django-chronograph/">django-chronograph</a> (which will come pre-configured with Courant News).</p>
<h3>Conclusion</h3>
<p>So the modified django-mailer system with the admin actions integration meets all of the requirements we had defined for the email engine. The next step will be to implement the <a href="http://code.courantnews.com/wiki/EmailSubscriptionSpec">email subscription spec</a> that Rob and I wrote back in December, though that work may be deferred to version 2.</p>
<p>I have not yet done extensive performance tests comparing use of a local mail server (e.g., Exim) vs. an external service (e.g., Gmail), but that’s something I’ll be exploring in the not-too-distant future. Even if the email sending process takes a long time, the users of the website and admin should not notice, and system performance should be well within acceptable bounds. User registration, password reset and other emails will have higher priorities and jump to the top of the queue, so even while processing a large subscription queue those critical messages will still be (almost) immediately sent out.</p>
<p>I’m holding off on checking this work into the public Courant News repository as I currently have a mess of Nando stuff interleaved, and I need to sort that out first. I also want to add some forms and views for handling creation of email subscriptions on the public website, so maybe once that is complete I’ll push through a checkin.</p>

<a href='http://www.maxcutler.com/2009/07/19/courant-news-email-engine/action' title='action'><img width="150" height="150" src="http://www.maxcutler.com/wp-content/uploads/2009/07/action-150x150.png" class="attachment-thumbnail" alt="" title="action" /></a>
<a href='http://www.maxcutler.com/2009/07/19/courant-news-email-engine/flash_message' title='flash_message'><img width="150" height="150" src="http://www.maxcutler.com/wp-content/uploads/2009/07/flash_message-150x150.png" class="attachment-thumbnail" alt="" title="flash_message" /></a>
<a href='http://www.maxcutler.com/2009/07/19/courant-news-email-engine/message_job' title='message_job'><img width="150" height="150" src="http://www.maxcutler.com/wp-content/uploads/2009/07/message_job-150x150.png" class="attachment-thumbnail" alt="" title="message_job" /></a>
<a href='http://www.maxcutler.com/2009/07/19/courant-news-email-engine/email' title='email'><img width="150" height="150" src="http://www.maxcutler.com/wp-content/uploads/2009/07/email-150x150.png" class="attachment-thumbnail" alt="" title="email" /></a>

]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/07/19/courant-news-email-engine/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Clean Install Software</title>
		<link>http://www.maxcutler.com/2009/07/14/clean-install-software</link>
		<comments>http://www.maxcutler.com/2009/07/14/clean-install-software#comments</comments>
		<pubDate>Tue, 14 Jul 2009 19:02:03 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://maxcutler.com/blog/?p=139</guid>
		<description><![CDATA[With all the talk of web versus desktop lately, I decided to reflect on what software I use outside of my web browser. A good way to think about this is to list all the software that you install on a fresh installation of your operating system (Windows, OSX, or Linux).

Over the past 6 months [...]]]></description>
			<content:encoded><![CDATA[<p>With all the talk of web versus desktop lately, I decided to reflect on what software I use outside of my web browser. A good way to think about this is to list all the software that you install on a fresh installation of your operating system (Windows, OSX, or Linux).</p>
<p><span id="more-139"></span></p>
<p>Over the past 6 months I’ve been installing new builds of Windows 7 every month or two on one of my laptops.</p>
<h3>General Programs</h3>
<p>The set of programs I install after each wipe:</p>
<ul>
<li><a href="http://www.microsoft.com/office/2010/">Microsoft Office</a> (productivity suite)</li>
<li><a href="http://www.getfirefox.com">Firefox</a> &amp; <a href="http://www.opera.com">Opera</a> (web browsers)</li>
<li><a href="http://trillian.im/">Trillian</a> (multi-protocol IM client)</li>
<li><a href="http://www.twhirl.org/">Twhirl</a> (Twitter client)</li>
<li><a href="http://www.pandora.com">Pandora</a> desktop client (internet radio)</li>
<li><a href="http://www.itunes.com">iTunes</a> (music for personal music device)</li>
<li><a href="http://www.adobe.com">Adobe Reader</a> or <a href="http://www.foxitsoftware.com/">Foxit</a> (PDF reader)</li>
<li><a href="http://www.7-zip.org">7-zip</a> (zip/tar archive creator/extractor)</li>
<li><a href="http://www.slingmedia.com">Sling Media Player</a> (watch home TV from across internet)</li>
</ul>
<h3>Development Tools</h3>
<p>I also have a bunch of development tools:</p>
<ul>
<li><a href="http://www.winscp.net">WinSCP</a> (FTP/SCP client)</li>
<li><a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">Putty</a> (SSH client)</li>
<li><a href="http://www.apachefriends.org/en/xampp-windows.html">XAMPP</a> (LAMP stack)</li>
<li><a href="http://www.python.org">Python</a> (programming language)</li>
<li><a href="http://www.vmware.com/workstation">VMWare Workstation</a> (virtual machine environment)</li>
<li><a href="http://www.activestate.com">Komodo IDE</a> (programming environment)</li>
<li><a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> and <a href="http://git-scm.com/">GIT</a> (source control integration)</li>
<li><a href="http://www.adobe.com/products/creativesuite/">Adobe Creative Suite</a> (Photoshop, etc.)</li>
</ul>
<p>There’s probably some that I’m missing, but those are all the ones that I use most often.</p>
<h3>Conclusion</h3>
<p>I think it’s safe to say that it’s near impossible to replace my development setup within my browser, but honestly “most” of the population doesn’t do such work.</p>
<p>On the general software side, I could probably get by with just a browser. Twitter, IM, Pandora, Office Web/Google Apps, etc. could replace many of the programs that I listed. I’d still have some issues with zip files and watching TV through my SlingBox, but my general needs could be satisfied. Yet I currently decide to use the desktop versions of these apps, because I can run them nicely in the background, with OS notifications, and automatic startup at system boot.</p>
<p>I’m curious to see what other people use and how readily they could forgo everything but a browser.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maxcutler.com/2009/07/14/clean-install-software/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
