This page is part of a static HTML representation of the TiddlyWiki at https://tiddlywiki.com/dev/

TiddlyWiki

15th July 2014 at 9:51am

Traditional web applications are bound to ~HTTP-Concepts, including stateless requests to transfer data. In these applications a state is often emulated by the use of sessions, which need to be handled on the client and especially on the server side. These restrictions often lead to a fragmented user experience because the user interface is rebuilt on every data transfer. TiddlyWiki tries to overcome these restrictions and the resulting disadvantages by building on few but basic concepts which loosen the coupling of HTTP and the actual application, eliminating the need of state emulation and resulting in a wiki style single page application with the ability to run in an offline environment.

TiddlyWiki as Single Page Application

TiddlyWiki builds on some basic concepts. First, TiddlyWiki should not be perceived as a dynamic web page like traditional server-side generated web pages. Instead TiddlyWiki can be perceived as an application which is written entirely in JavaScript and uses HTML5 and CSS3 to render a GUI. This way TiddlyWiki can be executed in any JavaScript environment like a browser or a node.js instance, while keeping the advantages of a simple application. One of these advantages is, that TiddlyWiki has no need to emulate an application state, as a traditional web application would need to do.

A second idea concerns the storage of the application data. In contrast to a traditional web application, TiddlyWiki doesn't store the data in an external database but simply uses native data structures already existing in JavaScript to store tiddlers, the basic (atomic) element of the TiddlyWiki application, in the memory. Additional core modules provide a way to persist this storage in simple HTML div elements.

Just by building on these simple and basic concepts,

  • TiddlyWiki is able to store application data in a single HTML page by using div elements as data container.
  • TW is able to store application code (JavaScript) in the same single HTML page.
  • TiddlyWiki can be executed in any JavaScript environment like a browser.

These points already enable TW to be used as an offline-enabled single file web application. Also, by using a server side node.js environment running the same TiddlyWiki application, TiddlyWiki can be used as an online web application. This is realized on server-side by providing an additional module to persist tiddlers into plain text files and on client-side by a module syncing the local data store with the node.js server.

Microkernel

In the universe of TiddlyWiki everything is a tiddler. Even the application logic is stored in tiddlers that are marked as "application/javascript". These tiddlers, which contain application logic, are called modules and a CommonJS compatible module system is responsible for assembling the individual modules into the TiddlyWiki application. The result is a tree representing the whole TiddlyWiki application containing module tiddlers, data tiddlers and some JavaScript functions and objects.

Only a small part of the TiddlyWiki is not managed as tiddlers, the microkernel. The microkernel is the first thing to run, when the application is started and it puts some initial objects and functions into the application tree, which are needed to load and manage tiddlers. After the microkernel built this initial application tree, the remaining parts of the application can be loaded as module tiddlers. Beside some utility functions the most important object that is contributed by the boot kernel is "$tw.wiki", consisting of JavaScript structures and functions that are used to store and manage the loaded tiddlers. Among other things this store can be used to add new tiddlers, remove tiddlers and retrieve tiddlers by name.

The microkernel constructs a initial $tw object containing the needed structures and functions.

Data Persistence

The next important part of the application are deserializers. Deserializers are responsible to load tiddlers from various sources. One of the deserializers provided by the microkernel for example can load new tiddlers from the current DOM tree. The counterpart of deserializers are saver. A saver is used to save the complete store or the complete TiddlyWiki for that matter at once. After a user made changes to some tiddlers, this method can be used to download the current state of the store as a completely new TiddlyWiki application.

Another way of persisting data are syncadaptors. Like deserializer and saver, a syncadaptor can load tiddlers into the store and can persist changed tiddlers. But in contrast to deserializer and saver it can load and persist single tiddlers. A syncadaptor can provide a list of loadable tiddlers registers at the store for changes. Now when a tiddler is changed and these changes are written to the store, the syncadaptor is triggered and persists the new changes, for each tiddler individually.

Tiddlers can be persisted from/to harddisk or synced with a remote server.

The User Interface

Following the "anything is a tiddler" concept, even the UI consists of tiddlers. This is possible because tiddlers can not only contain plain text or JavaScript (modules) but they also can contain a special markup text called WikiText. By using WikiText the user can put markup elements like tables or images in a tiddler. To provide some more sophisticated UI elements, WikiText can also contain special widgets like text input fields, checkboxes, dynamic lists etc. In most cases, these widgets are used to directly modify or represent the information contained in other tiddlers. If a tiddler is changed and this change should reflect in an UI element e.g. a widget, a process called selective update takes place. Selective updating means when a tiddler or a set of tiddlers changes, each widget is asked, if changes to this tiddlers would affect its appearance. If so, the respective widget is re-rendered otherwise it remains unchanged.

Modularization

The whole application is basically built from three parts. At first, the microkernel provides the basic functionality to handle tiddlers. The second part are tiddlers representing core functionality. These are for example modules which extend the store by more sophisticated functions, UI tiddlers and widget modules, a WikiText parser, sophisticated deserializers, savers, syncadapters, etc. These core modules are provided as plug-in to the microkernel. Consequently, a plug-in is a single tiddler which itself contains multiple tiddlers, forming the plug-in. Each of this tiddler might be a module providing new functionality (i.e. a module tiddler marked with "module-type: saver" can extend the application with new methods of saving the current wiki state.). Tiddlers provided in plug-ins are called shadow tiddlers. They are immutable and can not be edited or deleted but we can create a new tiddler with the same name to override a shadow tiddler.

Tiddler as Basic Element

By managing nearly every part of the application as tiddlers, the application is only needed to provide some basic functionality to manage the individual tiddlers, load and persist them, render them to HTML output and provide a way to register for the changes made to tiddlers. This way the whole wiki application can be build from these simple concepts. Plug-ins can be used to add new functionality to the existing modules or even to replace individual tiddlers/modules, enabling developers to build whole new applications on the TiddlyWiki base system.

A tiddler is the smallest unit of the TiddlyWiki system. It can contain any data like plain text, WikiText markup, JavaScript code (module tiddler), JSON structures (JSON structures might even contain additional tiddlers. Plug-ins are implemented this way to pack multiple tiddlers in a single plug-in tiddler), images in SVG format or even binary images encoded with base64. Internally Tiddlers are immutable objects containing a bunch of key:value pairs called fields. The only required field of a tiddler is the title field. The Standard fields of a tiddler are listed below. Nearly everything in TiddlyWiki is loaded as tiddlers. Plug-ins for example are a bunch of tiddlers that are distributed as a single JSON tiddler. The only exception is the microkernel which isn't a tiddler.

created
Timestamp number of milliseconds since 01.01.1970.
modified
Timestamp number of milliseconds since 01.01.1970.
tags
list of tags seperated by whitespace. Tags which contain whitespaces are wrapped by , e.g. example Tag.
type
Type of the Tiddler, e.g. text/plain or text/vnd.tiddlywiki .
title
Title of the Tiddler
list
An ordered list of tiddler titles associated with a tiddler

Tiddlers are used in multiple roles and on different levels. A developer uses tiddlers as the basic element containing application code, configuration values and even as a form of variable to save the current UI state. On a different level, a tiddler is also the basic unit of work for the wiki user, e.g. the individual wiki pages are implemented as tiddlers. This makes sense for multiple reasons: Because the UI of TiddlyWiki is build from tiddlers, the wiki user is able to edit the interface of his own TiddlyWiki just by editing a wiki page. For example to add a list of tiddler links to the sidebar, the user just needs to create a new tiddler, put the links into this tiddler and tag this tiddler with $:/tags/SideBar. This way the user can customise his work environment just by using mechanisms he already uses to manage his wiki pages. Tiddlers consist of fields. When using a tiddler as wiki page, the user can use these fields to store meta information, like tags.

Because fields for metadata and especially tags are an easy way for the user to organise his wiki pages, TiddlyWiki provides a special filter mechanism to choose tiddlers using their metadata. A filter string like [tag[learncard]topic[math]!tag[successful]] would filter all tiddlers tagged with "learncard", with the value "math" in the topic-field and are not tagged with "successful". A user could use this filter together with the <$list> widget to display a list of all math learncards which are not yet answered successfully in a wiki page.

Another example which shows how the "anything is a tiddler" concept leads to an environment where a single feature brings great benefit is the drag and drop feature. HTML5 standard comes with a native drag and drop feature. TiddlyWiki uses this feature and makes it possible to drag and drop a tiddler from one instance to another. And because anything is a tiddler, this brings the ability to drag and drop individual wiki pages, JavaScript modules, UI components and whole plug-ins between TiddlyWiki instances.

WikiText Markup

The WikiText is a markup language, created especially for the requirements of the TiddlyWiki application. It is based on Markdown, but extended with some TiddlyWiki specific features. On one hand its a text-to-HTML conversion language and on the other hand its used to provide the interactive features of TiddlyWiki. The aim of this language is to allow the user of the software to focus on the writing. The WikiText is used to format Tiddlers within the TiddlyWiki application. The tags of the WikiText syntax can be used within the standard text input field. During the saving process these tags renders to HTML elements for example:

WikiText:--- 
Renders as:
HTML:<hr>
WikiText:[img[https://tiddlywiki.com/favicon.ico]]
Renders as: TW
HTML:<img src="https://tiddlywiki.com/favicon.ico">

Furthermore the WikiText is used to access the widgets which are integrated in the application.These widgets are used to enhance the the WikiText with a rich functionality. Widgets are based on the ~HTML-Syntax but always starts with a $.

WikiText:
<$button message="tm-close-tiddler">Close Me!</$button>