bengillies.net

a blog by Ben Gillies

Running on TiddlyWeb, Part 2

Ok, so we got TiddlyWeb up and running in Part 1. The view that you get from this is fairly plain though, and definitely doesn't look anything like this site. So the next couple of steps involve customising and finalising the install. Most of this is pretty much the same as for any other version of TiddlyWeb, so I'm only going to cover it briefly as information already exists elsewhere.

Step three: Customising



The first thing we'll probably want to do is make a new bag and a couple of recipes. You can do this using twanager and running the following commands from inside your instance directory:

twanager bag <bag_name>
ctrl-D

twanager recipe <recipe_name>
/bags/system/tiddlers
/bags/<bag_name>/tiddlers
ctrl-D


You'll probably want to stop guests from editing your site too. For this, you'll need to create a user account with twanager. You can then set access policies from within each bag to ensure that you're the only person that can write to them. You'll also want to ensure that your web server can write to the store. You can do this using the chmod function. For more details on how it works, type:

man chmod


into a command line.

Once you've done this, the final step before you get into TiddlyWiki itself involves the .htaccess file in the root of your web directory. Open this up and ensure that put and delete are both enabled. Then type in the following, or ensure that something similar exists:

RedirectMatch ^/$ http://<your_domain_name.com>/index.cgi/

SetEnv PATH_INFO /


The RedirectMatch command ensures that whenever somebody types in your URL and hits enter, they get redirected to your TiddlyWeb install. The SetEnv command simply places a forward-slash into the PATH_INFO variable and is necessary in case anybody misses out the slash at the end of index.cgi, which would otherwise result in a 404.

Finalising



Now that your setup is customised and you have some recipes, bags and your own user name, we'll add a few plugins to get TiddlyWeb to load a TiddlyWiki by default.

Plugins in TiddlyWeb can be in two forms - server-side, or client side. Server-side plugins are wirtten in Python, and included by modifying tiddlywebconfig.py. Client side plugins are written in javascript and take the form of standard TiddlyWiki plugins, of which there are loads.

So first things first, let's add a server-side plugin to display one of two recipes (in the form of a TiddlyWiki) depending on whether the site visitor is logged in as an admin, or not. This plugin is called cachinghoster and can be found here. Drop it in the same place as tiddlywebconfig.py and point the links inside the file to the appropriate recipes. Ideally, one of these should allow you to update your blog and one should not. Then open tiddlywebconfig.py and add the following command:

'system_plugins': ['cachinghoster'],


Then just run "twanager server" in order to install it, and manually exit again. Now try opening your site again. You should get a TiddlyWiki loading up by default. With any luck, this should change to a different TiddlyWiki depending upon whether you are logged in or not. This will be primarily to ensure that your site is read only when people visit.

Finally, install the BlogLayout plugin by simply copying the contents across into a new tiddler, and tagging with systemConfig. It should save automatically (you will need to be logged in though) and will present you with a default view of al tiddlers, tagged with "blog", listed in date order with the most recent entry first. By default, it will also summarise these and add a read more link to the bottom. This functionality can be altered, or added as links manually in other areas too (see the links at the top of this site for an example) and more details can be found out in the BlogLayout plugin itself.

Well, that's it. Other than that, you might like to install a theme, or create your own, but you should now have a fully functioning blog created in TiddlyWeb.

Happy Blogging....

Running on TiddlyWeb, Part One

As I've just finished putting this site together, I thought I'd give you a brief overview of TiddlyWeb (the platform this site is built on) and how I went about implementing it.

First things first, there's quite a lot of documentation about TiddlyWeb already (see here) so I'm not going to explain the basics about it, or try to detail the underlying structure. All I'm going to do here is provide a set of instructions for installing and running TiddlyWeb on a setup similar to mine.

So what's my setup?

I'm running this site on Apache and Linux. I'm running Python through CGI, and I don't have root access to the server. If this sounds like you, then you've probably got one of the many hosting companies around providing you with your own web space on one of their servers. I would imagine this is a fairly common situation and unfortunately, requires jumping through a few extra hoops than the other install methods available, but here we go anyway.

Step One: Installing TiddlyWeb



The first hurdle to jump over is actually installing TiddlyWeb itself. Now, TiddlyWeb is usually installed with the Python tool "easy_install" but, if you don't have easy_install you're going to have to install it. The main problem with this however is the lack of root access. So to start, we're going to install Virtual Python. This is a tool that creates a virtual install of Python in your home directory and lets you install other libraries on top of that. So go here to install Virtual Python. Then go here and install easy_install from this script. From here, normal instructions can be followed for installation, so do:

easy_install -U tiddlyweb


Step Two: Setting up an Instance



Now that TiddlyWeb's installed, we need to create an instance in the directory you publish websties in (most likely public_html). So, go into this directory and run:

twanager instance <instance_name>


Where <instance_name> is the name you want to give your wiki. This will then set things up for a default install, creating the store (where your content is stored) and creating a default config file called "tiddlywebconfig.py". However, we don't want a default install, so go and grab the index.cgi file from the svn repository and drop it in the root of your web directory (e.g. public_html). Now open it up in a text editor (vi, nano, etc) and do the following:

Change the path at the top of the file to be your virtual python install path

then set the following:

file_store_location = <path_to_your_store> 
//most likely <instance_name>/store


Then check that the following lines are either commented out or do not exist (note that these changes may be implemented in a future version of TiddlyWeb, thus saving you the bother):

#sys.path.append('/home/cdent/src/TiddlyWeb')

#web_server_base = '/tiddlyweb/index.cgi'

#   hostname = os.environ['HTTP_HOST']
#   if ':' in hostname:
#       hostname, port = hostname.split(':')

#   config['server_prefix'] = web_server_base


and finally make sure the line
app = serve.load_app(hostname, port, config['urls_map'])

looks more like this:
app = serve.load_app()


That's it for now, so save and quit and load up tiddlywebconfig.py in a text editor. Add the following lines:

    'server_prefix': '<instance_name>/index.cgi',
    'server_host': {
    'scheme': 'http',
    'host': '<domain_name>',
    'port': '80',
    },


Save and quit. That should be it, TiddlyWeb should now work. Open up your browser and point it to http://your_domain_name/<instance_name/index.cgi/ to browse through bags, recipes, etc. Note that you will need the forward slash after the index.cgi, or you'll probably get an error.

Coming in Part 2 - Configuration and finalisation

Update


The index.cgi file has now changed. Please see CGI Install Update for more information.

A personal OpenID server


I've been looking at the TiddlyWeb log in system recently, specifically its support for OpenID, and my thinking went something like the following: "TiddlyWeb supports log in via OpenID (if you have one), and this is a blog that one person (that's me) needs to be able to log in to. What would be cool, would be if I could host my own OpenID server and use that to log into TiddlyWeb".

So after a bit of digging around, I came across a solution in the form of phpMyID which is an OpenID server serving one user only. First off, if you're not sure what OpenID is, the OpenID website describes it as follows:


OpenID eliminates the need for multiple usernames across different websites, simplifying your online experience.

You get to choose the OpenID Provider that best meets your needs and most importantly that you trust. At the same time, your OpenID can stay with you, no matter which Provider you move to. And best of all, the OpenID technology is not proprietary and is completely free.


All that looks very well and good so what's the downside you ask? Well unfortunately, support for OpenID isn't that great. A number of sites support it, but that support is hardly universal across the whole web.

Anyway, back to phpMyID. As the name suggests, it is written in php, so isn't really that compatible with TiddlyWeb (being written in Python), though being completely open, that doesn't really matter. The instructions on the site are fairly comprehensive, so to install it yourself, just follow them. As you do though, bear in mind the following points:

Finally, to integrate with TiddlyWeb/TiddlyWiki (it should work with both as long as you can put phpMyID on a server somewhere), enter the following into MarkupPreHead:

<link href="http://openid.bengillies.net/" rel="openid.server"/>
<link href="http://openid.bengillies.net/" rel="openid.delegate"/>


Where http://openid.bengillies.net/ is the path to your OpenID Server (e.g. - MyID.config.php - read the install instructions, ad you'll know which file I mean).

CGI Install Update

Update - These instructions have been superseded. Please see CGI and TiddlyWeb 1.0 for up to date instructions

Following on from my original post Running on TiddlyWeb, Part One, there has recently been an update to the index.cgi file to make installing clearer and easier to understand. The new file can be found on github at http://github.com/tiddlyweb/tiddlyweb/blob/master/index.cgi. This simplifies the first stage of the install procedure to the following:

  • Run this script from python.
  • Run this script from the new instance of python created in your home directory.
  • Type easy_install -U tiddlyweb into a command line and hit enter.
  • TiddlyWeb should now be installed. Type twanager instance <instance_name> somewhere in your home directory.
  • Copy index.cgi to somewhere in your public_html folder.
  • Move the tiddlywebconfig.py file from your instance to a different folder.

That first part should be fairly similar to the old method of installing. The main difference comes in how you edit the index.cgi and tiddlywebconfig.py files. So from here, go into index.cgi and change tiddlywebconfig_dir = <path to your tiddlywebconfig.py directory>. Then change os.environ['PYTHON_EGG_CACHE'] = <path to your ".python-eggs" folder>. With virtual python, this is "~/.python-eggs". Also, make sure that the path to python at the top is the path to your virtual python install.

Save that and go into tiddlywebconfig.py. enter the following information:
 'server_store': ['text', {'store_root': '<path to your instance>/store'}],
'server_prefix': '<path to your index.cgi file>',
'server_host': {
'scheme': 'http',
'host': '<your domain name here>',
'port': '80'},


Hopefully, this should make things simpler to understand, and easier to use. So from this point, continue the install as before to get tiddlyweb up and running.

How to make a Template in TiddlyWebPages

Since I announced TiddlyWebPages, I've been meaning to write a quick tutorial explaining how to make templates and define custom URLs for use on your site. In this post, I'll just cover templates and save URLs for another day. So let's start off at the point where you've installed TiddlyWeb, you have some content in your store, and you've installed TiddlyWebPages.

Right, the first step is to create a bag called templates and a bag called urls. Within the templates bag, you'll need to create a "wrapper" template. This will be the wrapper for all your content, so you can add links to your CSS definitions and Javascript files (or anything else) here without needing to include such things in every template. It needs to be called "Default" as it's the first one (and you need some sort of default right?) and while you can add other wrappers, we're not going into that quite yet. For now though, get the Default tiddler in the TiddlyWebPages GitHub directory at http://github.com/bengillies/TiddlyWeb-Plugins/raw/master/tw_pages/Default.tid and put it into your templates bag. You'll notice a couple of extra fields. list_tiddlers lets you specify the default template to use with a list of tiddlers (be it a bag, recipe or search results) while single_tiddlers does the same thing but for displaying a single tiddler only.

Your First Template


Now that's done, you can start adding templates. Now, as templates are all tiddlers themselves, you may want to just copy some from somebody else (my templates for example), but as this post is entitled "How to make a template", we'll assume you want to start from scratch.

Create a tiddler in the templates bag entitled "List". This will simply list all tiddlers in the bag/recipe that you are in, showing both the title, and the text. Next, enter the following information into the body of the tiddler:

{% for tiddler in base %}
<h1>{{tiddler.title}}</h1>
{{tiddler.text}}
{% endfor %}


Let's take a look at that line by line shall we?
{% for tiddler in base %}

This line starts a loop over all tiddlers, giving each tiddler in the list (called base, short for "base tiddlers") a name that you can refer to it with of "tiddler". "base" is a value that TiddlyWebPages provides you with to access the base set of tiddlers in the bag/recipe.

You can add other tiddlers, pre-formatted with another template, by specifying the template/recipe combination as a field in the template you want to include it in. For example, let's say you have created a "Header" template already and want to include it in your "List" template. Let's say that the tiddler that defines your header, is returned by the "my_header" recipe. To do that, you'd add a field to the "List" template specifying the "Header" template and the "my_header" recipe:
Header: my_recipe?select=title:ListHeading

In this definition, "Header" is the title of the field, and specifies the template you want to use, while "my_recipe" specifies the recipe that you want to use. Anything after the question mark is run as a filter on the recipe. In this case, we are selecting the ListHeading tiddler from the recipe. The ability to filter recipes is especially useful for sorting tiddlers, as recipes cannot sort by default.

Adding this Header into the template, would produce a result as follows:
{{extra['Header']}}
{% for tiddler in base %}
<h1>{{tiddler.title}}</h1>
{{tiddler.text}}
{% endfor %}

Notice the new variable called "extra". This contains the HTML for any extra templates you have specified in the tiddler's "fields" (as above). This gives two main variables that you can use: base; and extra. Other variables are: prefix - any server prefix you have defined in tiddlywebconfig.py; query - a key/value list of all items in the query string of the url; root_vars - a key/value list of any patterns that you have specified in your URL (by default, this will contain the tiddler name, in root_vars['tiddler'], the recipe name in root_vars['recipe'] and the bag name in root_vars['bag']).
<h1>{{tiddler.title}}</h1>

You can put HTML wherever you like, which can form the basis of your template. The tiddler.title is enclosed in double braces - this tells TiddlyWebPages (actually the Jinja2 templating engine) that tiddler.title is a variable and you want to write its value into the page. The {% ... %} pattern tells Jinja2 that you want to run something without writing the output to the page. In the example above, this would be the for loop.

{{tiddler.text}}
{% endfor %}

These lines just output the text of the tiddler and close the for loop. Optionally, you can choose to wikify the text by passing it through a filter and specifying a recipe name to use when creating links. If you did this with the recipe "sitecontent" (the recipe on my site that contains all my tiddlers) then you'd end up with the following:
{{tiddler.text|wikifier('sitecontent')}}

In addition to all the standard Jinja filters and the wikifier, there is another filter called "shorten" that you can use to safely shorten HTML without worrying about cutting off closing tags.

Now that you've done that, you'll want to test it. So go to the tiddlers in one of your bags, and append ".List" to the end of tiddlers to see the result. You can try this on my site by going to http://bengillies.net/.a/recipes/blog/tiddlers.ContentList (my template is a bit more complicated though).


Finally, please read through the Jinja2 documentation to get a better idea of what you can accomplish. You can find it at http://jinja.pocoo.org/2/documentation/templates

You can also view my Templates at http://bengillies.net/.a/bags/templates/tiddlers If you want to use any of them yourself.