Since we managed to successfully create a route, next step is to create an actual page to show it to the user.
While you can use virtually any Haskell template engine with Yesod, the built-in one uses Hamlet, Cassius, Lucius and Julius as its input. They are used to generate HTML, CSS and JavaScript files from templates. These four languages are known as Shakespearean templates – Hamlet for generating HTML, Cassius and Lucius for CSS (we’ll focus on Cassius, as the only difference is syntax of a block) and Julius for JavaScript – before you get too excited, Julius is not a transpiler – you have to write actual JavaScript, it’ll just do some variable interpolation. If you’re looking for an actual Haskell-to-JavaScript transpiler, you may want to take a look at GHCJS or Haste.

Remember our handler for projects, located in Handler/Projects.hs? We’re going to add some actual content now. First let’s add loading the page to handler. Here’s the new code for it:

getProjectsR :: Handler Html
getProjectsR = defaultLayout $ do
	setTitle "Projects"
	$(widgetFile "projects")

it’s important that the new part ($(widgetFile "projects")) is the last invocation in series, because it uses results of the earlier ones. Here’s an important fact: this code will not compile yet. That’s actually good news, because it means that Yesod got us covered against a situation where we forget to add the content (or the template name is not valid). To feed the compilation process it is sufficient to add an empty file located at templates/projects.hamlet. But what fun is an empty file? Let’s fill it with some static content, for example this one:

<div>
  <h1 .customTitle> Available projects:
    <ul #projectList>
      <li> Project 1
      <li> Project 2
      <li> Super project

Hamlet’s syntax is fairly straightforward: basically it’s like HTML, but uses nesting instead of closing tags. Also, you should only use a single tag per line (using multiple is possible, but they are not interpreted – i.e., you get what you write. Just don’t do it) and start the line with tag. While this seems reasonable, it leads to problems with whitespaces – suddenly trailing whitespaces in line start being important. Hamlet’s workaround for this is to provide escape characters: lines ending with # have their trailing whitespaces preserved, and lines starting with \ have their starting whitespaces preserved. # is a pretty important character in Hamlet – it’s also used for variable interpolation (we’ll cover it in the next post of the series) and assigning IDs to DOM elements (see ul element in the example above). There are also several other useful features like support for Maybe or conditionals, but we don’t need them now, so let’s not bother ourselves with them. Instead, let’s add a little style to our list of projects.

To include a custom stylesheet for our projects route, it’s sufficient to create templates/projects.cassius file and Yesod will understand that we want to use it. Let’s fill it with some simple content for now:

#projectList
    text-align: center;
    margin-bottom: 30px

.customTitle
    color: #FF0000

div
    color: #00FF00

now it looks really bad. But obviously it worked and stylesheet was included – go to localhost:3000/projects to check it out (remember to run stack exec -- yesod devel before). What’s also worth noting, this stylesheet was included only on projects route (don’t believe me – check it out yourself at localhost:3000).

I can imagine some of you wheezing: “sure, that’s all nice and fine, but what’s the actual benefit from using a new language? We could just use plain CSS for this, and industry already has Sass and Less to make life easier”. Well, you’re right – I didn’t show anything you can’t easily do with CSS yet. Bad news is that I won’t do it today – variable interpolation comes next, and that’s quite a nice feature – although I believe it’s much more useful for HTML templates than CSS ones.

Let’s sum up for today – we’ve managed to create a part of page that is injected into default-layout, but can contain own CSS and JavaScript (and HTML code of course). We also found out that .hamlet file is the only required part of the page, and the server will not compile without it – CSS and JS files will be included only if available (but if they are available, they will be included automatically). We also created a really ugly piece of layout, which we’ll probably need to fix later on – but that’s not a big deal, since we used it only to prove that stylesheets will be added automatically. Up to now the new template languages weren’t really useful – they simply had a bit different syntax. In the next episode we’ll explore their actual power – variable interpolation.

Stay tuned!