Ramblings of General Geekery

Previewing a baked site in IIS/Apache

This is the first post of a series of things I learned while using PieCrust.

If you’re using PieCrust as a static website generator, you know you can use the built-in development server to preview your site as you’re modifying it. This is all pretty nice but there are plenty of good reasons to not go that way, the top ones being:

  1. The development server doesn’t run any custom scripts you may have.
  2. IIS, Apache and all the other well-known web-servers are faster and more robust.
  3. You can’t use special features like .htaccess or web.config settings.

If you went with the recommended directory structure for your site, you will have all your content in a _kitchen directory ready to be baked into your final website. But this _kitchen directory really looks a lot like a regular PieCrust website when PieCrust is used as a lightweight CMS. The only difference is that there’s no main index.php file, and that you may be using some file processors.

If you create an index.php file to bootstrap the _kitchen website, it would get deployed to your export directory when you bake your site, so you need to do one of the following:

  • Write some PHP wrapper to the chef baking utility to exclude that file from baking (you can pass a “skip_pattern” parameter to the baker class). I’ll try to make it easier to add exclude rules to chef in the near future, but at the moment you would need to write some code. Not ideal.
  • Rename the bootstrap file _index.php, since all files or directories with a leading underscore in their names are excluded. Now, however, you will need to edit your .htaccess or web.config to add _index.php as a default document, but that’s really just one line of text or a couple clicks. That’s the solution I use.

If you use file processors, you may have to work around them, which may not be possible. I myself only use the LESS CSS processor, and it’s easy to avoid it because LESS comes with a client-side Javascript processor. The trick is now to switch between the client and server side processors, which can be done with a few Twig macros:

{% macro stylesheet(baker, path, media) %}
{% if baker.is_baking %}
<link rel="stylesheet" href="{{ path }}.css" type="text/css" media="{{ media|default('all') }}" />
{% else %}
<link rel="stylesheet/less" href="{{ path }}.less" type="text/css" media="{{ media|default('all') }}" />
{% endif %}
{% endmacro %}

This macro emits a reference to a stylesheet that points to the standard CSS file if the website is currently being baked (which means the server-side processor will run to generate that CSS file), or points to the LESS file itself otherwise (which means the processor will run on the client).

{% macro less_js(baker, site_root) %}
{% if not baker.is_baking %}
<script src="{{ site_root }}js/less-1.0.41.min.js" type="text/javascript"></script>
{% endif %}
{% endmacro %}

This second macro adds the client-side processor to your page if the baker is not running.

Now you just need to call those macros from your template file(s):

{{ less.stylesheet(baker, site.root ~ 'styles/my-awesome-stylesheet', 'screen, projection') }}
{{ less.less_js(baker, site.root) }}

Update (PieCrust >= 0.0.3)

Recent versions of PieCrust have, at last, the ability to define which files should be excluded from baking. This means you can rename the bootstrap file back to index.php if you wish, and exclude it from the bake along with any .htaccess or web.config:

baker:
    skip_patterns:
        - /^_/
        - index.php
        - .htaccess
        - web.config

This is much better!


Working with Disqus

Since I’ve migrated this blog to PieCrust and all its comments to Disqus I’ve run into a few problems that took me some time to figure out (although I got help from the nice Disqus guys). Those problems come down to the following information which was not quite clear to me even after reading their documentation several times:

  • The disqus_identifier value gives a unique name to a thread.
  • The disqus_location value indicates the URL(s) at which a given thread can be found.
  • A thread can be used by several URLs, but no URL can be used by more than one thread.

The first 2 points are pretty straightforward, but that last one was the tricky one. Basically (at the time of this writing, obviously) if you have 2 threads with 2 correctly unique identifiers that were created both with the same URL, your page at that URL will show all kinds of weird behaviours, from never loading any comments (you get the “Disqus loading” icon animation) to loading one of the thread regardless of what disqus_identifier you specified on that page. You would think that identifier would, well, identify exactly what thread you wanted to display, but no, the URL from which it is loaded apparently also plays an important role.

This means, for example, that you can’t display more than one thread on a single page, although the Disqus guys told me this limitation will be removed in a few months.

Another little thing to look for is the subtle distinction between http://example.com/some/url and http://example.com/some/url/ (note the trailing slash character at the end of the second URL). Those URLs are effectively different, as far as Disqus is concerned. This is especially important for statically generated websites since the actual URL of a page or post is http://example.com/some/url/index.html, so there could be at least 3 correct ways to access the same page. Hopefully, as long as you don’t have some weird address collision, you won’t run into the problem mentioned above (which I ran into because I was messing around with the very handy Disqus Python bindings to batch rename and re-identify my threads).

Hopefully this will save somebody some head-scratching.