<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss version="2.0"><channel><description>Stuff to look at about looking at stuff. From Chris Dent. What?




    




me@twitter












</description><title>Peer Pressure</title><generator>Tumblr (3.0; @cdent)</generator><link>http://cdent.tumblr.com/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/cdent" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Indexed TiddlyWeb Filters</title><description>&lt;p&gt;One of the core features of &lt;a href="http://tiddlyweb.com/"&gt;TiddlyWeb&lt;/a&gt; is its ability to use filters to constrain the tiddlers that are selected from any collection of tiddlers (bag, recipe, search results, etc.). In the early design discussions that led to the creation of TiddlyWeb filters were conceived as the mechanism a recipe would use to choose only some tiddlers from a bag. Bags are containers for tiddlers that have been grouped together for some reason. Recipes are lists of bags that lead to the creation of some useful set of tiddlers. When using TiddlyWeb and TiddlyWiki together, a recipe can create a particular application or vertical of TiddlyWiki. In that context one would use a filter to select some tiddler tagged “systemConfig” from one bag, others tagged “faq” from another, and others with modifier “cdent” from another.&lt;/p&gt;

&lt;p&gt;When TiddlyWeb is used generally as a data store, filters are just as useful. When requesting tiddlers from any bag you can select and sort by attributes, and limit the number of tiddlers. Application developers can also make new filters as plugins (see &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/mselect/"&gt;mselect&lt;/a&gt; for an example).&lt;/p&gt;

&lt;p&gt;This is all quite grand and useful but recent explorations by &lt;a href="http://softwareas.com/"&gt;Mike Mahemoff&lt;/a&gt; while developing &lt;a href="http://scrumptious.tv/"&gt;Scrumptious&lt;/a&gt; have revealed some (fairly expected) problems. Imagine a bag called “comments” containing some 10,000 or more tiddlers which are comments on URLs. Now imagine you’d like to get those tiddlers which have the field ‘url’ set to &lt;a href="http://cdent.tumblr.com/."&gt;http://cdent.tumblr.com/.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The naive way to do this is to look at each one of those tiddlers, one at a time, and say “Hello tiddler, have you got your url field set to &lt;a href="http://cdent.tumblr.com/?"&gt;http://cdent.tumblr.com/?&lt;/a&gt; Oh you do? Well then I’ll have you, thanks!” This is time consuming and resource intensive.&lt;/p&gt;

&lt;p&gt;It is also the way TiddlyWeb does filters. It’s like this for a few different reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The original design imagined many bags, not few bags with large numbers of tiddlers.&lt;/li&gt;
&lt;li&gt;It preserves the strict separation between the filter system and the storage system, meaning that the storage system can be simple and very adaptable: any filter can work with any store.&lt;/li&gt;
&lt;li&gt;It makes the filter system fairly transparent: There’s no magic going on; a filter works by looking at tiddlers and making a decision.&lt;/li&gt;
&lt;li&gt;It makes the filter system easy to extend: The contract between a filter and the rest of the system is “look at some tiddlers, return some tiddlers”. What the filter does when looking is arbitrary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href="http://github.com/tiddlyweb/tiddlyweb/commit/9bb5c15b26584e1d631dd6f57c4a7ff86b77f911"&gt;0.9.74 release of TiddlyWeb&lt;/a&gt; includes support for querying an index when doing select style filters. The support only kicks in in special circumstances (explained below) but when it does it can speed some filters up &lt;em&gt;immensely&lt;/em&gt;. In a test (using &lt;a href="http://github.com/tiddlyweb/tiddlyweb/blob/master/profile/list_tiddlers.py"&gt;profile/list_tiddlers.py&lt;/a&gt;) of 10000 tiddlers a filter that took 13.96 seconds without an index took .30 seconds with an index.&lt;/p&gt;

&lt;p&gt;That’s great news. Here’s the bad news: In at least this initial implementation the prerequisites for the indexing system to be used (and be useful) are quite complex. Here’s the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The filter being performed must be a select filter (sort and limit do not).&lt;/li&gt;
&lt;li&gt;If there are multiple filters being performed on the collection of tiddlers, the select filter must be &lt;em&gt;first&lt;/em&gt; in the stack and only that one filter will use the index.&lt;/li&gt;
&lt;li&gt;The collection of tiddlers must be what’s called a “natural” bag. That is, the thing being filtered is a bag that exists in the store and the entire contents of the bag is what’s desired to be filtered.&lt;/li&gt;
&lt;li&gt;That bag should be &lt;em&gt;skinny&lt;/em&gt;, meaning when it was loaded from the store its tiddlers contents was not determined. If you are processing recipes or working from URLs this is handled for you by the code. It’s only a concern if you are writing your own handlers.&lt;/li&gt;
&lt;li&gt;tiddlyweb.config[‘indexer’] is set to a string which is the name of a module which provides an &lt;code&gt;index_query(environ, **kwargs)&lt;/code&gt; callable that returns tiddlers which have been loaded from the store. &lt;a href="http://pypi.python.org/pypi/tiddlywebplugins.whoosher"&gt;tiddlywebplugins.whoosher&lt;/a&gt; has been updated to provide this and the next item.&lt;/li&gt;
&lt;li&gt;Something must provide an index for index_query to query. That index needs to be kept up to date as tiddlers are changed. tiddlywebplugins.whoosher has this functionality. The &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/sqlstore/"&gt;sql&lt;/a&gt; and &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/mappingsqlstore/"&gt;mappingsql&lt;/a&gt; have the guts to make the functionality possible, but have not yet been extended with an &lt;code&gt;index_query&lt;/code&gt; method.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The TiddlyWeb at &lt;a href="http://tiddlyweb.peermore.com/"&gt;http://tiddlyweb.peermore.com/&lt;/a&gt; has been updated to use the filter indexes. The relevant changes to the &lt;code&gt;tiddlywebconfig.py&lt;/code&gt; are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;tiddlywebplugins.whoosher&lt;/code&gt; to &lt;code&gt;twanager_plugins&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;tiddlywebplugins.whoosher&lt;/code&gt; to &lt;code&gt;system_plugins&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;indexer&lt;/code&gt; to &lt;code&gt;tiddlywebplugins.whoosher&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then &lt;code&gt;twanager wreindex&lt;/code&gt; is run to build the initial &lt;a href="http://whoosh.ca"&gt;Whoosh&lt;/a&gt; index.&lt;/p&gt;

&lt;p&gt;You can get some sense of the effects of the index by comparing the following to URLs (this is not an exact test, but gives the sense of things):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not indexed: &lt;a href="http://tiddlyweb.peermore.com/wiki/bags/docs/tiddlers?limit=5000;select=tag:systemConfig"&gt;http://tiddlyweb.peermore.com/wiki/bags/docs/tiddlers?limit=5000;select=tag:systemConfig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Indexed: &lt;a href="http://tiddlyweb.peermore.com/wiki/bags/docs/tiddlers?select=tag:systemConfig;limit=5000"&gt;http://tiddlyweb.peermore.com/wiki/bags/docs/tiddlers?select=tag:systemConfig;limit=5000&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The docs bag only has a couple hundred tiddlers in it and memcached is involved, so the effect is not huge, but if you imagine bags orders of magnitude bigger…&lt;/p&gt;

&lt;p&gt;Astute observers will note that what’s going on here is not particularly innovative: It’s simply the addition of an index to a query system. One can imagine future improvements a la SQL query optimization, wherein the order of the filters are adjusted to allow most effective use of the index, and the index is used for more queries than just those against “natural” bags. Constant evolution, constantly building on the shoulders of that which has come before.&lt;/p&gt;

&lt;p&gt;For more details, a browse of the code will be instructive. &lt;code&gt;tiddlyweb.control:filter_tiddlers_from_bag&lt;/code&gt; is a good entry point.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/233932281</link><guid>http://cdent.tumblr.com/post/233932281</guid><pubDate>Thu, 05 Nov 2009 14:25:08 +0000</pubDate><category>tiddlyweb</category></item><item><title>TiddlyWeb Value Proposition</title><description>&lt;p&gt;A common question associated with &lt;a href="http://tiddlyweb.com/"&gt;TiddlyWeb&lt;/a&gt; is “What can I do with it?” or “Why would I want to use it instead of &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; or something?” The answer is not simple.&lt;/p&gt;

&lt;p&gt;Because TiddlyWeb has tools for storing data and presenting that data in various forms over HTTP, it has some of the core features of a web application framework. However, since it (intentionally) is also missing some of the core features of a web application framework, a fair piece of cognitive dissonance can happen when the tool is approached as a web application framework.&lt;/p&gt;

&lt;p&gt;So it seems best to stay away from saying that TiddlyWeb is a web application framework, so as to manage expectations. The question remains, “What is it?”&lt;/p&gt;

&lt;p&gt;One pathway to answering that question is to create tools with it and see what the commonalities are between those tools. A derivative of this approach is to create a killer app with TiddlyWeb: a &lt;em&gt;something&lt;/em&gt; which demonstrates all the salient features and how to use them, both as a user and as a developer.&lt;/p&gt;

&lt;p&gt;This approach seems to falter: The concepts in TiddlyWeb are sufficiently strange (I won’t say unique, because they aren’t that, they are common concepts, with their own spin) that in order to create a tool that uses them well you first need to either understand them in the abstract, or see some examples. Catch 22, especially if you are an examples oriented person.&lt;/p&gt;

&lt;p&gt;FND and I tend to converse on this topic about daily, trying to come up with different strategies for answering it. Today I suggested that instead of creating a new application, from scratch, that is cool and interesting because it uses TiddlyWeb, it might be better to find some application that could be made better through the addition or inclusion of TiddlyWeb.&lt;/p&gt;

&lt;p&gt;It turns out this process has already started and by analyzing that process we might understand TiddlyWeb better.&lt;/p&gt;

&lt;p&gt;The process has started with TiddlyWiki. TiddlyWiki is made better for a particular set of use cases by taking advantage of TiddlyWeb features. The fundamental experience of TiddlyWiki does not change: you’ve still got a wiki in an HTML file, with these things called tiddlers, some of which are special plugins that change behaviors.&lt;/p&gt;

&lt;p&gt;What TiddlyWeb adds when used with TiddlyWiki is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralization of content storage, storing at the level of the tiddler, with revisions, protection against editing conflicts and access control to read, write, create and delete; accessible from multiple locations on the network.&lt;/li&gt;
&lt;li&gt;A (hopefully) straightforward system of managing access control of tiddlers and making other kinds of groupings of tiddlers through the use of bags. Bags are collections of uniquely named Tiddlers.&lt;/li&gt;
&lt;li&gt;A system for composing functional collections of tiddlers selected from multiple bags using recipes. Recipes are list of bags paired with filters. Filters are rules which limit the tiddlers pulled from a bag when processing the recipe.&lt;/li&gt;
&lt;li&gt;Tools for viewing and manipulating tiddlers in different forms than those used in the wiki (e.g. JSON, Atom).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These four things together provide a multi-user environment for TiddlyWiki that allows multiple custom views of the same or similar content, depending on some piece of context. Different recipes can provide a different view on the same stuff, providing a different look and feel, different security handling, etc.&lt;/p&gt;

&lt;p&gt;TiddlyWeb has many other features, but the above four are probably the key aspects which define its special sauce. When I evaluate a nascent TiddlyWeb tool for its tiddly-fitness the evaluation is done based on the extent to which the system takes advantage of and understands the above features.&lt;/p&gt;

&lt;p&gt;These ideas should allow us to create some mental heuristics to use when approaching a TiddlyWeb project. If we have an existing project or use case that we intuit will be helped by using TiddlyWeb we can ask ourselves: 1) What aspects of this project will benefit from bags, recipes and filters? 2) How can we take advantage of different representations?&lt;/p&gt;

&lt;p&gt;If, for some reason, we are planning to make a project from scratch, and have decided to use TiddlyWeb prior to really evaluating our use cases, then we can ask ourselves: 1) How can we best structure our data and UI to use recipes, bags and filters to provide flexible user experiences? 2) What representations can we present to allow other people to provide flexible user experiences?&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/225212920</link><guid>http://cdent.tumblr.com/post/225212920</guid><pubDate>Tue, 27 Oct 2009 21:39:31 +0000</pubDate><category>tiddlyweb</category></item><item><title>Python Namespace Packages for TiddlyWeb</title><description>&lt;p&gt;In Friday’s &lt;a href="http://cdent.tumblr.com/post/214629671/tiddlyweb-dev-deploy-workshop"&gt;TiddlyWeb Dev/Deploy Workshop posting&lt;/a&gt; I said that mature plugins need to be packaged so they can be indexed by &lt;a href="http://pypi.python.org/"&gt;PyPI&lt;/a&gt; and installed via &lt;code&gt;easy_install&lt;/code&gt; and &lt;code&gt;pip&lt;/code&gt;. At base this is relatively straightforward, put some stuff in a directory, make a setup.py, register the package, package up a source distribution, tell PyPI about it.&lt;/p&gt;

&lt;p&gt;This is okay if you have a good name for your package, but what about packages, like plugins for TiddlyWeb, which have names which are only meaningful in their use context? You can’t just use the name of the module, otherwise you end up with namespace collisions, trouble finding stuff, and associated beasts of chaos.&lt;/p&gt;

&lt;p&gt;Thankfully distutils, setuptools, pip, etc conspire to support a notion called &lt;code&gt;namespace_packages&lt;/code&gt; which can solve this issue. Unfortunately using the feature is not exceptionally well documented. I found getting started a bit frustrating, until I sort of cracked the nut. Here’s some info for reference.&lt;/p&gt;

&lt;p&gt;First some prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You need &lt;a href="http://peak.telecommunity.com/DevCenter/setuptools"&gt;setuptools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You need a username and password on &lt;a href="http://pypi.python.org/pypi?%3Aaction=register_form"&gt;PyPi&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Some understanding of how to make a python package distribution. Here’s one tutorial: &lt;a href="http://www.siafoo.net/article/77"&gt;Use setup.py to Deploy Your Python App with Style&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Some understanding of Python &lt;a href="http://docs.python.org/tutorial/modules.html#packages"&gt;packages&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That tutorial includes a section about using &lt;code&gt;namespace_packages&lt;/code&gt; under the heading “Multiple Distributions, One (Virtual) Package”. &lt;em&gt;That “Virtual” is key:&lt;/em&gt; if you wish to use namespace packages there much be &lt;em&gt;no&lt;/em&gt; real distribution which occupies the namespace. In the example of tiddlywebplugins, you can have tiddlywebplugins.static and tiddlywebplugins.utils distributions which are members of the tiddlywebplugins namespace, but you must not have a tiddlywebplugins distribution. If you do the packages which are supposed to occupy the virtual namespace will not be found. The upshot of this is that if you already have a package out there using a name that you want to use as a namespace, you will need to rename the existing package (this is why the old tiddlywebplugins package is now &lt;a href="http://pypi.python.org/pypi/tiddlywebplugins.utils"&gt;tiddlywebplugins.utils&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Packaging a Plugin&lt;/h3&gt;

&lt;p&gt;So say you have a TiddlyWeb plugin called foobar.py sitting in a directory somewhere. You’ve determined that it is a happy little plugin and the world would benefit if it could be installed easily. You’ve heard of the tiddlywebplugins namespace and you’d like to join the party. Here’s what you do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In that directory make a &lt;code&gt;tiddlywebplugins&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;tiddlywebplugins/__init__.py&lt;/code&gt; to include just this line: &lt;code&gt;__import__("pkg_resources").declare_namespace(__name__)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Move foobar.py into the tiddlywebplugins directory.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;setup.py&lt;/code&gt; (in the original directory) that includes at least:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;
     from setuptools import setup, find_packages

     setup(
         version = '0.1',
         namespace_packages = ['tiddlywebplugins'],
         name = 'tiddlywebplugins.foobar',
         description = 'A TiddlyWeb plugin for foobaring the fritz.',
         install_requires = ['setuptools', 'tiddlyweb'],
         )
&lt;/pre&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Do not import from the tiddlywebplugins package in setup.py.&lt;/em&gt; This will make installs struggle or fail later.&lt;/li&gt;
&lt;li&gt;Learn enough about distribution to register the package and upload it. The links above point to enough documentation to figure that part out. If you can’t be bothered to read that documentation then you shouldn’t be distributing packages. We wouldn’t want you aoling all over PyPi.&lt;/li&gt;
&lt;li&gt;When you want to use your foobar plugin in a TiddlyWeb &lt;a href="http://tiddlyweb.peermore.com/wiki/recipes/docs/tiddlers/instance"&gt;instance&lt;/a&gt; or application refer to it as &lt;code&gt;tiddlywebplugins.foobar&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><link>http://cdent.tumblr.com/post/216241761</link><guid>http://cdent.tumblr.com/post/216241761</guid><pubDate>Sun, 18 Oct 2009 13:00:00 +0100</pubDate><category>tiddlyweb</category><category>python</category></item><item><title>TiddlyWeb Dev/Deploy Workshop</title><description>&lt;p&gt;Yesterday I gathered with the &lt;a href="http://www.osmosoft.com/"&gt;Osmosoft&lt;/a&gt; gang to discuss developing and deploying applications that are built on top of &lt;a href="http://tiddlyweb.com/"&gt;TiddlyWeb&lt;/a&gt;. Since I mostly develop TiddlyWeb itself and not things built upon it, I tend to be fairly distanced from the issues so getting together and having a chat and messing about with some code was a good thing.&lt;/p&gt;

&lt;p&gt;Mike has &lt;a href="http://softwareas.com/actions-and-conclusions-from-tiddlyweb-devdeploy-workshop"&gt;written up his summary&lt;/a&gt; of the things to do next. I took some notes as well, which I’ll attempt to summarize here.&lt;/p&gt;

&lt;p&gt;To get a sense of the issues we went around the room and people reported on how they’ve been managing development and deployment and what’s working well and what’s not. There were some but not many common threads.&lt;/p&gt;

&lt;p&gt;One common issue is that most of the people have a tendency to do a code a bit, reload a web page cycle of development and test. When using &lt;code&gt;twanager server&lt;/code&gt; this does not work well as the server needs to be restarted with each code change. Restarting CherryPy’s wsgiserver is less easy than some desire because it can be some time before the main thread will come round to hearing an interrupt signal. The initial solution to this problem, the &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/reloader/"&gt;reloader plugin&lt;/a&gt;, helps but gets a bit weird when syntax errors exist in the watched Python files (which happens a lot if you have a &lt;code&gt;esc:w&lt;/code&gt; trigger finger): The entire server will crash out and you have to start the process again by hand. This mostly makes sense from a logical standpoint but is not that helpful.&lt;/p&gt;

&lt;p&gt;One proposed solution to this problem is to host TiddlyWeb under a simple CGI setting. This will reload and recompile the code with every request. This can be slow for production settings but plenty fast for development. The TiddlyWeb source package includes an &lt;a href="http://github.com/tiddlyweb/tiddlyweb/blob/master/index.cgi"&gt;index.cgi&lt;/a&gt; script for this. Ben Gillies has written &lt;a href="http://bengillies.net/.a/recipes/sitecontent/tiddlers/CGI%20Install%20Update"&gt;some docs&lt;/a&gt; on how to use it.&lt;/p&gt;

&lt;p&gt;Of course to use the CGI option you have to have some kind of web server around. Many systems come with Apache already on them or easy to install. If you prefer not to run Apache (like me) another option is &lt;a href="http://pypi.python.org/pypi/Spawning"&gt;Spawning&lt;/a&gt; a fast multi-process, multi-threaded, Python web server. There’s a TiddlyWeb “factory” for Spawning called &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/spawner/"&gt;spawner&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.whatfettle.com/"&gt;Paul&lt;/a&gt; wisely pointed out that much of this reload fiddling about can be avoided by writing and testing Python modules that perform most of the activity for you application, minus the web handling, and then &lt;em&gt;using&lt;/em&gt; these modules in small layers of Python code that integrate with TiddlyWeb.&lt;/p&gt;

&lt;p&gt;There was a fair amount of resistance in the group to formal and rigorous testing, which I think is extremely unfortunate, but Simon rightly points out that lots of people are like that, and TiddlyWeb is going to limit its audience a great deal if it requires developers to be totally test driven.&lt;/p&gt;

&lt;p&gt;Another point of difficulty and contention is lack of familiarity with Python, Unix and TCP fundamentals. I’m not sure how to respond to that sort of thing other than to say that if you want to develop networked applications in Python, on Unix, then it’s probably pretty good to be familiar with such stuff.&lt;/p&gt;

&lt;p&gt;By the far the biggest issue with development is managing the inclusion of necessary stuff in the development environment. This includes auxiliary plugins that are required for the system, TiddlyWiki content and plugins, and static content that the web app needs. Mike’s &lt;a href="http://softwareas.com/actions-and-conclusions-from-tiddlyweb-devdeploy-workshop"&gt;blog post&lt;/a&gt; has most of the plans in this area. The gist is two pieces of development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improving the existing &lt;a href="http://github.com/FND/tiddlyweb-plugins/blob/master/devtext.py"&gt;devtext&lt;/a&gt; &lt;a href="http://tiddlyweb.peermore.com/wiki/recipes/docs/tiddlers/store"&gt;store&lt;/a&gt; so it more effectively (and &lt;em&gt;correctly&lt;/em&gt;) supports during development manipulation of the store and inclusion of TiddlyWiki content. We’ll be talking about the details of this in IRC this afternoon.&lt;/li&gt;
&lt;li&gt;Creating a suite of shell-based tools that provide Make like functionality for establishing and maintaining a development environment and easing deployment. The long term plan is to migrate these tools to Python as time and knowledge allows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For myself the things that have become important are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Making existing plugins more visible to developers so they know what tools are available.&lt;/li&gt;
&lt;li&gt;Packaging so-called mature plugins as Python packages that are installable via &lt;code&gt;easy_install&lt;/code&gt; or &lt;code&gt;pip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enhancing documentation of configuration options so they are more visible.&lt;/li&gt;
&lt;li&gt;Publishing the quick hacks and tricks I do to make my own development life a bit more zipless.&lt;/li&gt;
&lt;/ul&gt;</description><link>http://cdent.tumblr.com/post/214629671</link><guid>http://cdent.tumblr.com/post/214629671</guid><pubDate>Fri, 16 Oct 2009 13:00:00 +0100</pubDate><category>tiddlyweb</category></item><item><title>Info Condom</title><description>&lt;p&gt;The recent suffering of Twitter and Facebook (and others apparently) at &lt;a href="http://news.cnet.com/8301-27080_3-10305200-245.html"&gt;the hands of a huge DDOS&lt;/a&gt; is just one more reason to disapprove of centralized, single-source, non-federated services: They are vulnerable to just this sort of thing.&lt;/p&gt;

&lt;p&gt;A system of federated presentation services and many &lt;a href="http://cdent.tumblr.com/post/116865746/internet-bank-of-content"&gt;Banks of Content&lt;/a&gt; would be far less vulnerable. Oddly, this is a well known lesson and a fundamental piece of the architecture that underlies the internet. However it is a problem that is far easier to solve at the level of technological interaction than at the level of social interaction.&lt;/p&gt;

&lt;p&gt;One of the appeals of Twitter and the like is that you can experience moments like this: “I’m on Twitter! ZOMG are you on Twitter too!!?? You &lt;em&gt;totally&lt;/em&gt; have to get on twitter and then we can be on twitter &lt;em&gt;together&lt;/em&gt;!”.&lt;/p&gt;

&lt;p&gt;That’s far more fun and engaging than: “I propagate my microblog content by URI from my robust distributed content store to multiple presentation services, it would be great if your microcontent could co-mingle with mine on the open internet and together stimulate the generation of new knowledge.”&lt;/p&gt;

&lt;p&gt;(Actually that sounds really sexy to me, but I’ve been told I’m a bit strange.)&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/157958226</link><guid>http://cdent.tumblr.com/post/157958226</guid><pubDate>Fri, 07 Aug 2009 16:43:00 +0100</pubDate><category>openweb</category></item><item><title>Recent TiddlyWeb Plugins of Note </title><description>&lt;p&gt;Though the historical roots of &lt;a href="http://tiddlyweb.com/"&gt;TiddlyWeb&lt;/a&gt; are as a store for quine-like systems (I should write more about this), because it has a very flexible plugin system it also manages to be something of an unintentional web-app framework. Many plugins have been developed over the past several months. Many are experiments to demonstrate possibilities. Others are practical tools. Here’s a bit of info on those I’ve recently put together. &lt;a href="http://bengillies.net/"&gt;Ben Gillies&lt;/a&gt;, &lt;a href="http://www.jonrobson.me.uk/"&gt;Jon Robson&lt;/a&gt;, &lt;a href="http://softwareas.com/"&gt;Mike Mahemoff&lt;/a&gt;, and &lt;a href="http://fnd.lewcid.org/blog/"&gt;FND&lt;/a&gt; have all been doing interesting work as well.&lt;/p&gt;

&lt;p&gt;Just this morning I made &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/markdown"&gt;markdown.py&lt;/a&gt; which is in the class of plugins known as wikitext renderers. These provide a method for transforming the text of tiddler stored in TiddlyWeb into some other textual form, usually HTML. The default renderer is called ‘raw’ and returns its input. &lt;a href="http://tiddlyweb.peermore.com/wiki/#TiddlyWebWiki"&gt;TiddlyWebWiki&lt;/a&gt; uses the wikklytextrender plugin as its default renderer. It takes TiddlyWiki formatted text and returns HTML. The markdown renderer renders &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; syntax to HTML. It’s possible to run multiple wikitext renderers in the same TiddlyWeb instance, which is used is determined by the value of tiddler.type. Here’s the entire content of the markdown plugin:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import markdown2

def render(tiddler, environ):
    """
    Render text in the provided tiddler to HTML.
    """
    return markdown2.markdown(tiddler.text)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/ramstore"&gt;ramstore.py&lt;/a&gt; is a StorageInterface implementation for TiddlyWeb that persists the main entities of TiddlyWeb (Tiddlers, Bags, Recipes, Users) into RAM in the same process. Persist is not really the right term because as soon as the current process goes away, so do the tiddlers. This plugin mostly exists for testing (it allows you to effectively mock a store without actually being a mock) and to demonstrate the bare minimum of what a store needs to be able to do to fully support the StorageInterface. Longer term, however, I can see it being useful as part of a layered caching solution (one thread reads or writes RAM and returns control to the web request handling layer, another thread wakes up when RAM is written and takes what is written and sends it downstream to more persistent layers).&lt;/p&gt;

&lt;p&gt;The default distribution of TiddlyWeb provides no exposure of User entities over HTTP. &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/userbag"&gt;userbag.py&lt;/a&gt; and &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/users"&gt;users&lt;/a&gt; demonstrate two (incomplete) ways of exposing them. The former uses a combination of &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/diststore"&gt;diststore&lt;/a&gt; and a simple StorageInterface implementation which presents the users on a system as tiddlers in a bag called ‘users’. The latter add /users and /users/{usersign} routes with handlers that query the store. At the moment both are read only.&lt;/p&gt;

&lt;p&gt;Maybe I’ll write another one of these.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/157123497</link><guid>http://cdent.tumblr.com/post/157123497</guid><pubDate>Thu, 06 Aug 2009 13:13:19 +0100</pubDate><category>tiddlyweb</category></item><item><title>Tools Together</title><description>&lt;p&gt;&lt;strong&gt;Brain Dump&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As &lt;a href="http://tiddlyweb.com/"&gt;TiddlyWeb&lt;/a&gt; has matured, one of the things I have noticed is that people are often wanting it to do more than it does. The generic form of the query is something along the lines of “Wouldn’t it be more complete if it did X”.&lt;/p&gt;

&lt;p&gt;This is interesting to me because in a way it is contrary to the TiddlyWeb point. At base TiddlyWeb is a tool for manipulating chunks of stuff called tiddlers on the web. It is one of many tools in the toolbox for doing web stuff.&lt;/p&gt;

&lt;p&gt;An analogy may help. There are lots of tools out there that spin and accept attachments: screwdrivers, socket wrenches, drills, etc. You can make a drill be a screwdriver if you want, but sometimes it is overkill. TiddlyWeb is an extensible web service: with extensions it can serve up static content, use templates, do all the usual web framework stuff. But that doesn’t mean it should be used for all the usual web framework stuff. Maybe, maybe not.&lt;/p&gt;

&lt;p&gt;TiddlyWeb comes out of the Unix tradition: small tools that do one job well and can be integrated with other small tools through pipelines. This is true in how TiddlyWeb can interact with other tools and also internal to the architecture of TiddlyWeb: separated layers with strict contracts for interaction. This means it is easy to extend and it interoperates nicely with other stuff.&lt;/p&gt;

&lt;p&gt;The most performant and scalable implementation of a large scale service that involves TiddlyWeb likely involves TiddlyWeb; a separate web server (or two or three or four) serving static content, doing some URL rewriting, some caching; a memcached server; a database server; and maybe another framework (django, turbogears, rails, etc) presenting UIs that might use the TiddlyWeb server as a datastore.&lt;/p&gt;

&lt;p&gt;This last thing (presenting UIs) is the main area in which TiddlyWeb intentionally makes no provision (to concentrate on effective backend handling). Good web frontend presentation is strenuous, there are existing tools which make it easier. A tool approach means that TiddlyWeb can play well with those guys.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/141439434</link><guid>http://cdent.tumblr.com/post/141439434</guid><pubDate>Tue, 14 Jul 2009 14:10:22 +0100</pubDate><category>tiddlyweb</category><category>openweb</category></item><item><title>Leaping Forward</title><description>&lt;p&gt;I’ve been having a bit of a debate with &lt;a href="http://twitter.com/Casablanca"&gt;@Casablanca&lt;/a&gt; about the need or merits of designing and developing for people who use Outlook or IE. It started with:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/cdent/status/2327875584"&gt;@cdent&lt;/a&gt;: This #fixoutlook thing is bullshit. Just don’t use outlook!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/Casablanca/status/2328970657"&gt;@Casablanca&lt;/a&gt;: @cdent it’s not about whether you use outlook. It’s about having to design for people who do (e.g. our client’s customers)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/cdent/status/2331591336"&gt;@cdent&lt;/a&gt;: @Casablanca don’t design for those people! Design well enough that they’ll want to use what you’re using. If U cowtow, they’ll never learn.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/Casablanca/status/2332209628"&gt;@Casablanca&lt;/a&gt;: @cdent you mean we should tell our clients to tell their customers to change their email clients? A bit impractical, no?&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/cdent/status/2334529588"&gt;@cdent&lt;/a&gt;: @Casablanca Just because it is impractical doesn’t make it wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/Casablanca/status/2340561913"&gt;@Casablanca&lt;/a&gt;: @cdent does that mean you’ve never tested code in ie, because you don’t want to design for those people either?&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/cdent/status/2341245264"&gt;@cdent&lt;/a&gt;: @Casablanca I haven’t personally tested code in IE for several years, if ever. Nor do I test other code in non-posix envs.&lt;/p&gt;

&lt;p&gt;My basic assertion here is that people or organizations won’t change to things that are better if they can get the cool stuff on what they already have.&lt;/p&gt;

&lt;p&gt;A secondary assertion is that by requesting Microsoft fix Outlook, Microsoft is not getting the punishment they deserve for causing the problems they have caused over the last…well the last very long time. There shouldn’t be a campaign to fix Outlook, there should be a campaign to boycott Outlook and boycott developing for Outlook.&lt;/p&gt;

&lt;p&gt;I understand the economic considerations involved in the calculus used to determine “shall we do the work to make this work in IE”. For people encumbered by relationships with the corporate world, it’s kind of inevitable that someone along the chain will declare an operating environment where things must work. Likely that is an environment where openness, consensual standards and interoperability are meaningless tokens, not thriving actors in the system.&lt;/p&gt;

&lt;p&gt;I try to avoid those kinds of relationships, and think other people should as well. I’m well aware that some people can’t and some people don’t, and more power to them. In fact it works out quite well for me: Because I work on open code in open environments, if there are people who are interested in making the stuff I do work in non-standard environments, they have easy access to do so. The pain stays with the people who need or want to suffer it.&lt;/p&gt;

&lt;p&gt;Yes, I’m being impractical. Yes, I’m being unrealistic. But I can see little to suggest that the practical realities of the world are the best ways of doing things, so I’ll continue.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/130537549</link><guid>http://cdent.tumblr.com/post/130537549</guid><pubDate>Fri, 26 Jun 2009 10:04:58 +0100</pubDate><category>openweb</category></item><item><title>S5 For TiddlyWeb</title><description>&lt;p&gt;This evening FND and I were discussing how one of these days I’ll have to do a TiddlyWeb presentation: make slides, talk to people, gesticulate in awkward ways while standing in front of people and moving around for no particular reason. I remarked that I was going to use 3x5 cards to lay out my thoughts because they are physical and I think better with physical stuff.&lt;/p&gt;

&lt;p&gt;This led to more discussion about how in the &lt;a href="http://tiddlywiki.com"&gt;TiddlyWiki&lt;/a&gt; universe slide presentation systems are a bit of theme or motif. I said I had considered making a tool to present slides out of TiddlyWeb but figured I would do such a thing when I really needed it. What I had in mind was some kind of jQuery thing that retrieved content from the server as needed. In other words, a project, an investment of some kind. FND brilliantly suggested that an &lt;a href="http://meyerweb.com/eric/tools/s5/"&gt;S5&lt;/a&gt; serializer would be the ticket.&lt;/p&gt;

&lt;p&gt;I had heard of S5 before, but never really knew what it was. So I went digging around and saw that the basics of S5 are not only incredibly straightforward, the fine folks at &lt;a href="http://meyerweb.com"&gt;meyerweb.com&lt;/a&gt; have &lt;a href="http://meyerweb.com/eric/tools/s5/primer.html"&gt;packaged it all up nice and easy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I thought to myself: All TiddlyWeb needs to do is make the s5 javascript and CSS available (either via the hosting web server, or the &lt;a href="http://tiddlyweb.peermore.com/wiki/#twstatic"&gt;static plugin&lt;/a&gt;), gather some tiddlers, and push them into the HTML file provided for S5. I set about doing that and lo and behold it works! &lt;a href="http://tws5.peermore.com/wiki/recipes/default/tiddlers.s5"&gt;Here’s an example&lt;/a&gt;. Go have a look, it gives a bit of an idea of what’s going on.&lt;/p&gt;

&lt;p&gt;And &lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/tws5"&gt;here’s the code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The serializer architecture in TiddlyWeb has been designed from the start to be extensible. By configuration or a plugin you can associate a MIME type or a file extension with a Python module that implements at least some of the &lt;em&gt;SerializationInterface&lt;/em&gt;. A serializer takes TiddlyWeb objects, such as a tiddler or collection of tiddlers, and turns them into some stringified form of some type (HTML, JSON, an S5 file, etc.). Some serializers go the other way as well (e.g. turning a JSON string into a Tiddler object).&lt;/p&gt;

&lt;p&gt;The S5 serializer checks for some special tiddlers to set meta-presentation-stuff like title and presenter name, and then renders each of the tiddlers it has been provided into HTML. This HTML is then pushed into the template file (&lt;a href="http://jinja.pocoo.org/"&gt;jinja2&lt;/a&gt; is used) and the results are sent out over the web as an HTML file. That HTML file requests back to the server for the necessary javascript and CSS.&lt;/p&gt;

&lt;p&gt;Because TiddlyWeb already has all the bits for generating the list of tiddlers and getting them to the serializer, the serializer itself can be quite small and concentrate on just the work it is supposed to do. The code is only 55 lines long, including whitespace. And I like whitespace.&lt;/p&gt;

&lt;p&gt;There are still some things to clean up, but I reckon it is nice start.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://tws5.peermore.com/wiki/default/recipes/tiddlers.s5"&gt;A demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/tiddlyweb/tiddlyweb-plugins/tree/master/tws5"&gt;The code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddlyWeb’s home site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://cdent.tumblr.com/post/46434732/and-the-leaders-said-let-them-eat-cake"&gt;An old posting about TiddlyWeb serializers&lt;/a&gt;. That one involves cake rather than presentation slideshows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I updated the link to the demo to a new location to reflect that there’s now support for ordering slides in the presentation.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/124826535</link><guid>http://cdent.tumblr.com/post/124826535</guid><pubDate>Tue, 16 Jun 2009 23:40:00 +0100</pubDate><category>tiddlyweb</category></item><item><title>"The GIF Pronunciation Page. It’s jiff. Here’s evidence."</title><description>“&lt;a href="http://www.olsenhome.com/gif/"&gt;The GIF Pronunciation Page&lt;/a&gt;. It’s jiff. Here’s evidence.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;a href="http://simonwillison.net/2009/Jun/11/gif/"&gt;The GIF Pronunciation Page&lt;/a&gt;&lt;/em&gt;</description><link>http://cdent.tumblr.com/post/121953256</link><guid>http://cdent.tumblr.com/post/121953256</guid><pubDate>Thu, 11 Jun 2009 21:57:39 +0100</pubDate></item><item><title>Synthesis </title><description>&lt;p&gt;Not long ago I decided to take a break from updating my status on &lt;a href="http://twitter.com/cdent"&gt;Twitter&lt;/a&gt; and &lt;a href="http://facebook.com"&gt;Facebook&lt;/a&gt;. It was a spur of the moment decision but the urge had been building for quite a while. What I said at the time was: “It’s mediating my conversations and I like the internet when it disntermediates.”&lt;/p&gt;

&lt;p&gt;Meaning: Using Twitter and Facebook statuses gives me the action of initiating interactions with the world, satisfying something innate, but for the most part ends the experience there. On one hand this is perfectly fine: Broadcasting the ephemera of life maintains a loose contact, a finger in the ambient stream of ones social network. And every now and again someone will @you or “like this” to let you know that the world rolls on.&lt;/p&gt;

&lt;p&gt;On a different hand, by granting a minor satisfaction of the urge to express, 140 characters of news bleeds off the pressure to say something of substance, something with significance, something that synthesizes.&lt;/p&gt;

&lt;p&gt;This may be the most telling way in which I’m showing my age: Knowledge trumps Information; though communication is the grist of knowledge generation, action, results, doing, &lt;em&gt;knowing&lt;/em&gt; is what matters. When I was at &lt;a href="http://socialtext.com"&gt;Socialtext&lt;/a&gt; and actively engaged with &lt;a href="http://www.blueoxen.com"&gt;Blue Oxen&lt;/a&gt; I had occasion to play in the fields of the lords of Silicon Valley and often thought: All these Californians seem to do is travel from one conference, meetup, retreat to the next. When do they &lt;em&gt;do&lt;/em&gt; anything? When is the synthesis? (It does happen, but it is on the fringes of the whirling soup of information being exchanged. People step out of the flow and then return with their synthesized new stuff.)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.eekim.com/"&gt;EEK&lt;/a&gt; (of Blue Oxen) and I, in our too infrequent conversations, often return to the topic “What happened to wikis?” Somewhere along the way the popular conception of a wiki transformed from a tool for synthesizing new understandings in a group to a tool for representing topical information which can refined. In many modern wikis, UI affordances emphasize the single page and the fact that it is editable rather than the entire wiki and its nature as an evolving (visible by recent changes) networked (via hyperlinks) corpus of shared understandings. A traditional wiki is a synthesizing tool when it exposes or strengthens the connections between distant concepts and categories. The group using a wiki learns by exposing, exploring and, eventually, refining those connections.&lt;/p&gt;

&lt;p&gt;I get bored when I’m not learning, learning requires synthesis and synthesis requires reflection, reflection is something we pause for. Writing a tweet is vaguely like pissing &lt;em&gt;with&lt;/em&gt; the wind: off it goes, out there with the breeze; easy, initially satisfying, but ultimately boring. So a pause. I’m sure I’ll return to it eventually but for the time being I need some reflection, some synthesis, and some doing and being.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;While looking around for things I’ve thought or written related to this, I found &lt;a href="http://ontolog.cim3.net/forum/ontolog-forum/2002-06/msg00007.html"&gt;this old email about knowledge representations from 2002&lt;/a&gt; which has a bit to say about synthesis.&lt;/em&gt;&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/119454584</link><guid>http://cdent.tumblr.com/post/119454584</guid><pubDate>Sun, 07 Jun 2009 16:16:42 +0100</pubDate></item><item><title>Don't Shape My Net Bro</title><description>&lt;p&gt;I have always been, and plan to remain, fiercely of the opinion that ISPs should never be involved in traffic shaping at the application/layer 7 level. It is completely antithetical to the spirit of the network (stupid network and all that) and I think in the long run it is very bad business for ISPs.&lt;/p&gt;

&lt;p&gt;If a customer wishes to do their own shaping to maintain quality of service (e.g. prioritizing interactive ssh sessions over retrieving web pages) more power to them. Such tools are available.&lt;/p&gt;

&lt;p&gt;If an ISP wants to do shaping of the the total bandwidth any single endpoint gets across a switch, that makes pretty good sense.&lt;/p&gt;

&lt;p&gt;But: If the ISP starts digging into packet headers and even packet bodies to do shaping they are introducing a huge cost for themselves. On the one hand their switches much do greater work. On the other hand there is now a presumption that the ISP knows or can know the content that is traversing their network and can be held liable for producing data about that content or controlling that content.&lt;/p&gt;

&lt;p&gt;I get the impression that this latter point about liability is already a lost cause in the UK, which is a damn shame.&lt;/p&gt;

&lt;p&gt;If BT or any other ISP is selling 8mbps connections to customers, then the customer should be able to expect that level of service for any type of content they get across the wire. If BT insists on being so oversubscribed that they can’t support that level of service at all times, they should shape total usage, not specific protocols or applications.&lt;/p&gt;

&lt;p&gt;It’s interesting to me that BT would want to perform any kind of shaping. BT has an effective monopoly on the physical infrastructure that provides these services. By encouraging more and more intensive use of the internets they increase the demand for the infrastructure they provide.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I do contract work with &lt;a href="http://www.osmosoft.com"&gt;Osmosoft&lt;/a&gt; which is part of BT. These are my opinions. I’m sure there are lots of people within and without BT with lots of different opinions on this matter.&lt;/em&gt;&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/119436651</link><guid>http://cdent.tumblr.com/post/119436651</guid><pubDate>Sun, 07 Jun 2009 15:24:56 +0100</pubDate><category>openweb</category></item><item><title>Internet Bank of Content </title><description>&lt;p&gt;This is a followup to &lt;a href="http://cdent.tumblr.com/post/83871624/invert-the-web"&gt;Invert the Web&lt;/a&gt; where I wrote:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Today I go to a web site and give it some output of my brain. The web site takes my content and in exchange it gives me a URL so I and other people can get to the content again. What should happen instead is that I make some content and give that URL to some websites so they can get to the content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In typical me fashion that wasn’t very clear. Here I shall try to make parts of it more clear and other parts more muddy. Let’s expand the above.&lt;/p&gt;

&lt;p&gt;Today when I publish a photo or make a tweet the mechanism goes something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I suck the photo off my camera, do whatever tweaking I like to it, and then upload a &lt;em&gt;copy&lt;/em&gt; of it to some photo site (e.g. &lt;a href="http://www.flickr.com/photos/cdent/"&gt;Flickr&lt;/a&gt;). My photo then gets a URL somewhere in Flickr’s URLspace and I can tell people about that URL, or people can browse Flickr and stumble upon my photo. If things go my way and I play the game right, the photo might even show up on Explore.&lt;/li&gt;
&lt;li&gt;I go to &lt;a href="http://twitter.com/"&gt;http://twitter.com/&lt;/a&gt; or use an app like &lt;a href="http://iconfactory.com/software/twitterrific"&gt;Twitterrific&lt;/a&gt; and type up my tweet. The content is transmitted to and stored on Twitter’s servers and &lt;a href="http://twitter.com/cdent/status/1936107277"&gt;gets a permalink&lt;/a&gt; in their URLspace.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I would prefer is something like this, where the URL becomes a more &lt;em&gt;Universal&lt;/em&gt; Resource Locator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I suck the photo off the camera and store it in my own personal URLspace, getting a URL that links to the content. I then give that URL to Flickr and whatever other services provide a nice URI for browsing photos. People can still browser Flickr and stumble upon my photo and the photo may still show up in Explore. And lots of other places too.&lt;/li&gt;
&lt;li&gt;I write my tweet and store it in my own personal URLspace. I use the returned URL and give it to Twitter, Pownce, Jaiku, Facebook, MySpace, iChat and a variety of other “status” related services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this stage of the conversation the first objection is usually, “Not everyone can host their own content.” Indeed this is true. It’s also true, though, that not everyone keeps all their money in their wallet, under the mattress or in a mason jar in a hole in the back yard. They use banks. And those banks provide a variety of services to provide incentives for people to deposit their money with them. So we could have banks for content.&lt;/p&gt;

&lt;p&gt;Another objection is “I don’t want to do that two step publishing dance just to get something on Flickr.” Me neither, that’s why we have computers to automate the parts of processes which are fully describable. POSTting something in the content bank and then PUTting the returned URL to Flickr is fully describable.&lt;/p&gt;

&lt;p&gt;Why would you want a bank for content? What would the benefits be?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All content remains yours, held in trust by the bank, forever.&lt;/li&gt;
&lt;li&gt;If a presentation service goes out of business, your risk or loss is more manageable.&lt;/li&gt;
&lt;li&gt;Any publication of content can be immediately rescinded by changing access policies on the URL (modulo whatever caching policies you’ve chosen).&lt;/li&gt;
&lt;li&gt;You can (in theory) have access policies or capabilities statements on all your URLs.&lt;/li&gt;
&lt;li&gt;Anything which can be captured by a MIME type can be stored in the bank.&lt;/li&gt;
&lt;li&gt;You can host your own bank if you want: It’s just HTTP.&lt;/li&gt;
&lt;li&gt;You can publish your content to multiple places by reference instead of copy. When you make changes, you don’t need to worry about going round to several different presentation services.&lt;/li&gt;
&lt;li&gt;You have the option of maintaining several content accounts for all your various internet personas.&lt;/li&gt;
&lt;li&gt;Banks could differentiate themselves by providing different levels of service: different ways of managing access control, service level agreements, data sharding and redundancy. Some people might opt for free content accounts in exchange for allowing some or all of their content to be anonymously mined for targeted advertising purposes or market research.&lt;/li&gt;
&lt;li&gt;A suitably well featured bank could provide persistent and versioned storage for all your stuff, ever. Kind of like a &lt;a href="http://github.com/"&gt;github&lt;/a&gt; for everything, not just code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And what about places like Flickr or Twitter, what we might call presentation services? What could they gain?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They don’t need to worry about storage quite as much.&lt;/li&gt;
&lt;li&gt;They can concentrate specifically on the UI of their service, distinguishing themselves through innovations in that area.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These ideas are the latest synthesis of a variety of things which have proven to be important on the internet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separation of concerns. The presentation services worry about presentation and banks worry about storage.&lt;/li&gt;
&lt;li&gt;Cool URIs.&lt;/li&gt;
&lt;li&gt;Data ownership and portability. It’s always yours.&lt;/li&gt;
&lt;li&gt;MIME. Lots of different types of content.&lt;/li&gt;
&lt;li&gt;Stupid Network. Put the smarts where the smarts need to be and nowhere else.&lt;/li&gt;
&lt;li&gt;The awesomeness of REST, or more accurately HTTP, and the open web it/they allow.&lt;/li&gt;
&lt;li&gt;Using content by reference rather than copy (c.f. &lt;a href="http://en.wikipedia.org/wiki/Project_Xanadu"&gt;Xanadu&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Transclusion"&gt;Transclusion&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Purple_Numbers"&gt;Purple Numbers&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It would probably be possible to prototype a content bank in &lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddlyWeb&lt;/a&gt; or &lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt; or some kind of interface to &lt;a href="http://aws.amazon.com/s3/"&gt;S3&lt;/a&gt;. My own first work related to such things was &lt;a href="http://www.socialtext.net/open/index.cgi?closet"&gt;closet&lt;/a&gt; from which TiddlyWeb got a few ideas.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/116865746</link><guid>http://cdent.tumblr.com/post/116865746</guid><pubDate>Tue, 02 Jun 2009 17:28:19 +0100</pubDate><category>openweb</category><category>tiddlyweb</category></item><item><title>#openhackday </title><description>&lt;p&gt;I went to &lt;a href="http://yahoo.com/"&gt;Yahoo’s&lt;/a&gt; &lt;a href="http://openhacklondon.pbworks.com/"&gt;Open Hack Day London&lt;/a&gt; yesterday. Forthwith my observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I went with &lt;a href="http://blog.ingy.net/"&gt;Indy döt Net&lt;/a&gt;. We had some misconceptions about the event which may have informed our experience. Back before folk like &lt;a href="http://www.loudthinking.com/"&gt;DHH&lt;/a&gt; brought about the sexy extroverted geek, oldsters like myself thought of hackathons as small gatherings with lots of caffeine, pizza, a goal or two or three and lots of bandwidth.&lt;/li&gt;
&lt;li&gt;Yahoo put on a great show. The space was large. The food was good. There were some interesting presentations. There was plenty of caffeine. There was some late night pizza. But it was, in some sense, a show (there was &lt;a href="http://www.pornophonique.de/"&gt;a band&lt;/a&gt;, they were fun). This is perfectly appropriate on Yahoo’s part. They’re trying to get people involved in their (by the way, very good) APIs, tools, info.&lt;/li&gt;
&lt;li&gt;The bandwidth was not great. The usual WiFi problems: routers not giving out DHCP leases, people getting dropped off the ends of NAT tables, pipes being saturated. It seems like this ought to be a solved problem. My guess is that it goes something like this: The owner or supplier of the event space has a definition of robust network with phat pipe that is several orders of magnitude below that of the customer. Or at least I hope it is something like that. In any case, the Yahoo people worked valiantly all day long to get things working in an acceptable fashion.&lt;/li&gt;
&lt;li&gt;Having bad network for the start of the event was a real buzzkill, especially when the stuff being shown off were tools for accessing information on the open web (&lt;a href="http://developer.yahoo.com/yql/"&gt;YQL&lt;/a&gt; is cool!). I was planning to make something with &lt;a href="http://developer.yahoo.com/yui/"&gt;YUI&lt;/a&gt; but since I couldn’t download the code, I used &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; instead because I had that library on my local disk already.&lt;/li&gt;
&lt;li&gt;FND discovered a big performance bug in &lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddyWeb&lt;/a&gt; so we fixed it and released a new version. We might not have found the problem if it weren’t for the slow network.&lt;/li&gt;
&lt;li&gt;Ingy and I left without staying overnight because the vibe was large and big and loud.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://search.twitter.com/search?q=%23openhackday"&gt;Tweets from the event&lt;/a&gt; point out that at least some people felt spectacularly productive in the time they were there. I certainly got a lot done, once I settled in. It suggests that there’s something wrong with the way we, as a society, do work. These days more and more people have the job of “knowing stuff”. Some days you’re just stupid, for whatever reason. Probably shouldn’t work on that day. Other days you’re smart. Then might be a good time to work. However this might also just be a romantic belief that supports my own predilections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, it was a good time. Glad I was there.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/105896203</link><guid>http://cdent.tumblr.com/post/105896203</guid><pubDate>Sun, 10 May 2009 18:37:24 +0100</pubDate><category>openhackday</category></item><item><title>TiddlyWeb for the Impatient</title><description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; These instructions have been updated to reflect that the wiki functionality of TiddlyWeb has been migrated into a plugin (called tiddlywebwiki). See &lt;a href="http://tiddlyweb.peermore.com/wiki/#TiddlyWebWiki"&gt;TiddlyWebWiki&lt;/a&gt; for updates.&lt;/p&gt;

&lt;p&gt;When &lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddlyWeb&lt;/a&gt; first started being usable as an actual server, rather than a codebase against which to run some tests, it felt rather complex, maybe even onerous, to use. I hope that’s no longer true. Here’s TiddlyWeb for the impatient:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;sudo easy_install -U tiddlywebwiki&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;twanager --load tiddlywebwiki.config instance myname&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd myname&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;twanager server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;open &lt;a href="http://0.0.0.0:8080/recipes/default/tiddlers.wiki"&gt;http://0.0.0.0:8080/recipes/default/tiddlers.wiki&lt;/a&gt;&lt;/code&gt; or &lt;code&gt;xdg-open &lt;a href="http://0.0.0.0:8080/recipes/default/tiddlers.wiki"&gt;http://0.0.0.0:8080/recipes/default/tiddlers.wiki&lt;/a&gt;&lt;/code&gt; or if you don’t have one of those commands open your browser to that URL.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In your browser you will now see a &lt;a href="http://www.tiddlywiki.com/"&gt;TiddlyWiki&lt;/a&gt; hosted on a TidldyWebWiki to which your edits and new additions will be saved.&lt;/p&gt;

&lt;p&gt;For this to work you need a fairly modern system with Python installed, Python’s setuptools installed and generally speaking a friendly environment for doing stuff. In my experience that’s modern OS X and Ubuntu. YMMV.&lt;/p&gt;

&lt;p&gt;Hosting a TidldyWiki usable by multiple users is but one small piece of what TiddlyWeb can do, but the above opens the door. For more info see &lt;a href="http://tiddlyweb.peermore.com/"&gt;http://tiddlyweb.peermore.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; Some people have reported that the second step fails reporting an ImportError. When this happens it means the first step did not fully install all the tiddlyweb dependencies, and you’ll have to install them separately using easy_install. The ImportError will report what is missing.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/94180697</link><guid>http://cdent.tumblr.com/post/94180697</guid><pubDate>Wed, 08 Apr 2009 15:54:00 +0100</pubDate><category>tiddlyweb</category></item><item><title>TiddlyWeb + IMAP</title><description>&lt;p&gt;One of the more interesting but mostly unexplored areas of &lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddlyWeb&lt;/a&gt; is its ability to use its storage system to adapt pretty much any datastore into something useful to the tiddlers, bags and recipes that TiddlyWeb uses. Last year some time I created &lt;a href="http://cdent.tumblr.com/post/46209623/webs-of-tiddlywebs-with-tiddlywebweb"&gt;tiddlywebweb&lt;/a&gt;, which lets you use another (remote) TiddlyWeb server as the storage for a different TiddlyWeb server. While &lt;a href="http://svn.tiddlywiki.org/Trunk/contributors/ChrisDent/experimental/tiddlyweb-plugins/tiddlywebweb/"&gt;cleaning it up last night&lt;/a&gt;, to get it more in line with contemporary plugin behaviors, I decided I need to make something similar to prove the point a bit stronger.&lt;/p&gt;

&lt;p&gt;Python’s standard library includes some pretty useful tools for talking to IMAP servers and parsing email messages. Like many of the modules in the standard library, these aren’t exactly pretty or super clear, but they get the job done well.&lt;/p&gt;

&lt;p&gt;I decided I’d start a TiddlyWeb &lt;a href="http://tiddlyweb.peermore.com/wiki/#store"&gt;store&lt;/a&gt; that uses an IMAP account on the backend. Rather than figuring out the mapping between email and tiddlers from the start, I figured I’d just get rolling and see where I could take things.&lt;/p&gt;

&lt;p&gt;First I needed some code to talk to IMAP4 servers. &lt;a href="http://docs.python.org/library/imaplib.html"&gt;imaplib&lt;/a&gt; does that. Second I need to figure out how to use it. So I started some code that logs me into my IMAP account, selects the default mailbox, and gets me some references to all the messages there:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;imap = IMAP4_SSL(hostname)
imap.login(user, password)
imap.select()
typ, data = imap.search(None, 'ALL')
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That code is straight out of the docs.&lt;/p&gt;

&lt;p&gt;If I have some messages I want to be able to parse them. The &lt;a href="http://docs.python.org/library/email"&gt;email&lt;/a&gt; library does that just fine. When you fetch a specific message from the IMAP server it can be parsed from a string into a message object. For the sake of simplicity I’ve tossed aside any message that is MIME multipart:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;messages = []
for num in data[0].split():
    typ, data = imap.fetch(num, '(RFC822)')
    message = message_from_string(data[0][1])
    if not message.is_multipart():
        messages.append(message)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it’s possible to do things like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;print 'Subject: %s' % messages[1]['subject']
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Okay, satisfactory. Now we know how to get at stuff on the IMAP server. Time to start making a store. We can use the same file. A store in TiddlyWeb is a subclass of &lt;a href="http://tiddlyweb.peermore.com/wiki/#StorageInterface"&gt;StorageInterface&lt;/a&gt;. There is a set of methods it may support. No method is required. It’s really up to you what you want to handle. A store gets, puts and deletes various entities and lists collections thereof.&lt;/p&gt;

&lt;p&gt;To get things rolling I decided my store was going to be readonly and work for just one user, at least at first. Making messages map to tiddlers, and folders/mailboxes map to bags seems to make sense. Recipes? Dunno. Maybe someday that would be a mechanism for handling multiple user accounts on the server.&lt;/p&gt;

&lt;p&gt;The store methods we need to implement, then, are &lt;code&gt;list_bags&lt;/code&gt;, &lt;code&gt;bag_get&lt;/code&gt; and &lt;code&gt;tiddler_get&lt;/code&gt;. List all the folders on the server, list all the messages in a folder, retrieve an individual message and map some fields to tiddler fields. Mostly straightforward, with some blips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don’t know about you, but I have several hundred folders in my imap account, some with an astounding number of messages in them. Anything with “list all” in the description is kind of bad news. So the first hack was to only list folders beginning with ‘a’ (in IMAP-style pattern matching this is ‘&lt;prefix&gt;/a%’).&lt;/prefix&gt;
&lt;/li&gt;
&lt;li&gt;Any bag may only contain one tiddler with any one title. This is not true in an email folder, so when listing the contents of a folder/bag and creating a list of messages/tiddlers it is necessary to create a unique ID. I chose the union of message-id and subject. The message-id should be unique but is not particularly meaningful in lists. I thought about using the IMAP UID but these are not guaranteed to be the same between sessions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From there it is pretty cool with the tiddlers: the body of the message is the tiddler text (we are only accepting non-multipart messages), the date of the message is the tiddler modified time, the email address part of the from is the tiddler modifier.&lt;/p&gt;

&lt;p&gt;And so it all pretty much just works. If you go to &lt;code&gt;/bags&lt;/code&gt; you get a list of all the folders starting with ‘a’. If you follow links, you eventually get a list of all the messages in a folder. If you click on one, you can read it. If you click on a tiddlywiki link, all those mail messages show up in a tiddlywiki, which I must say is quite wacky.&lt;/p&gt;

&lt;p&gt;Things that would be useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some form of caching. Lord can it be slow. Even since some core performance changes to TiddlyWeb in the last few days.&lt;/li&gt;
&lt;li&gt;The same date used to set modified should set created too.&lt;/li&gt;
&lt;li&gt;Other message headers in the tiddler as extended fields.&lt;/li&gt;
&lt;li&gt;A TiddlyWiki plugin plus a TiddlyWeb plugin that lets you send mail from TiddlyWiki in response to messages.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tiddler_put&lt;/code&gt; and &lt;code&gt;tiddler_get&lt;/code&gt; for moving and removing messages.&lt;/li&gt;
&lt;li&gt;Some kind of role for recipes.&lt;/li&gt;
&lt;li&gt;A something, maybe called polystore, that lets one TiddlyWeb server access multiple different stores.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What else? Give it try if you are curious and hardy. Contact me if you want some help.&lt;/p&gt;

&lt;p&gt;The code is in the &lt;a href="http://svn.tiddlywiki.org/"&gt;TiddlyWiki subversion repository&lt;/a&gt;, in my &lt;a href="http://svn.tiddlywiki.org/Trunk/contributors/ChrisDent/experimental/tiddlyweb-plugins/imapstore/"&gt;tiddlyweb-plugins dir&lt;/a&gt;. I’ve also started keeping track of such things &lt;a href="http://github.com/cdent/tiddlyweb-plugins"&gt;on github&lt;/a&gt;.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/89803274</link><guid>http://cdent.tumblr.com/post/89803274</guid><pubDate>Wed, 25 Mar 2009 21:42:57 +0000</pubDate><category>tiddlyweb</category></item><item><title>Docupeopletation</title><description>&lt;p&gt;Writing documentation is spectacularly difficult. At least for me. While I’m capable of being quite verbose (perhaps too verbose) in response to a question (perceived or actual) I’m crap at predicting what people will want or need before they get to the point of asking questions.&lt;/p&gt;

&lt;p&gt;This is having an unfortunate effect in the land of &lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddlyWeb&lt;/a&gt;: documentation is lagging quite far behind the functionality of the tool and while I’m generating new documentation on a fairly regular basis I have no way of knowing if it is the right documentation.&lt;/p&gt;

&lt;p&gt;Any software project, especially one which is both an application, a library and an HTTP API, has several different types of documentation. There’s the documentation in the code explaining functions, classes, methods, modules and such. With Python there are tools like &lt;a href="http://pypi.python.org/pypi/pylint"&gt;pylint&lt;/a&gt; and &lt;a href="http://svn.browsershots.org/trunk/devtools/pep8/pep8.py"&gt;pep8.py&lt;/a&gt; which will tell you when your code is missing docstrings so TiddlyWeb has most of that covered with at least basic documentation on stuff that is public.&lt;/p&gt;

&lt;p&gt;More complicated is the narrative that explains what TiddlyWeb can do and the documentation that explains how to do it. Making it go, getting the best out of it. That’s the stuff that’s hard to do alone; since narrative is a story it only emerges through human communication: feedback loops, a dialog of participants.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/89338519</link><guid>http://cdent.tumblr.com/post/89338519</guid><pubDate>Tue, 24 Mar 2009 12:00:00 +0000</pubDate><category>tiddlyweb</category></item><item><title>What I did on my Spring Vacation </title><description>&lt;p&gt;I made &lt;a href="http://raamapable.appspot.com"&gt;raamable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My friend Stan is going to be part of the support crew of Team Hoosiers when they once again participate in the &lt;a href="http://www.raceacrossamerica.org/"&gt;Race Across America&lt;/a&gt;: a west to east cross-continental traverse of the US. On bikes.&lt;/p&gt;

&lt;p&gt;Stan wondered about the possibility of some web based resources to help make things go. When heading across the country where every minute counts it’s good to know where you are going; what’s coming up next; weather conditions; the nearest grocery, gas, laundry, bike store.&lt;/p&gt;

&lt;p&gt;When I was working for &lt;a href="http://www.socialtext.com/"&gt;Socialtext&lt;/a&gt; most of the developers worked from home, scattered around the world. When we did get together we’d sometimes experience bursts of productivity that were very pleasant: a great sense of being in the zone. Bourbon was often involved. Intense work and intense play.&lt;/p&gt;

&lt;p&gt;Seemed like Stan’s project was a good reason to do some good work for a good cause.&lt;/p&gt;

&lt;p&gt;So I hunted out &lt;a href="http://mml.name/"&gt;Matt&lt;/a&gt; and &lt;a href="http://urbanape.com/"&gt;Zac&lt;/a&gt;, also former Socialtexters, and we planned a hankathon (hack and drink a thon) in Bloomington, the font of much goodness. The idea was we’d gather, mess about with some Google mashups, see what we ended up with, and see what we learned about how to have effective similar things in the future. These days it should only take a few days to establish a startup.&lt;/p&gt;

&lt;p&gt;We made plans. Zac couldn’t come: teething baby. Down to just Matt and me. I was sick, Matt had to work, and hanging out with Stan is too rare and too fun to be wasted on staring at computers so we didn’t have the focus and concentration we originally desired. We still managed to get some things done and learn some things.&lt;/p&gt;

&lt;p&gt;On the learning side we had some thoughts for next time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear the decks. If you’re going to a multi-day hackathon, don’t bring other work.&lt;/li&gt;
&lt;li&gt;Have a least three people. If you know exactly what you are doing, pairing or sharing work can work out very well, but if you are exploring as much as executing, an odd number keeps thinking unstable and diverse.&lt;/li&gt;
&lt;li&gt;Spend the first day, half day, some unit of time brainstorming and finding the point of gravity. The group needs an articulated shared goal to have shared momentum.&lt;/li&gt;
&lt;li&gt;Have a tool for keeping track of what’s up. We used a &lt;a href="http://tiddlyweb.peermore.com"&gt;TiddlyWeb&lt;/a&gt; hosted &lt;a href="http://tiddlyweb.peermore.com/wiki/recipes/raam/tiddlers.wiki"&gt;tiddlywiki&lt;/a&gt; but didn’t initially use it all that well. Since we were in person I suspect something more tactile like a whiteboard with stickies on it might have worked better.&lt;/li&gt;
&lt;li&gt;Get necessary infrastructure in place beforehand.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite being a bit discombobulated we did manage to create something.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ingy.net/"&gt;Uncle Ingy&lt;/a&gt; says every good project starts with a good name, so I baked the name “raamable” into a &lt;a href="http://github.com/cdent/raamable"&gt;git repo&lt;/a&gt; on &lt;a href="http://github.com/"&gt;github&lt;/a&gt; and started gathering the necessary pieces.&lt;/p&gt;

&lt;p&gt;Since we knew we’d be working on this project separately before and after the hankathon, we’d need a convenient way to work in a test and deployed environment. &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt; makes that easy: do local development until you get it right and then deploy to the servers.&lt;/p&gt;

&lt;p&gt;We had some known &lt;a href="http://tiddlyweb.peermore.com/wiki/recipes/raam/tiddlers.wiki#data"&gt;data sources&lt;/a&gt;: gps waypoints for the race, locations and frequencies of &lt;a href="http://www.noaa.gov"&gt;NOAA&lt;/a&gt; weather radio towers, a &lt;a href="http://gisdata.usgs.gov/xmlwebservices2/elevation_service.asmx/getElevation"&gt;web service&lt;/a&gt; that gives elevation for longitude and latitude in the US.&lt;/p&gt;

&lt;p&gt;First pass plan: put all that stuff on a google map and see what happens. There were some challenges.&lt;/p&gt;

&lt;p&gt;It’s easy to put a bunch of markers on a map. &lt;a href="http://github.com/cdent/raamable/blob/17e068d5b796a51d354df049b12e100c50a2262f/mapthing/js/elegraph.js"&gt;The code&lt;/a&gt; shows that well enough. What’s harder, when there are several hundred markers, is plotting the line of the route on roads. Plotting a route requires using GDirections, which will only take 25 waypoints per use. Our solution was to loop over the markers in chunks of 25. The results in the map shown on the &lt;a href="http://raamapable.appspot.com/"&gt;front page&lt;/a&gt;. The animation is a side effect of the process being somewhat slow. The darker blue spots happen where one block of 25 stops and another starts.&lt;/p&gt;

&lt;p&gt;On the &lt;a href="http://raamapable.appspot.com/alt"&gt;interactive map&lt;/a&gt; yellow markers are time stations, orange are turns on the route, and the towers mark nearby weather radio towers. Each GMarker that represents a turn has an added attribute &lt;code&gt;altitude&lt;/code&gt; containing meters of elevation at that location. Each GMarker representing a radio has a &lt;code&gt;frequency&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;The race route turns information did not come with elevation data. I initially planned to make the map queryable for elevation at any point (thus the /proxy URL in the app engine code) but then we decided an elevation profile image would be nice. Dynamic querying for that would be much too time consuming and barring catastrophe elevation doesn’t change much so storing it on the map seemed the way to go. For kicks I processed the route turn CSV file through a shell one liner using curl to get the elevation data and add it back into the file.&lt;/p&gt;

&lt;p&gt;The elevation profile is a &lt;a href="http://code.google.com/apis/chart/"&gt;google chart&lt;/a&gt; that is redrawn each time the map is moved or zoomed. The crux here was to make sure that we only draw information for those markers which are within the bounds of the current view. &lt;code&gt;updateProfile&lt;/code&gt; in the &lt;a href="http://github.com/cdent/raamable/blob/17e068d5b796a51d354df049b12e100c50a2262f/mapthing/js/elegraph.js"&gt;code&lt;/a&gt; shows how this is done.&lt;/p&gt;

&lt;p&gt;There are many hundreds of radio towers in the continental US. We only want to show those which are near the route. There’s doesn’t seem to be a straightforward efficient way to say “plot only those waypoints which are near to this other set of waypoints” so we constructed our own. The entire route describes a rectangle that has northern and souther latitudes that can exclude most of the towers. So first we do that. The slope of the route (southwest to northeast), however, is too steep for this to be good enough: a larger number of towers are plotted which are too far away to be tuned in and make the map uselessly noisy. To deal with this an array of bounds, one containing each ten turns (plus and minus 1 degree of longitude and latitude) along the map, is created. The remaining radio tower locations are compared against the bounds. See &lt;a href="http://github.com/cdent/raamable/blob/17e068d5b796a51d354df049b12e100c50a2262f/mapthing/js/elegraph.js#L126"&gt;_establishRouteCallback&lt;/a&gt; and &lt;a href="http://github.com/cdent/raamable/blob/17e068d5b796a51d354df049b12e100c50a2262f/mapthing/js/elegraph.js#L84"&gt;_addTowersCallback&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We hope to do quite a bit more. We’re tracking our plans on &lt;a href="http://tiddlyweb.peermore.com/wiki/recipes/raam/tiddlers.wiki#%5B%5BTodo%20List%5D%5D"&gt;the wiki&lt;/a&gt;. What’s &lt;a href="http://raamapable.appspot.com/"&gt;running now&lt;/a&gt; is a useful tool but suffers one rather extreme flaw: it requires network access. We hope to modify things so that useful printouts can be made from the system and carried on the route.&lt;/p&gt;

&lt;p&gt;This is an open source project, you are welcome to help out, use this for your own bike ride, or whatever. If you do, we’d love to hear from you.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/86648122</link><guid>http://cdent.tumblr.com/post/86648122</guid><pubDate>Sun, 15 Mar 2009 13:14:00 +0000</pubDate><category>raam</category></item><item><title>Invert the Web</title><description>&lt;p&gt;I was talking this afternoon with Fred. Over the past few days, he and Jon have been creating a &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; archiver called &lt;a href="http://www.osmosoft.com/tiddlytweets"&gt;TiddlyTweets&lt;/a&gt; using &lt;a href="http://www.tiddlywiki.com/"&gt;TiddlyWiki&lt;/a&gt; plugins. It’s cool: you give it a twitter username and it retrieves all the tweets and archives them in a useful fashion, preserving a link to their original URI.&lt;/p&gt;

&lt;p&gt;I’ve been hassling Fred about this, as I like to do, because one of the reasons I have liked Twitter is because tweets have, or at least had, a sense of being ephemera. In my mind, if you feel like you need to archive your tweets, then you are doing it completely wrong.&lt;/p&gt;

&lt;p&gt;But that’s just my opinion and Fred’s is different. He says there’s good stuff in those tweets which you might want later. This is true enough.&lt;/p&gt;

&lt;p&gt;Today, in IRC, he said:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;without starting the whole discussion again, after
yesterday's(?) archiving exchange, it struck me as
odd that you're so indifferent - after all, you're a
proponent of cool URIs, which kinda includes permanence
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My response went something like this:&lt;/p&gt;

&lt;p&gt;Every tweet has its own URI already, the “statuses” URL, so the coolness is basically there already. Fred responds that Twitter is not reliable. This is true but I suggested that archiving was a short term solution to the problem that allows the long term problem to persist. The long term problem is that ones tweets live at Twitter, not in ones own persistent store: Twitter should be a presentation engine which has access to your own microcontent.&lt;/p&gt;

&lt;p&gt;This reminded me that in some ways what I’ve been working on for the last ten years or so with &lt;a href="http://en.wikipedia.org/wiki/Purple_Numbers"&gt;Purple Numbers&lt;/a&gt;, wikis in general, &lt;a href="http://tiddlyweb.peermore.com/"&gt;TiddlyWeb&lt;/a&gt;, persistent identifiers etc. are tools to make such things possible. What I’d like to see is an inversion of the current content relationship that is present on the web.&lt;/p&gt;

&lt;p&gt;Today I go to a web site and give it some output of my brain. The web site takes my content and in exchange it gives me a URL so I and other people can get to the content again. What should happen instead is that I make some content and give that URL to some websites so they can get to the content.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/83871624</link><guid>http://cdent.tumblr.com/post/83871624</guid><pubDate>Thu, 05 Mar 2009 20:38:22 +0000</pubDate><category>openweb</category></item><item><title>TiddlyWeb Store Migration Plugin</title><description>&lt;p&gt;Some of the people at &lt;a href="http://www.osmosoft.com/"&gt;Osmosoft&lt;/a&gt; are working on an additional StorageInterface for TiddlyWeb that enables development of tiddler content that is readable by TiddlyWeb, by Cook (the tool used to build TiddlyWikis out of content in the &lt;a href="http://svn.tiddlywiki.org/"&gt;tiddlyweb subversion repository&lt;/a&gt;. To help make using the new store, I’ve written a &lt;a href="http://svn.tiddlywiki.org/Trunk/contributors/ChrisDent/experimental/tiddlyweb-plugins/migrate/"&gt;plugin that can migrate TiddlyWeb data from one store to another&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;TiddlyWeb can host in one process as many different references to as many different stores (objects that implement the StorageInterface) as you like, so creating a migration tool is a simple matter of enumerating all the content in one store and putting it into another.&lt;/p&gt;</description><link>http://cdent.tumblr.com/post/78006403</link><guid>http://cdent.tumblr.com/post/78006403</guid><pubDate>Fri, 13 Feb 2009 13:03:40 +0000</pubDate><category>tiddlyweb</category></item></channel></rss>
