Problem

You would like to use a custom layout for your pages which differs from the default layout.

Solution

To define a custom layout you can easily create your own layout templates, according to default layout. We can then define an own layout function which will use those layout templates.

Step1:

Create new custom layout templates:

mkdir -p templates/layout/custom
cp templates/default/* templates/layout/custom/

Step2:

Define a new module for custom layouts:

mkdir -p MyProject

touch MyProject/CustomLayout.hs
module MyProject.CustomLayout where

import Import
import Text.Hamlet (hamletFile)

customLayout :: Widget -> Handler Html
customLayout widget = do
    master <- getYesod
    
    -- much more code here

    pc <- widgetToPageContent $ do
      -- add custom CSS or JS here
      $(widgetFile "layout/custom/default")
    withUrlRenderer $(hamletFile "templates/layout/custom/default-layout-wrapper.hamlet")

Step 3:

Use the new layout in your handler files:

module MyProject.PageHandler where

import Import
import MyProject.CustomLayout (customLayout)


getSomethingR :: Handler Html
getSomethingR = customLayout $ do
  setTitle "This is a page with a custom layout"
  $(widgetFile "your-resource-template-here")

Discussion

As you can see, we copied the default layout files to simplify the creation of our custom layout. Of course, we could write them from scratch. Please feel free to adapt the copied file to your needs. Furthermore you need to make sure the hamletFile function is imported inside the CustomLayout module.

Our customLayout behaves very similar to our default layout. But we are not limited to this. We can adapt the customLayout function to something more specific to this layout (you may would like to add more general data for the custom layout template).