Technical description of the Perl code used to generate


This page describes the Perl code used to generate this website. I offer a pared-down version for download under the GNU free software licence. The website generated by that software may be seen here. If there is any interest in this I'll provide some of the bits of code I had cut out.

This software has been designed to facilitate the creation of new pages, new page groupings, change of site structure, page structure, introduction of new features, removal of unwanted features, sale of products via Paypal. It does require you to know Perl but not to be a Perl guru.

It has been written in a way that is easy to understand and to be so simple that modification does not require the period of immersive study normally needed when returning to update an old piece of code, i.e. the structure is easy to keep in your head.

1. Background

This site has existed for more than five years in various incarnations:,, and before becoming in July 2002.

During that time it has gone from

  • a frame based site consiting of a set of html pages grouped much as they are now,

  • to a frame based site having one long side index indexing each page on the site,

  • to a set of simple html pages looking much as the site does today,

  • to a Perl and mySQL based site similar to the current site where pages were delivered by a single program and pages were identifed using a path_info string,

  • to the current implementation as a loosely organised set of Perl programmes.

The transition from the mySQL based site to the current implementation was performed part-time over a nine month period, with both implementations running side by side with the differences between them not readily apparent to the visitor.

Initially the site had about 50 pages, now it has more than 160.

The last rewrite was motivated by difficulties I had in performing even trivial modifications to page and site structure. Adding new pages was painful. There was too much code, too many modules, and too much time needed to get back into the code and database. I only worked on the site part-time and did not need the hassle.

What I needed was a program/code organisation/structure which obviated the need for serious documentation, databases, or any complexity whatever. It also needed to let me make extensive changes simply and easily and preferably without a cumulative build-up of complexity.

I had been experimenting with different versions of what became the current design on three other sites I run -, the now inactive and These had been written with an eye to speedy update of data content and were evolving nicely. It seemed reasonable therefore to use their code structure as the basis for this site.

Prior to the rewrite less than 20 pages had been added to the site over a 2 year period. Since the rewrite, pages are being added at a rate of 5 or more per month, many pages are updated on a daily or weekly basis, and I have implemented at least three significant structural and organisational changes to the site.

2. Website structure in brief

The website consists of a set groups of pages relating to a particular subject area, e.g. a group of ladscape paintings. An index to pages belongng to the subject group is displayed on the left hand side of each of that group's pages.

The first page in each group is accessible via the main index which appears at the bottom of each page. The main index is also accessible as a page in its own right. In addition to the subject groups there exist arbitrary cross subject groupings, e.g. work in progress and recent pictures, represented as indexes whose entries link to pages within different subject groups.

Pages may contain images with or without titles, text of various sorts, lists etc. Additionally each page contains a comments form by which visitors may send a message to the website. Some pages contain links to PayPal specific to the purchase of particular pictures. For each of these there exists an additional page, accessible only through PayPal which thanks the visitor for their purchase and displays the picture they just bought, e.g.

Any page may be easily made printer friendly by the addition of a few lines of code.

Updating the code of every .pl file in the website is done by global edits.

3. Website overview in brief

mainDirectory - | | - subjectGroup1 -| - | | - | | - | | etc. etc. | | | - subjectGroup2 -| - | | - | | - | | etc. etc. | etc. etc. | | - | - | - | - | - | - | -

Figure: Program and directory structure within cgi-bin

Each page is represented by a separate Perl program, e.g.

Pages belonging to a particular group are held in a directory specific to that group, e.g. subjectGroup1.

Each group directory contains the group index as a Perl module, e.g. subjectGroup1/

The group directories exist within the main (cgi-bin) index for the site, e.g. /home/cgi-bin/mainDirectory

In adition to containing group directories the mainDirectory contains a number of modules and one program:

  • - processes POST data from the visitor comments form,

  • - parses PATH_INFO: which if present specifies the how the page request is to be processed, For instance .../subjectGroup2/ tells to take its side index data from .../ as opposed to taking it from .../subjectGroup2/

  • - contains the data required to create the main index,

  • - contains data required to create an index to work currently in progress,

  • - contains data required to create an index to the most recent pages.

  • - creates a page showing only the main index and displaying the same group index as the last page accessed, e.g. .../ This page is a legacy of a previous implementation and will be removed in favour of having the main index at the foot of every page. However, its presence here serves to show the ease with which arbitrary pages may be inserted into the site.

Excepting the mainMenu which uses tables, layout is done using CSS. I use tables to avoid the hassle of catering for Internet Explorer quirks in what is a fiddly area.

4. Program code structure

4.1. Program code representing page content and identity

Page content includes header content: <title> and <meta> keywords and description, and body content.

Header content is represented by a set of variables: e.g. $pageTitle, $metaKeywords, $metaDescription (figure 4.1 below).

Body content is represented as an array of hashes (figure 4.1 below). Each hash has a contentType which determines how the hash data will be processed by the module which generates the page. Example contentType types include headings, paintings with and without titles, paragraphs, verse, etc. Data passed to the program by POST data or PATH_INFO may be used to modify the data passed to PageFormatter for display and the identity of the PageFormatter routine called in order to do the formatting. For instance, .../subjectGroup2/ causes the thank you version of the page to be printed.

Page identity is given by the program file name, e.g., and by the name of the directory in which it resides, e.g. trees. This could be obtained automatically, e.g. by means of $0 and but specifying it explicity in the code is character forming. These values are required for reporting errors and where comments have been sent from and for obtaining the last modified date for the file.

my $metaKeywords = 'website,generator,perl,gnu,free,software,licence'; my $metaDescription = 'Perl website generator with GNU free software licence'; my $pageTitle = 'Perl code used to generate this website'; my $indexGroup = 'trees'; my $pageFileName = ''; my @contentAry = ( { contentType =>'titledPainting', pictureGroup =>'giants', pictureWidth =>420, pictureHeight =>317, pictureUrl =>'giants.jpg', pictureAlt =>'picture of giant¦#039;s causeway.', pictureTitle =>'Waves on Giant's Causeway', pictureDimensions =>'25 x 20', pictureMedium =>'watercolour with bodycolour', pictureDate =>'1998', }, # end anon hash { contentType => 'paragraphSequence', paraSequence => [ 'Not long ago one of my visitors asked me why I painted this picture. Here is a slightly edited version of my reply.', 'For the third or fourth time in my life I have been trying to make a living solely from the sale of my pictures and these seemed like a good subject that people might like to buy. ......', 'Why Hokusai? - well he painted a famous picture/print, called <a href=''>the wave</a> which uses highly symbolic notation to denote the foam on the wave's crest.', ], }, # end anon hash ); # end contentAry

Figure 4.1: page content representation

4.2. Code for turning page content into html output

This is done by the module.

The module is structured as follows:

  • The method: new - creates the PageFormatter object and stores the data and objects to be used in generating the html. This method is called by all programs.

  • A set of methods each of which creates a distinct page type, e.g. standardContent, printableContent. Each page generation program calls just one of these routines.

    These all have the same structure: a set of calls is made to turn content data into snippets of html code according to the contentHash{contentType}, e.g. paragraphSequence, unorderedListSequence.

    These snippets of html code are then embedded within a set of structural <div class='div_type'> tags which enable CSS code to position the html content.

    The completed html text is output to the browser and any emails that need sending are sent.

And that's it. That's as complex as it gets. All the pages in the website you are now browsing and websites: and have a version of the structure I've described here.

5. Code available under GNU fre software licence

If you wish to download and make use of this code you may do so under the conditions of the GNU free software licence.

Please send me your comments

If you include your e-mail I may reply!  

Page last modified: 19:31 Monday 13th. May 2013