Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
124 lines (69 sloc) 2.78 KB


A tiny web dev DSL


{-# LANGUAGE OverloadedStrings #-}

import Network.Miku
import Hack2.Handler.SnapServer

main = run . miku $ get "/" (text "miku power")


cabal update
cabal install miku
cabal install hack2-handler-snap-server

-- copy and paste the above example to myapp.hs

runghc myapp.hs

check: http://localhost:3000

Quick reference



{-# LANGUAGE OverloadedStrings #-}

-- use - instead of $ for clarity
import Air.Light ((-))
import Prelude hiding ((-))

import Network.Miku
import Hack2.Handler.SnapServer

main = run . miku - do

  get "/" - do
    -- something for a get request

  post "/" - do
    -- for a post request

  put "/" - do
    -- put ..

  delete "/" - do
    -- ..


get "/say/:user/:message" - do
  text . show =<< captures

-- /say/miku/hello will output
-- [("user","miku"),("message","hello")]


-- public serve, only allows `./src`
public (Just ".") ["/src"]

Mime types

-- treat .hs extension as text/plain
mime "hs" "text/plain"


-- before takes a function of type (Env -> IO Env)
before - \e -> do
  putStrLn "before called"
  return e

-- after takes that of type (Response -> IO Response)
after return

Hack2 integration

Use hack2 middleware

import Hack2.Contrib.Middleware.SimpleAccessLogger

middleware - simple_access_logger Nothing

Convert miku into a hack2 application

-- in Network.Miku.Engine

miku :: MikuMonad -> Application

Miku application template

This template project shows how to incorporate sandboxing, auto-reloading and other cool stuff.


  • It's recommended to use your own html combinator / template engine. Try DIY with, e.g. moe.
  • Example view using custom html combinator (moe in this case)
  • When inspecting the request, use ask defined in ReaderT monad to get the Hack2.Environment, then use helper method defined in Hack2.Contrib.Request to query it.
  • Response is in StateT, html and text are simply helper methods that update the state, i.e. setting the response body, content-type, etc.
  • You do need to understand monad transformers to reach the full power of miku.