Ode's themes really are simple. This post tells you everything you need to know to use them effectively (Part 1 of 2).
Note that this is not a post about theme design and development. For example, I will not say much about theme components (page, page_no_posts, date, content_type). That's a topic for another post.
Let's make a deal. Follow along with this post and the next one from beginning to end, without skipping ahead or jumping around. Make sure you understand each point before moving on. If, after reading this over a couple of times, you are having trouble with using any themes, contact me directly (really) and I'll help you figure out what's going on. (You can find my email address somewhere in this site's sidebar.)
I recommend that you read this post with the text_page theme, which is little more flexible and better suited to reading longer content.
OK, ready?
What is a theme?
A theme is a folder containing at least the following four required files:
The folder and its contents constitute a single theme.
For example, the text_page theme, which is included as part of Ode's release package (as of version 1.2.0) looks like:
text_page/
content_type.text_page
date.text_page
page_no_posts.text_page
page.text_page
text_page.css
This is a particularly straightforward theme. It consists only of the 4 required files and a stylesheet. There isn't even an images directory or a single image file. But, while it is uncomplicated it isn't special. It is essentially the same as every other theme.
Notice that all of the required files must end with an extension that matches the name of the enclosing folder (i.e. the theme name). This requirement does not extend to other files. You are free to name your CSS files, images, javascript files, and anything else you want to include as part of your theme, whatever you like.
What if I wanted to rename this theme, to say... I don't know... 'fred'.
I would change the name of the enclosing folder and the extensions on the required theme files, like so:
text_page/ -> fred/
content_type.text_page -> content_type.fred
date.text_page -> date.fred
page_no_posts.text_page -> page_no_posts.fred
page.text_page -> page.fred
text_page.css
That's all there is to renaming a theme. I wouldn't need to make any other changes. The theme will now respond to the name 'fred' (Keep reading.)
I've just described an individual theme. We can have as many themes as we want.
All themes belong in a 'themes' folder, and we can have one of these 'themes' folders at every level of the content hierarchy.
'themes' folders must exist under Ode's document root alongside your content.
So let's say that the following list describes the content directory of some Ode site.
/
computing/
operating_systems/
macos/
macosx/
windows/
windows7/
linux/
unbuntu/
freebsd/
We can have as many as 10 'themes' directories (one at every level of the content hierarchy).
That would look like:
/
themes/
computing/
themes/
operating_systems/
themes/
macos/
themes/
macosx/
themes/
windows/
themes/
windows7/
themes/
linux
themes/
unbuntu/
themes/
freebsd
themes/
We can't have any more than this because the operating system won't allow it. Filesystem directory entries must be uniquely named (i.e. we cannot have more than one identically named entry in the same directory).
So far so good?
So we have 10 themes directories represented but so far not a single theme. The 'themes' directories are not themselves themes. They are just the containing folders for themes.
Each 'themes' directory can contain any number of themes, like 'text_page' introduced above.
For example, if we added the 'text_page' theme to the computing category's themes folder, that would look like:
computing/
themes/
text_page/
...
At this point, you should feel pretty comfortable with
If we can have any number of themes, how does Ode determine which one to use for a given request?
We must tell Ode the name of the theme we want it to use for each request. We can do this in two ways:
To request a specific theme, append the name of the theme to the end of the post name in the requested URL, as if the theme name were the file extension of the post.
Continuing with the example above, let's say that we have a post file titled 'some_post.txt' in the 'windows7' category on our Ode site. The path to that post is:
/computing/operating_systems/windows/windows7/some_post.txt
and the corresponding URL to the post file would be something like:
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/windows7/some_post
If we want that post to be displayed using the 'text_page' theme, we just treat the theme name as a file extension and add it to the URL like so:
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/windows7/some_post.text_page
I can display the same post, using other installed themes, just by changing the theme name:
The same post using a theme called 'logic':
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/windows7/some_post.logic
The same post using a theme called 'html'. (Note: There is nothing special about a theme titled 'html'. It is just a theme name like any other. There are no reserved or special theme names.)
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/windows7/some_post.html
The same post using a theme called 'rss'. (Note: It would make sense that a theme titled 'rss' is a standards compliant RSS feed of some sort, but there is nothing special about a theme titled 'rss'. It is just a theme name like any other. If it is an RSS feed that's because of the content of the theme, not the theme name. There are no reserved or special theme names.)
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/windows7/some_post.rss
OK?
But what about category pages? How do we request a specific theme for category pages like:
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/windows7/
We use the special filename 'index'.
Under Ode, a request for the filename index is synonymous with a request for the parent category.
The following requests mean exactly the same thing to ode:
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/index
As do the following pair of requests, which both target the site root.
http://sample.net/cgi-bin/ode.cgi/
http://sample.net/cgi-bin/ode.cgi/index
Because we can associate a filename (index) with a directory request, we can explicitly ask for a theme just as we did for post type requests.
For example:
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/index.text_page
The same post using a theme called 'logic':
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/index.logic
The same post using a theme called 'html'
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/index.html
The same post using a theme called 'rss'.
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/index.rss
We can switch between themes like this on a per request basis. We can also specify theme names in links in order to control not just the the target of a link, but the look of the page as well.
There is a default theme, which is set in the configuration file. The default set in the config file distributed as part of the release package is 'html' - through release 1.2.0. (See the config file for more info.)
Whenever you do not specifically name a theme as part of the request URI, the default is used.
Of course this works when the request targets a post or a category.
For example:
The following is a request for the post titled 'some_post' using the default theme.
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/some_post
The following is a request targeting posts in the windows category using the default theme.
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/
You can also include the special filename 'index' to make a category request using the default theme (though I can't think of a reason to do that):
http://sample.net/cgi-bin/ode.cgi/computing/operating_systems/windows/index
Note: The fact that we can make requests without specifying a theme is important in terms of web best practices.
The web is a great big distributed application. Each site, no matter how large or small, is part of that application. The fact that hypertext links allow us to easily and almost effortlessly create links between sites, and without negotiating the connection with the owner of the sites we link to, key to the power and utility of the web. But, with this impromptu linking comes a lot of responsibility.
We must all take care to avoid harming the web by breaking its links (inbound links to pages under our control). This happens whenever someone (including search engines) links to our site and then we subsequently move, rename, or delete the targeted page. Ideally, once a page is published it will always be available at the same location forever. Unfortunately, this is not always possible. Still, we have an obligation to do the best we can and avoid making our links unnecessarily brittle. File extensions are a frequent source of unnecessary problems.
If we include file extensions (theme names under Ode) as part of our URLs and then later change the file extension for some reason, associated links may break, even though the content itself is still available.
Consider a static site where all of the HTML files end with the extension 'html' and links to the content on the site include these file extensions.
For example
<a href="http://sample.net/dir1/some_post.html" title="...">some_post</a>
Now, lets say that for some reason we change all of the file extensions used. Maybe we start using a new development tool that exports files with the common three character extension 'htm' instead.
That change is enough to break the link above, and all other links to pages on the site. A visitor would need to somehow know to change the file extension to access the same content. (We could set up some sort of redirection to help visitors find their way, but that's just another complication that we then need to maintain going forward indefinitely.)
With Ode these 'file extensions' are actually theme names. There is no risk of links to content breaking if a referenced theme becomes unavailable. What will happen instead is that Ode will display the requested content using the baked-in error theme. Though that's substantially better than throwing off a 'file not found' error and displaying no content at all, as would be the case with a static site, it's far from ideal. We can avoid the issue entirely by not referencing theme names in links and using the default whenever possible, especially for permalinks.
At this point we've discussed how to tell Ode what theme we want to use for a given request. Next, we need to cover how Ode figures out which one of the possibly many available themes to use.
First of all, the script already has the name of the theme it's looking for (discussed above). As you might guess, Ode simply ignores any theme that doesn't match the name provided.
If we have instructed Ode to use a theme named 'text_page', it will ignore any theme with a different name.
Given the following partial directory structure...
/computing
themes/
text_page/
rss/
html/
some_other_theme_name/
...
... and a request something like
'http://sample.net/cgi-ebin/ode.cgi/computing/index.text_page'
It should be easy to see that Ode will use the text_page theme and ignore all of the others.
But what if the directory structure looks like:
/
themes/
text_page/
computing/
themes/
text_page/
operating_systems/
themes/
text_page/
macos/
themes/
text_page/
macosx/
themes/
text_page/
windows/
themes/
text_page/
windows7/
themes/
text_page/
linux/
themes/
text_page/
unbuntu/
themes/
text_page/
freebsd/
themes/
text_page/
and the request is:
'http://sample.net/cgi-ebin/ode.cgi/computing/operating_systems/windows/windows7/index.text_page'
It's not a matter of selecting the text_page theme and ignoring themes with different names. This time the script has to choose which text_page theme to use from among the 10 that are available.
Ode always chooses a theme from along the path of the request.
The path of this request is:
/computing/operating_systems/windows/windows7/
So that reduces the number of themes in play to 5:
1. /themes/text_page/
2. /computing/themes/text_page/
3. /computing/operating_systems/themes/text_page/
4. /computing/operating_systems/windows/themes/text_page/
5. /computing/operating_systems/windows/windows7/themes/text_page/
How does it pick from among these?
It always starts looking for a theme as close to the request as possible and then works back toward the site root.
So for the request
...computing/operating_systems/windows/windows7/index.text_page
Ode would use:
/computing/operating_systems/windows/windows7/themes/text_page/
This behavior allows us to customize themes for each category. Keep in mind that even though these themes all share the same name, they care completely independent.
The text_page theme in the windows7 category might look nothing like the text_page theme in the computing category.
If the script can't find the theme it's looking for in the category closest to the request, it moves up one level in the category structure and looks for the named theme there. This process continues until the script finds the theme it's looking for, or it runs out of places to look.
If the script makes it all the way back to the site root and still doesn't find the theme it needs, it gives up and returns a baked-in error theme, which includes a message stating that the requested theme could not be found.
Do you have to create a version of your themes for every category on your site? No, you don't - absolutely not!
You could stick with a single themes directory at the root of your site and keep just one instance of all your themes there. Themes at the site root apply to every category on the site, because every category is a descendant of the root (i.e. any request that can be made includes the site root). With no other 'themes' directories to get in the way, themes at the site root will be used in answer to every request.
If you want to have a single consistent theme across your entire site, then you only need to have one theme in the themes directory at the root.
IMPORTANT
Ode supports a dated themes feature. Dated themes allow a site maintainer to save previous versions of a theme as changes are made over thim. These dated variants of the same theme can be used to recreate the look of the site at any point in time. I'll discuss dated themes more in the next post.
What's important to understand now is that this post describes the behavior of the script when the dated themes feature is disabled.
The config file includes a setting labeled 'use_site_look_date'. This variable acts as a mode toggle (on/off switch).
When use_site_look_date is true the dated themes mechanism is enabled, and when the same setting is false, it's disabled.
Dated themes are identical to non-dated themes with the single exception of the name of the directory enclosing the theme.
Compare:
You will recognize the first as the text_page theme used in the examples throughout this post. The second is the same text_page theme but we have appended a dash followed by a date suffix.
The suffix indicates the date when the theme was installed (copied to some themes directory).
Every dated theme follows this same form:
theme name
a dash
a date suffix with the format YYYYMMDD, with underscores allowed between elements of the date suffix to improve readability.
theme_name-YYYYMMDD
Here is the crucial point:
When config::use_site_look_date is true non-dated themes are ignored. When config::use_site_look_date is false dated themes are ignored.
You can think of use_site_look_date as a switch flipping between dated and non-dated themes. You need to understand that when the setting is true all of the non-dated themes (i.e. any theme not ending in a date suffix) are completely ignored. As far as the script is concerned they don't exist. The same thing is true of dated themes whenever use_site_look_date is false.
I'll have much more to say about use_site_look_date in the next post. Just make sure you understand the last point.
If you have questions, please ask. (Either send me an email or start a discussion on the forum).
If you understand what you've read so far, then continue on to part 2).