Skip to content
A tiny web dev DSL
Find file
Failed to load latest commit information.
src move tests to test directory
test move tests to test directory
.gitignore update ignore
Nemesis clean up example and Nemesis
Setup.lhs init init init
miku.cabal bump version clean up example and Nemesis


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


  • 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.


Something went wrong with that request. Please try again.