NAME
Miril::Manual - Why and how to use Miril, the static content management sytem.
WHAT IS SPECIAL ABOUT MIRIL
Miril is written in perl and uses the CGI::Application framework.
Miril stores your data in a backend (text files, a database, etc.) and publishes it to static pages. Unlike homegrown static publishing solutions (e.g. scripts using the Template Toolkit), Miril provides a nice user interface for editing content (web-based or via a command-line application).
Miril has been designed from the very start to be extremely easy to deploy. The main distribution has only pure-perl dependencies. Stable Miril versions will be available in a tarball with all dependencies bundled, so that installing on a typical shared host should be a no-brainer.
Miril has been designed with small to medium-sized websites in mind, i.e. websites with hundreds of pages as opposed to thousands of pages. If you have a typical small website such as a corporate website or a personal blog Miril may be a better deal for you than full-blown content management systems since it is faster to deploy, easier to manage, and generally has less administrative overhead both for the site administrator and for the users.
Miril has a user interface that has been deliberately kept extremely simple and uncluttered. The goal is for the end users of Miril (those in charge of managing content) to require little or no training to start using it. This means that some of the administrative tasks (such as user management and adding special types of pages) can only be performed by editing the configuration files and templates manually. For a similar reason, Miril also takes a very simplistic approach towards access management and does not provide roles or complex permissions. In fact, Miril has been designed to be used in teams where 1) users generally can trust each other and complicated access management is not necessary and 2) there is at least one tech-savvy user who can take care of the occasional administrative tasks.
Miril is extensible. You can choose between different storage backends (currently only a file-based backend is provided), different templating systems, etc.
DEPLOYMENT OPTIONS
Miril is run as a cgi script. This means that:
On a shared host, you can run Miril from your
cgi-bin
directory. It will run slower than in amod_perl
environment, but since Miril will be used only when managing content this should not be a problem.Of course, if you have sufficient control over your environment and the load on Miril demands it, you can accelerate Miril by running it under
FastCGI
ormod_perl
.Because Miril ultimately produces static content only, you can run it from your local machine and then synchronize your local output directory with the web server. This way you can manage websites on servers that don't even have
perl
installed, or where installing Miril would be difficult.
INSTALLATION
Currently Miril is installable only from CPAN
. Simply run install Miril
from your favourite CPAN
shell. The CPAN distribution comes with an example website you can build on to get started faster.
CONFIGURATION
Create required files and folders
Miril requires that you have the following files and folders in place:
~/miril - Base Miril directory
~/miril/sites - Site configuration and data
~/miril/sites/some_site/cache - Directory where Miril caches stuff
~/miril/sites/some_site/data - Directory where Miril store data files
~/miril/sites/some_site/tmpl - Directory where you keep the templates for building your site
~/miril/sites/some_site/cfg/config.xml - Main configuration file
~/miril/sites/some_site/cfg/users.xml - Usernames and passwords
~/miril/sites/some_other_site - You can keep info about more than one site
~/miril/lib - If you downloaded Miril with bundled dependencies, they will be here
Of these, the two configuration files are the only ones that you need to create manually, and more information is provided below. All other stuff is written by Miril itself, but it does need the directories to exist first. You can just unpack the example site provided with the Miril distribution to get started faster.
Create a cgi script
Once you have installed Miril, create a cgi script named miril.pl
or miril.cgi
with the following content:
#!/usr/bin/perl
use strict;
use warnings;
use Miril;
my $app = Miril->new( PARAMS => {
miril_dir => $path_to_base_miril_dir,
site => $name_of_website,
});
$app->run;
A single Miril installation can handle multiple websites. $path_to_base_miril_dir
should point to the base Miril directory, for example ~/miril
. $name_of_website
is the name of the website that will be managed by this particlar Miril instance (e.g. some_site
or some_other_site
).
Create a configuration file
Make sure you create your configuration file in the location that you chose above. Currently only XML is supported for the configuration file format.
Basic configuration options
A minimal configuration file has the following content:
<xml>
<output_path>~/miril/www/some_site</output_path>
<files_path>~/miril/www/some_site/files</files_path>
<domain>www.example.com</domain>
<http_dir>/</http_dir>
<files_http_dir>/files/</files_http_dir>
<secret>Some secret line</secret>
</xml>
The options are explained here:
- files_path
-
This is the directory where files (e.g. images, pdf files, etc.) uploaded by Miril users will be stored. Miril must have read-write access to this directory. In a typical installation this directory will be somewhere below your server's document root.
- output_path
-
This is the directory where Miril will place all the output files it produces. In a typical installation this directory will be somewhere below your server's document root.
- http_dir
-
This is the base URL of your website and Miril will use this string to prefix all URL's that it produces. If your website is located at
http://www.example.com
, you would sethttp_root
tohttp://www.example.com
to produce fully qualified URL's. If you want your website to have relative URL's, you need to leave this option empty. If your website is located athttp://www.example.com/mywebsite
, you would sethttp_dir
tohttp://www.example.com/mywebsite
for fully qualified URL's and to/mywebsite
for relative URL's. - files_http_dir
-
This option specifies the base URL for accessing the files managed by the
files_path
option above. It follows the same rules ashttp_root
. - domain
-
If you have specified a relative URL in
http_dir
above, use this option to provide the domain name of your website for cases where fully qualified URL's are needed, such as RSS feeds. Leave empty if you have sethttp_dir
to a fully-qualified URL. - secret
-
A random phrase used for security purposes when encrypting authentication data stored in cookies (required by CGI::Applciation::Plugin::Authentication::Cookie).
- view
-
Which view module, or templating system, will be used to render your site. Default is
HTML::Template
, which will load Miril::View::HTML::Template. You can also set this toText::Template
, and additional templating systems may be added in the future.
Configuring content types
Next you may need to configure your content types. This is what a basic configuration looks like:
<xml>
...
<types>
<type>
<name>Story</name>
<id>story</id>
<location>story</location>
<template>post.tmpl</template>
</type>
<type>
<name>Page</name>
<id>page</id>
<location></location>
<template>page.tmpl</template>
</type>
</types>
...
</xml>
You will get these two content types by default if you have not specified your own content types in the configuration file.
- name
-
The user-friendly name of the content type, as it would appear to the end user.
- id
-
A unique alphanumeric string identifying the content type, used internally by Miril.
- location
-
The location, relative to
output_path
, where Miril will write entries of this content type. - template
-
The template file Miril will use to create html pages of this content type.
Creating lists
Miril allows you to create special pages which combine data from multiple posts - e.g. a list of articles, a RSS feed, etc. This is how you configure lists:
<xml>
...
<lists>
<list>
<id>news</id>
<template>news.tmpl</template>
<location>news.html</location>
<match>
<type>story</type>
<status>published</status>
<last>6</last>
</match>
</list>
<list>
<id>feed</id>
<template>atom.tmpl</template>
<location>atom.xml</location>
<match>
<type>news</type>
<status>published</status>
<last>10</last>
</match>
</list>
</lists>
...
</xml>
- id
-
A unique alphanumeric string identifying the list.
- template
-
The template file Miril will use to create this list.
- location
-
The location of the file, relative to
output_path
, where Miril will write this list. If this is a grouped or paged list (seegroup
andpage
below) this parameter accepts a Text::Sprintf::Named string used to generate the location of the individual grouped or paged lists.
Parameters accepted for grouped lists
Lists grouped by date:
date
,year
,month
.Lists grouped by month:
year
,month
.Lists grouped by year:
year
.Lists grouped by topic:
topic
.Lists grouped by type:
type
.Lists grouped by author:
author
.
Parameters accepted for paged lists
page
, specifies the current page number
- group
-
Specifies a grouped list. A grouped list will split the posts it matches into groups and output individual files for each group. This is a powerful option that allows you for example to create archives by month or by year or create lists of posts by topic. The following values for the group option are accepted:
date
,month
,year
,topic
,type
,author
.Group
works in conjunction with a sprintf-like format in thelocation
option to define the output paths for the individual list files to be produced. - page
-
Specifies a paged list. A paged list will split the posts it matches into smaller lists each containing the number of posts specified as an argument to the
page
option, and prodice an individual output file for each such list. It works in conjuntion with a sprintf-like format in thelocation
option to define the output paths for the individual list files to be produced. Additionally, thelist
object passed to your template file has apager
attribute, containing a Data::Page object for the current page. - match
-
The
match
elemement is used to determine which posts are included in the list. The filtering criteria are:- type
-
Only return posts with this type id.
-
Only return posts with the specified author.
- topic
-
Only return posts with the specified topic id.
- last
-
Only return the N most recent posts matching the above criteria.
Only published posts can be included in the list (i.e. posts whose status is
published
and notdraft
).
Specifying authors
Miril allows you to specify the author of each post. The list of authors is specified in the confuguration file as follows:
<xml>
...
<authors>
<author>J. R. R. Tolkien</author>
<author>J. K. Rowling</author>
</authors>
...
</xml>
Note that any registered user can specify any author name for any post, so this is used only to display post information in the published site rather than to control access. This is part of Miril's design philosophy (trusted team).
Specifying topics
Miril has basic support for topics, or categories. The list of topics is specified in the confuguration file as follows:
<xml>
...
<topics>
<topic>
<id>flowers</id>
<name>Flowers</name>
</topic>
<topic>
<id>animals</id>
<name>Fuzzy Animals</name>
</topic>
<topic>
<id>bananas</id>
<name>Bananas</name>
</topic>
</topics>
...
</xml>
Each post can then be associated with one or more topics.
Create a users file
You need a file with information about users and passwords in order to run Miril. The file must be named usres.xml
and be located in the directory specified by the cfg_path
option in the main configuration file. Currently only XML is supported as the configuration file format. The structure is as follows:
<xml>
<user>
<name>J. R. R. Tolkien</name>
<password>123456</password>
<username>tolkien</username>
</user>
<user>
<name>J. K. Rowling</name>
<password>123456</password>
<username>rowling</username>
</user>
</xml>
Passwords can be stored either in plain text, or encrypted (using the MD5 algorithm). When you create a new user, you initially specify their password in plain text and them tell them to log in with this password but change it immediately afterwards. When a password is changed using Miril's user interface, it will be stored encrypted in the above XML file. Similarly, if a user has forgotten their password, you can temporarily reset it manually to a plain-text password and ask them to change it again.
Miril is not accessible to unregistered users. All registered users have identical permissions and can edit and publish all types of content.
Create your output templates
Once the configuration and users files have been set up, you can run Miril and edit content. In order to publish content, however, you need to provide the templates which will be used to render your pages. The templates are located in the directory specified by the tmpl_path
option in the configuration file, and must contain all the templates specified when configuring content types and lists, as well as any additional templates referenced by them (such as headers and footers). Currently the only supported template format is HTML::Template with HTML::Template::Plugin::Dot. The templates are initialised with the die_on_bad_params
option set to false, and the global_vars
option set to true.
Posts
Each template used to generate an individual post is passed a post
paremeter, which is a Miril::Post
object containing all information about the post being rendered. The structure of the post
object is as follows:
- post.title
-
The title of the post.
- post.id
-
The alphanumerical id of the post.
-
The teaser of the post, rendered into html.
- post.body
-
The full text of the post, rendered into html.
- post.type
-
A
Miril::Type
object. Has four properties:id
,name
,location
andtemplate
. - post.url
-
A
Miril::URL
object. Has three properties:abs
- an absolute URL,rel
- a relateive URL, andtag
- a tag URI for Atom feeds. -
The author of the post.
- post.published
-
A
Miril::DateTime
object. Has three methods:epoch
- returns epoch time,iso
- returns time in an ISO-compliant format suitable for Atom feeds, andstrftime
- returns time formatted on the basis of the "strftime" in POSIX-compliant string passed as an argument. - post.modified
-
A
Miril::DateTime
object. See above for details. - post.topics
-
An arreyref of
Miril::Topic
objects associated with this post. Each topic is an object with two properties:id
andname
.
Lists
Each template used to generate a list is passed aa list
paremeter, which is a Miril::List
object with the following methods:
- list.id
-
List id (as specified in the configuration file).
- list.title
-
List title (as specified in the configuration file).
- list.posts
-
An array reference of
Miril::Post
objects contained in the list. See above for details. - list.url
-
A
Miril::URL
object representing the URL where the list will be visible when published. - list.count
-
The number of posts contained in the list.
- list.group
-
A method that groups the posts in the current list according to the parameter passed, and returns a list of
Miril::List
objects representing the resulting lists. Accepted parameters aredate
,month
,year
,topic
,type
andauthor
. If called without arguments, returns the parameter by which the current list has been grouped, andundef
if the list was not generated as a result of grouping. - list.key
-
For lists that have been generated as a result of grouping, returns an object that can be used to identify the current group. For example, when a list has been grouped by topic, the
key
method of each of the resulting list objects will return aMiril::Topic
object representing that list's topic. Similarly lists grouped by type are identified by aMiril::Type
object, lists grouped by date, month or year are identified by aMiril::DateTime
object, and lists grouped by author are identified by an author string. - list.timestamp
-
A
Miril::DateTime
object representing the time of createion of the list. Useful for Atom feeds. - list.post_by_id
-
Returns an individual post from the list.
USER INTERFACE
Once you have configured Miril, you can access it by typing the url of the cgi script you created, e.g. http://www.examle.com/cgi-bin/miril.pl
. Miril's user interface has the following elements:
Posts
This is the main screen. It displays a list of all content entries. It provides links to search entries or to post a new entry.
Files
Displays a list of all files the user has uploaded and a link to a file upload form.
Edit Post
This screen is displayed when creating a new post or when modifying an existing one. Most of the options should be self explanatory, but there are a few things to keep in mind:
The ID field is an aplphanumeric string which servers as an unique id for this post. Future versions may create this id automatically and hide it from the user altogether. It may be useful, however, to specify it manually, since this id is used to generate the url of the output file (usually by attacing
.html
at the end) and the user may want to have control over the url for SEO purposes.The status field has two options -
draft
andpublished
. Posts marked asdraft
will be available for viewing and editing from Miril's UI, but will not be published to the live website.The post text is run through a filter before publishing. Currently only Markdown is available via the Text::MultiMarkdown module.
Additionally, you can break your post into a teaser and full text by inserting the
<!-- BREAK -->
string somewhere in the post text. The content before the break mark will be available in theteser
property of thepost
object passed to your templates.
Other data passed to templates
In addition to the post and list objects respectively, each template file is passed the following arguments:
- id
-
The string id of the respective post or list object
- title
-
The title of the respective post or list object
- cfg
-
The global Miril configuration object (i.e. the contents of the configuration file as a hashref).
CAVEATS
There are no tests yet.
The code is messy and buggy - this is still an alpha release!
The API is going to be changing a lot before the 1.0 release, so be sure to keep up with the development process (see "SUPPORT" below) if you plann to use Miril at this stage. Things that may change include the structure of the configuration file, the structure of the
post
objects, and the API for extending Miril.
SUPPORT
Website
The Miril website will be located at http://www.miril.org.
Bugs and feature requests
Please use the Github issue tracker at http://github.com/pshangov/miril/issues to report bugs and request features.
Mailing list
Support can be obtained via the Google Groups page: http://groups.google.com/group/miril.
Repository
Miril is hosted on Github at http://github.com/pshangov/miril.
AUTHOR
Peter Shangov, <pshangov at yahoo.com>
COPYRIGHT & LICENSE
Copyright 2009-2010 Peter Shangov.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 484:
Expected text after =item, not a bullet