Autohandlers

In the previous section we wrote a full HTML file in a single template.
This is not how you want to write websites, though, normally you would put
the header in a file, footer in a file, and include them both in each
template—in order to not duplicate the header/footer information.

Sytes provides a better mechanism inspired from
Perl's HTML::Mason module (which in
turn, if I remember correctly, was inspired
from HTML::EmbPerl).
Auto-handlers are files that your templates implictly “inherit” from, and
where you can add stuff like header/footer, include scripts etc. After
over 10 years of Web development, I have yet to see a more powerful
technique for writing websites. This very website uses autohandlers a
lot, and it's a core concept in Sytes.

Essentially, if you drop a file named “autohandler.syt” in the
root directory, then any request to execute a template will instead call
the autohandler, providing a function that runs the original template.
The autohandler can setup header/footer and execute the original template
whenever it's convenient by calling (call-next).

So let's modify the previous syte like this. Let's create a
file autohandler.syt in the root directory:

If you access the page now at http://foobar.local/ you should see
pretty much the same result, although our index.syt file is a lot
simpler. One little gray area is the fact that we can't include the page
title in the <title> tag now, because we don't know it. At
the time the autohandler is run, the requested template
(index.syt) is still pending execution, therefore what could we
display in <title>?

The following version answers this question. Here's the autohandler
first:

The above autohandler calls the template first, before getting to
output the actual page contents. A function provided by Sytes — @attr — allows you to pass information between templates, so because
we have (call-next) early, the 'TITLE
attribute will be available when we generate the <title> tag.

The output of the template is saved in a local variable CONTENT, and it'll be inserted into the main output at the right time
(i.e. in the DIV with class "body").

Just a side note, here is the definition of @attr if you
want to understand how it works:

You can notice here that there's a *attributes* global
function. That's defined by the system and it returns the value of a
Common Lisp dynamic variable which is bound to a fresh hash table on each
request. This variable is shared between templates, so whatever you put
into it in one place will be visible in another over the course of a
single request. The function @attr itself takes one or two
arguments. If you pass a single argument, it'll return the value of the
specified key from the attributes table. If you pass two arguments it
will set the value of that key.

Back to index.syt now, it should become the following in order to
pass this information to the autohandler:

We're using a small trick here, @attr returns the value so
it'll be inserted into the <h1>...</h1> tag. Of course, you
have total freedom over that, for example you could move the H1
tag into the autohandler if that's the common case for most templates.

So now we separated the header/footer and other HTML boilerplate that we
need to include in all pages into a single file (the autohandler). If we
need to create a new page now, we can do that easily:

Accessing http://foobar.local/newpage should display it with
header and footer.

Subdirectories

If you have a nested directory structure and place autohandlers in
subdirectories, the autohandlers are chained. This site, for instance,
has a big section in the subdirectory /sytes/. All files inherit from the
main autohandler (the one in the root directory), but in /sytes/ we want
to display additional information such as the table of contents on the
right. The file structure is like this:

/autohandler.syt
/sytes/autohandler.syt
/sytes/...

In the toplevel autohandler we have a section like this to display the
table of contents that you can see on the right side:

There's no hard-coded text into it, it just looks for the SUBCONTENT
attribute and if present it's assumed to be a list of things to display on
the right side. The autohandler in /sytes/ in turn contains the
following:

Avoiding them

In some rare occasions you might want to have a file that's not served
through an autohandler. For a concrete example, the
URL /robots.txt (on every website) is queried by various search
engines. That's the place where you can declare which parts of your
website should be visited by robots, and which not. Robots are
technically free to ignore it, but that's another story; the story we're
talking about now is how to serve a proper robots.txt file while
all the requests are served by Sytes through autohandlers.

Since it's a request like any other, even if you do have a file
named robots.txt in your root directory it'll be interpreted as a
Sytes template and will obey the autohandler if one is present. To
prevent it from doing that, you can do the following:

The (@inherit nil) expression tells Sytes that this
particular template doesn't want to inherit from any autohandler; and
(http/set-content-type "text/plain") tells it to output a
plain text content-type rather than the default HTML one.