@@ -0,0 +1,168 @@
2+title: How to write pages
3+what: elaborates a little on writing pages and templates
6+## The structure of a Page
8+The most important thing to realize is that a page is reduced to a `Context`,
9+and therefore is just a key-value mapping. Another example:
18+This will produce the following mapping:
21+- `$author`: Mia Wallace
22+- `$body`: Hello there! This is a simple about page.
24+`$body` is the traditional name for the main body part of a page. If the page
25+has a `.markdown` extension for example, this would also be rendered by pandoc.
26+But pages are more flexible. The following is also a valid page:
31+This will produce one key-value pair:
33+- `$body`: Hello there! This is a simple about page.
35+But Hakyll can do more than this. You can add extra sections, apart from the
36+body, and even leave out the body.
42+ A small introduction goes here. I can write *markdown*
43+ here, by the way. Well, assuming this page has a
44+ `.markdown` extension.
47+ I can write some more things here.
50+ The body comes last, and is optional.
52+This will produce the following:
54+- `$author`: Vincent Vega
55+- `$prelude`: A small introduction goes here. I can write *markdown* here, by the
56+ way. Well, assuming this page has a `.markdown` extension.
57+- `$main`: I can write some more things here.
58+- `$body`: The body comes last, and is optional.
60+The example from this tutorial (we will see later) uses this to build a
61+three-column system for the website, separating content from layout.
65+Now you know that pages, and `Context`s in general, are basically nothing more
66+than key-values mappings, it is time to abuse this fact. There is another
67+way to create a `Context`, called `combine`.
69+The type signature of the `combine` function does a pretty good job at
73+combine :: HakyllAction () Context
74+ -> HakyllAction () Context
75+ -> HakyllAction () Context
78+This means we can take two `Context`s values and combine them. This is
79+basically a `Map.union`: The result will contain all keys from both `Context`s,
80+with there corresponding values. If a key is present in both `Context`s, the
81+value from the first argument will be chosen. This is, for example, almost
82+always the case with the `$url` field (since almost all `Context`s have an url
85+Combining two `Context`s, but overriding the `$url` is quite common, so there is
86+another function that helps us here:
89+combineWithUrl :: FilePath
90+ -> HakyllAction () Context
91+ -> HakyllAction () Context
92+ -> HakyllAction () Context
97+Now that we have the tools, we'll get on to the example. This time, we'll
98+be making a more advanced brochure site. Here [is a zip file] containing the
99+source code for the tutorial.
101+[is a zip file]: examples/morepages.zip
103+Every page consists of three sections, originally named `section1`, `section2`
104+and `section3`. So our pages look more or less like this:
111+ Nullam imperdiet sodales orci vitae molestie. Nunc...
115+ Vivamus eget mauris sit amet nulla laoreet lobortis.
120+ In urna ante, pulvinar et imperdiet nec, fermentum ac...
122+The cool thing is we do not have to specify how these will be layed out. In our
123+template, we decide to use a simple three column system:
126+<div class="column"> $section1 </div>
127+<div class="column"> $section2 </div>
128+<div class="column"> $section3 </div>
131+The columns are then floated using css. So far so good, but what if we wanted
132+an additional text block on every page? An easy solution would be to add this
133+to the template, but then our layout-content separation idea will be broken
134+again. So we simply add to the template:
137+<div class="footer"> $footer </div>
140+And now we will use `combine` to put the footer on every page - so we need to
141+add the footer page to every `Context`. We write a small auxiliary function
142+that combines a given `Context` with the footer:
145+withFooter = flip combine $ createPage "footer.markdown"
148+Note that we use `flip` here - we want `footer.markdown` to be our second
149+argument. That is because Hakyll will take the `$url` from the first `Context`,
150+so all pages would be rendered to `footer.html` - obviously not what we want.
151+Now, were we previously wrote:
154+render "about.markdown"
155+where render = renderChain ["templates/default.html"]
159+We simply have to add our footer:
162+render "about.markdown"
163+where render = renderChain ["templates/default.html"]
168+And now every page will include the footer.