Question

I'm using Snap to create a fairly simple portfolio that, for the most part, just stores stuff in the database and shows it to the user. One of the features I'd like to have is the ability to show off retired designs for my portfolio. Each design would be little more than a single template and a handfull of assets (images, css, etc.). For organizational purposes, I would like to keep everything belonging to a single design together and separate from the templates/assets for my portfolio.

src/Site.hs

static/images/logo.png
static/css/responsive.css

archives/foo.com/2012-03/index.html
archives/foo.com/2012-03/images/logo.png
archives/foo.com/2012-03/css/styles.css
archives/foo.com/2012-03/favicion.ico

archives/bar.com/2011-08/index.html
archives/bar.com/2011-08/images/logo.png
archives/bar.com/2011-08/css/styles.css
archives/bar.com/2011-08/favicion.ico

I did try using serveDirectory on archives. Requesting example.com/bar.com/2012/03/ requests archives/bar.com/2012/03/index.html as one would expect and that's fine for some instances. I would like to be able to use some compiled splices or Charade so that the page doesn't look so empty when the original content can't be replicated (usually because it came from a database that's long forgotten).

Maybe making a separate snaplet for this purpose makes more sense? If so, how would I go about doing this? For reference, my site's snaplet is fairly basic and looks something like this:

app :: SnapletInit App App
app = makeSnaplet "connex" "A snaplet for the connex site." Nothing $ do
    h <- nestSnaplet "heist" heist $ heistInit' "templates" defaultHeistState
    s <- nestSnaplet "session" sess $ initCookieSessionManager "config/site_key.txt" "session" (Just 86400)
    d <- nestSnaplet "db" db pgsInit

    addRoutes 
        [ ("/", indexH siteH)
        -- more routes here
        , ("", serveDirectory "static")
        ]
    return $ App h s d
    where
        defaultHeistState = mempty {
            hcInterpretedSplices = defaultInterpretedSplices,
            hcLoadTimeSplices = defaultLoadTimeSplices
        }

(P.S. I have a similar but unrelated project that allows users to customize the appearance of their own "site". Currently, customization is limited to images and CSS. If the solution for the above problem could be used to allow customizing the layout template for each user, that would be great. If not, no worries.)

Was it helpful?

Solution

You'll probably have to do some manual wiring to get this to work the way you want, but there are some helpers that you can use. First there is the addTemplatesAt function that lets you include external templates in your HeistState. You can use that in combination with your own serveDirectory routes to serve the static resources. Once you get this working for one case, I'm sure you'll be able to find a way to combine the two in an abstraction that lets you pretty easily add multiple versions of your site's previous look.

OTHER TIPS

Here's the detailed solution I ended up with for my primary use case:

app :: SnapletInit App App
app = makeSnaplet "app" "An snaplet example application." Nothing $ do
    h <- nestSnaplet "heist" heist $ heistInit' "templates" defaultHeistState
    s <- nestSnaplet "sess" sess $ initCookieSessionManager "site_key.txt" "sess" (Just 3600)
    d <- nestSnaplet "db" db pgsInit

    addRoutes routes
    addTemplatesAt h "archives" "archives" -- added this
    return $ App h s d
    where
        defaultHeistState = mempty
            { hcInterpretedSplices = defaultInterpretedSplices
            , hcLoadTimeSplices = defaultLoadTimeSplices
            }

The handler to serve my templates looks like this (very similar to what heistServe looks like):

archiveServe :: AppHandler ()
archiveServe = do
    url <- withRequest (return . rqPathInfo)
    let
        splices = return ()
        template = "archives/" <> url <> "index"
    renderWithSplices template splices 

And my routes:

designH = route
    [ ("/", ifTop designIndexH)
    , ("/archives/", archiveServe)
    , ("/archives/", serveDirectory "archives")
    ]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top