<!DOCTYPE html>
<!-- ========================================== kroc camen of camen design ============================================= -->
<title>code · Under the Hood #5:  New Website-Ish</title>
<link rel="stylesheet" type="text/css" href="/design/design.css" />
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no" />
<link rel="alternate" type="application/rss+xml" href="/code/rss" title="Just code" />
<link rel="canonical" href="/code/uth5_new-website-ish" />
<!-- =================================================================================================================== -->
<header>
	<h1><a href="/" rel="index">
		Camen Design
	</a></h1>
	<nav><ul>
		<li><a href="/">all</a></li>
		<li><a href="/projects">projects</a></li>
		<li><a href="http://forum.camendesign.com">forum</a></li>
	</ul><ul>
		<li><a href="/quote/">quote</a></li>
		<li><a href="/writing/">writing</a></li>
		<li><a href="/blog/">blog</a></li>
		<li><a href="/photo/">photo</a></li>
		<li><a href="/code/" rel="tag">code</a></li>
		<li><a href="/art/">art</a></li>
		<li><a href="/link/">link</a></li>
		<li><a href="/poem/">poem</a></li>
		<li><a href="/audio/">audio</a></li>
	</ul><ul>
		<li><a href="/web-dev/">web-dev</a></li>
		<li><a href="/annoyances/">annoyances</a></li>
		<li><a href="/eve/">eve</a></li>
		<li><a href="/code-is-art/">code-is-art</a></li>
		<li><a href="/inspiration/">inspiration</a></li>
		<li><a href="/windows/">windows</a></li>
		<li><a href="/gift/">gift</a></li>
		<li><a href="/gaming/">gaming</a></li>
		<li><a href="/mac/">mac</a></li>
		<li><a href="/osnews/">osnews</a></li>
		<li><a href="/c64/">c64</a></li>
		<li><a href="/linux/">linux</a></li>
	</ul>
	<a rel="previous" href="/code/uth4_mime-type">
		older article →
	</a><a rel="next" href="/code/using-abbr">
		← newer article
	</a></nav>
</header>
<!-- =================================================================================================================== -->
<article><header>
	<!-- date published or updated -->
	<time pubdate datetime="2008-09-10T10:13:00+01:00">
		<sup>10:13<abbr>am</abbr> • 2008</sup>
		<abbr title="September">Sep</abbr> 10
	</time>
	<!-- categories -->
	<ul>
		<li><a href="/code/uth5_new-website-ish" rel="bookmark tag">code</a></li>
		<li><a href="/code-is-art/uth5_new-website-ish">code-is-art</a></li>
		<li><a href="/web-dev/uth5_new-website-ish">web-dev</a></li>
	</ul>
	<!-- licence -->
	<small>
		<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_GB">c</a>
		share + remix
	</small>
</header>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<section>
<h1>Under the Hood #5: <br />New Website-Ish</h1>
<p>
	<strong>Welcome</strong> to Camen Design v0.2-ish. I’ve replaced the publishing code in the site, leaving the
	HTML5 &amp; CSS intact. They will be replaced in the next update. I plan to target Firefox 3.1 (and hopefully Safari
	4 may be out by then too), allowing me to make use of
	<a href="http://vision-media.ca/resources/css/css-transformations-animations-and-transitions-examples" rel="external">CSS
	animation/transitions</a> and
	<a href="http://www.css3.info/preview/border-image/" rel="external"><code>border-image</code></a>.
</p><p>
	In fact, because my site has its PHP / HTML / CSS entirely separated, any one can be replaced without touching a
	line of the other.
</p><p>
	On the <a href="http://meiert.com/en/blog/20080819/re-clean-and-optimized-css/" rel="external">subject of
	future-proof CSS</a>, I noted:
</p>
<blockquote>
	<p>
		A CSS file is such that you can throw it away easily and start again. I could design my website any way I
		wanted without ever changing the HTML.
	</p><p>
		Clean and separated HTML/CSS means that parts can be replaced. That’s what future-proof is about – the
		ability to adapt to <em>changes</em>.<br />
		<br />
		Being bit-rot proof is an entirely different matter!
	</p>
	<cite>Kroc Camen, on <a href="http://meiert.com/en/blog/20080819/re-clean-and-optimized-css/" rel="external">Jens Meiert’s blog</a></cite>
</blockquote>
<p>
	That’s a different topic for another day though. This article is about the new back-end:
</p>


<h2>Clean URLs</h2>
<p>
	In the previous version of the site, a <a href="/.system/archive/0_1/index.php">PHP script</a> handled the
	database, spitting out the data as requested. v0.2 is now all static XHTML5 files, ensuring faster load speed and
	better caching. The <a href="#uth5-publishing">publishing script</a> generates pre-gzipped “.xhtml” files for
	each of the articles, as well as each of the index pages. The home page is “1.xhtml”, the second page
	“2.xhtml” and so on. Each content-type is a folder, containing another set of numbered files for the pages. e.g.
	“blog/1.xhtml” and so on.
</p><p>
	Mod_Rewrite is used to mask the “.xhtml” extension, so it isn’t required, giving nice looking URLs with no
	querystring as before. “<samp>/?blog&amp;amp;page=2</samp>” now becomes
	“<a href="/blog/2"><samp>/blog/2</samp></a>”.
</p><p>
	The ‘.htaccess’ file I wrote now handles everything dynamic, applying the ‘application/xhtml+xml’ mime-type
	to the HTML, but falling back to ‘text/html’ for
	<a href="http://www.microsoft.com/windows/internet-explorer/beta/default.aspx" rel="external">browsers that can’t
	deal with that</a>.<br />
	<br />
	I’ve opened up my ‘.htaccess’ file so you can <a href="/.htaccess">view it fully</a>, but a detailed
	break-down is covered below.
</p>


<h3>Serving Compressed <ins>X</ins>HTML5</h3>
<p>
	A big problem with the old code was that a single PHP page was not being cached very well, relying on me manually
	setting all the HTTP-Headers for the various pages requested. In this new version each page is a separate file, and
	so Apache and your browser can handle things fine.
</p>

<pre><code>FileETag MTime Size
AddDefaultCharset utf-8</code></pre>

<p>
	This declaration tells Apache to send <a href="http://en.wikipedia.org/wiki/HTTP_ETag" rel="external">ETags</a> in
	HTTP-Headers. The ETag is a unique hash of the file, so that the browser knows when the file has actually changed.
	Apache sends ETags automatically anyway, but uses the default “MTime INode Size”, which ties the ETag to the
	file’s storage cluster on the disk. If you were to upload the same file again, despite its contents not changing,
	Apache would send a different ETag in that case.
</p>

<pre><code># .xhtml files are gzipped html5 documents ready to serve
AddType application/xhtml+xml .xhtml
AddEncoding gzip .xhtml</code></pre>

<p>
	This creates a new file-type “.xhtml”, and serves it as ‘application/xhtml+xml’ by default. Though it is
	possible to serve HTML5 as ‘text/html’ in Firefox 3 &amp; Safari, the <code>&lt;legend&gt;</code> tag will not
	work correctly when used inside a
	<a href="http://www.whatwg.org/specs/web-apps/current-work/#the-figure" rel="external"><code>&lt;figure&gt;</code></a>
	element. This is due to the all-round broken-ness of the <code>&lt;legend&gt;</code> tag in all browsers (caused by
	pandering to IE’s even more broken implementation).
</p><p>
	The publishing script uses the
	<a href="http://php.net/manual/en/function.gzencode.php" rel="external"><code>gzencode</code></a> PHP function
	when saving the files to zip the contents for bandwidth-savings and fast delivery. The
	“<code>AddEncoding</code>” declaration applies this to Apache, adding the necessary
	“<code>Content-Encoding: gzip;</code>” HTTP-Header automatically.
</p>

<pre><code># load page 1 by deafult
DirectoryIndex 1.xhtml index.php index.html</code></pre>

<p>
	The home page is just page 1 of however many pages of the full archive of the site. Therefore “1.xhtml” is set
	as the default page to go to in a folder so that “/art/” returns “/art/1.xhtml”.
</p>

<pre><code># if the url contains the ".xhtml", show the source code
RewriteCond %{THE_REQUEST} \b([^\.]*[^/])\.xhtml\b
RewriteRule ^ - [T=text/plain,L]</code></pre>

<p>
	Viewing the <a href="/code/uth5_new-website-ish.html5">HTML source</a> of the pages on this site is an integral
	part of its design, so I wanted to make it very easy to do so. Just click the “html” link at the top of any
	page. The code above checks if the URL typed into the browser had the “.xhtml” included and if so, keeps the URL
	as is, but serves it as “text/plain” instead, preventing the browser from rendering the HTML.
</p>

<pre><code># leave the ".xhtml" off (clean urls)
RewriteRule ^([^\.]*[^/])$ /$1.xhtml [L]</code></pre>

<p>
	This finds any URL that has zero or one subfolder, and no dot in the filename. It then rewrites the URL to append
	“.xhtml” as the actual file to return. This is so “/blog/hello”, secretly returns the file
	“/blog/hello.xhtml”.
</p>

<pre><code># although I don’t support IE, I do have to fall back to text/html,
# otherwise it will try and download the page instead of rendering it
RewriteCond %{HTTP_ACCEPT} !application/xhtml\+xml
RewriteCond %{REQUEST_FILENAME} .*\.xhtml
RewriteRule ^ - [T=text/html,L]</code></pre>

<p>
	As described, this will check the browser capabilities to see if it does not accept ‘application/xhtml+xml’ and
	revert to ‘text/html’. If this is not done, IE will try and download the file instead of showing it. In 2008.
</p>


<h3>Compressed Stylesheets</h3>

<pre><code># "csz" compressed CSS filetype
AddType text/css .csz
AddEncoding gzip .csz</code></pre>

<p>
	As with the “.xhtml” definition, this creates a “.csz” filetype of mime-type “text/css”, and default
	gzip (compressed) encoding. The publishing script takes the normal ‘design.css’ file and spins off a compressed
	copy ‘design.csz’.
</p>

<pre><code># on my localhost, don’t use a cached CSS file
RewriteCond %{DOCUMENT_ROOT} "^/Users/kroc/Sites/Camen Design/upload"
RewriteRule ^design/$ /design/design.css [L]
RewriteRule ^design/$ /design/design.csz [L]</code></pre>

<p>
	When I’m editing the website on my computer, I’m refreshing constantly to see new CSS changes. This code checks
	if the webroot is that of my Mac’s localhost and passes the standard ‘.css’ file and stops processing. The
	next line passes the compressed CSS file in the case the document root match was not made (live server).
</p>


<h3>Compressed RSS</h3>
<p>
	The publishing script creates a compressed ‘rss.rsz’ file in each folder and on root.
</p>

<pre><code>AddType application/rss+xml .rsz
AddEncoding gzip .rsz

RewriteRule ^([a-z0-9-]+/)?rss$ /$1rss.rsz [L]</code></pre>

<p>
	This redirects URLs ending in “rss” to the compressed “rsz” file. e.g. “/blog/rss” becomes
	“/blog/rss.rsz”.
</p>


<h2 id="uth5-publishing">Static Publishing</h2>
<p>
	When I <a href="/blog/02-thoughts">mentioned my plans</a> for v0.2, I noted one particular fallacy:
</p>
<blockquote>
	<p>
		A simple text field is never going to replicate the editing power I have with
		<a href="http://macromates.com" rel="external">TextMate</a>. I’ve got no search and replace, no syntax
		highlighting, no keyboard shortcuts.
	</p><p>
		Trying to add these things is just <a href="/art/aol">re-implementing the wheel</a>, and thus breaks my
		very own design principle №3, <q><a href="/blog/hello#hello-iii">Let Everybody Else Do Their
		Job</a></q>
	</p>
	<cite>Kroc Camen: <a href="/blog/02-thoughts">“<cite>0.2 Thoughts</cite>”</a></cite>
</blockquote>
<p>
	Therefore, I removed the <a href="/blog/02-thoughts#02-admin">administration interface</a>, in favour of a Laguna
	2 (sadly offline now) style system.
</p><p>
	The publish script is available to <a href="/.system/archive/0_2/publish.php">view online</a>, but is not much use
	out of context. You can download a stub copy of this website with everything necessary to roll your own using the
	enclosure in your RSS reader, or the attachment at the bottom of this article.
</p>


<h3>Content on Disk</h3>
<p>
	The source content of this website is just a folder, with a sub folder for each of the “content-types” (blog |
	tweet | photo <abbr title="et cetera">&amp;c.</abbr>). In each folder is a file containing a <abbr>JSON</abbr>
	meta-data header and the raw HTML of the article. This layout directly maps to the new clean URLs too.
</p>
<img src="/code/uth5_new-website-ish/data-folder.png" alt="camen design v0.2’s data folder layout" width="257" height="274" />
<p>
	Creating a new blog post is nothing more than creating a new file. Because content is now disk files, instead of
	database entries, I can use my text-editor’s global search and replace and HTML editing capabilities and I can use
	my operating system to manage the files instead of having to implement more and more server-side administration
	pages to do the same thing.<br />
	<br />
	Now I can blog the same way I create the stuff I blog about.
</p>


<h3>Inside a Content Entry</h3>
<p>
	A content file looks like this inside: (this one is for <a href="/code/uth3_sqlite">this article</a>)
</p>

<pre>{	"date"		:	200807101232,
	"updated"	:	200807101232,
	"title"		:	"Under The Hood #3: ¬Using A Quick &amp;amp; Easy SQLite Database",
	"licence"	:	"cc-by",
	"tags"		:	["code-is-art", "web-dev"],
	"enclosure"	:	["sqlite.php"]
}

HTML content goes here...</pre>

<p>
	Pretty self-explanatory. When creating a new article, the “date” and “updated” fields are left out, and the
	publishing script then adds them in automatically. If I want to mark an article as updated, and thus push it to the
	top of the RSS regardless of its original publishing date, I just delete the “updated” line and the publishing
	script puts in a new timestamp.
</p>

<hr />

<p>
	<a href="/.system/archive/0_2/camendesign-0.2.zip" type="application/zip">This zip file</a> is updated every time
	I publish, so it always contains the most up to date code.
</p>
</section>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
</article>
<footer>
	<nav><a href="http://forum.camendesign.com">‹ Discuss this in the Forum ›</a></nav>
		
	<a href="mailto:kroc@camendesign.com">kroc@camendesign.com</a>
	<nav>view-source:
		<a href="/code/uth5_new-website-ish.rem">Rem</a> •
		<a href="/code/uth5_new-website-ish.html">HTML</a> •
		<a href="/design/">CSS</a> •
		<a href="/.system/">PHP</a> •
		<a href="/.htaccess">.htaccess</a>
	</nav>
	<form method="get" action="https://duckduckgo.com">
		<input type="hidden" name="sites" value="camendesign.com" />
		<input type="search" name="q" placeholder="search…" />
		<input type="submit" value="Go" />
	</form>
</footer>
<!-- =================================================================================================== code is art === -->