Andrew McNabb

Smug: smugly superior to wikis

Smug lets you edit web pages live in a web browser. This may sound a lot like a wiki, but Smug is not a wiki. Wikis are based on a flawed model that assumes that content must be either open or stable, but not both. A page on a wiki is open, and anyone can edit it. This unlimited openness can lead to anarchy, expressing itself as users deface pages or fight over content. If it gets out of control, an administrator can lock a page, which completely removes all of the wiki's openness.

Smug does not require to choose between openness and ownership. In this sense, it is much more in line with open source software than with wikis. A page has an owner, who has full control over its content. Other users can edit a page, but their modifications are not automatically incorporated. Instead, the pages are prepared as a patch, which is submitted to the page owner. The owner then decides whether to accept or reject the patch. Submitting a patch in Smug is just as easy as editing a page in a wiki, but the result is openness without anarchy.


If you would like to participate in development, please sign up for the smug-dev mailing list (on Google Groups). There is also a smug-users mailing list for discussion about how to use or set up Smug.

The Git repository for Smug is at:


Issue tracking and mailing lists are hosted by Google Code under the smugweb project.

Smug is licensed under GPLv3. Some people seem to be opposed to the GPL. If you have a good reason for me to release it under a different license, let me know. I'm open-minded about these sorts of things.

How Smug works

Smug is written in Python. It stores its data in the distributed version control system Git, which is also used to manage the source code of the Linux kernel and many other large projects. Smug's web interface is built in the Django framework and makes use of the Django templating system.

Installation and Setup

If you would like to get Smug working as quickly as possible, please refer to Simple Setup. If you are already using Django and want to use Smug in the same Django project, you should instead read Advanced Setup.

Filters and Templates

The Git repository stores the content, but Smug needs to decide how to present it. Smug filters provide a variety of ways to interpret the content. If no filter is configured for a file, Smug will guess the MIME type from the file extension and output the content as-is. The following filters are currently present in Smug.

The plain text filter outputs the content as-is but assumes that the MIME type is text/plain. I use this for template files; these files have an html extension, but it makes more sense to display them as text.
This site uses the template variables filter for all normal html pages. The filter requires a Django template file, which in this site is template.html. The contents of the page are passed into the context as "contents". The title of a page is passed in as "title" if it can be determined. If a comment were found in the first line with the form, "<!-- title: This is the Title -->", then "This is the Title" would be interpreted as the title. Other than the title comment, the page is simple html.
Users who would like to do more complicated things with Django templates can use the extend template filter. The filter requires a base template file, and the contents of the file should contain Django block tags to override blocks in the base template.
Those who like maintaining content in ReST format can present their content as html on the fly.

Future filters will add support for other markup languages, and conversions.


Smug is still a pretty new project. I like to think that the code is pretty clean and flexible, but there are still a lot of missing features. Send me an email if you have any patches you like to submit. The TODO file lists off a bunch of things that need to be done. Note that to simplify copyright issues, I request that you transfer ownership of submissions.

The project is already functional. Smug can serve up a Git-backed site, directly from the repository (i.e., no working tree is needed). As Git users push updates to the repository, they are instantly available online. MIME types are correctly set, so images and other files can be served up directly from Git. The authentication system works (using Django's authentication system). Any logged-in user can commit changes and create new branches.

Here are some of the more urgent features I would like to add:

Anonymous edits (in progress)
Anonymous users should be able to do an edit. The result should be submitted as a patch.
Blog support
I'm still figuring out how blog support would look, exactly. Each blog entry would be a separate file in the repository. I suppose there would be another file that lists all of the blog files in order, possibly with metadata like the entry name and post-date. We would then have some front-end tools that make it easy to add entries. We would probably also have a shell script to do the same thing, so that it's easy to manage the blog on the command line.
Add button
At the moment, there is only an edit button for existing pages. You can add a page by typing the edit url in the browser, but we need a button that makes it easy to create a new page.
Unicode support
Unicode works in basic edits—for example, the preceeding em-dash was added from a Smug web form. However, Smug still needs additional testing with Unicode.
Markup languages
Support for ReST is included, but other wiki-like markup languages is on the list.
I'm still brainstorming about how to show and enforce ownership. It's possible that the only way to do this would be using multiple repositories (which Smug already supports).
Powered by Smug