diff --git a/Panda/Config/Global.hs b/Panda/Config/Global.hs
--- a/Panda/Config/Global.hs
+++ b/Panda/Config/Global.hs
@@ -1,23 +1,23 @@
 module Panda.Config.Global where
 
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, readFile)
+import Prelude hiding ((.), (/), (^), id, readFile)
 import Panda.Type.Reader
 
-db_id      = "db"
-flat_id    = "."
-blog_id    = "blog"
-config_id  = "config"
-tag_id     = "tag"
-
-db_uri     = db_id
-flat_uri   = db_uri / flat_id
+db_id       = "db"
+flat_id     = "."
+blog_id     = "blog"
+config_id   = "config"
+tag_id      = "tag"
+comment_id  = "comment"
 
-config_uri = flat_uri / config_id / "site.txt"
-blog_uri   = flat_uri / blog_id
-tag_uri    = flat_uri / tag_id
+db_uri      = db_id
+flat_uri    = db_uri / flat_id
 
-markup     = markdown
+config_uri  = flat_uri / config_id / "site.txt"
+blog_uri    = flat_uri / blog_id
+tag_uri     = flat_uri / tag_id
+comment_uri = flat_uri / comment_id
 
 
 -- unsafe, must restart server after changing config file, sorry about that ...
diff --git a/Panda/Controller/Application.hs b/Panda/Controller/Application.hs
--- a/Panda/Controller/Application.hs
+++ b/Panda/Controller/Application.hs
@@ -2,28 +2,27 @@
 -- models are made as simple and small as possible
 -- views are pure functions.
 
--- I believe this leads to more robust system, and provides much more
--- flexibility in both design and implementation
-
+-- a note on encoding:
+-- IO are in utf-8 filter, internally use unicode bytes
 
 {-# OPTIONS -fno-monomorphism-restriction #-}
 
-
 module Panda.Controller.Application where
 
 import qualified Data.Map as Map
 
 -- env
 import Panda.Helper.Env hiding (tag)
-import Prelude hiding ((.), (/), id)
+import Prelude hiding ((.), (/), (^), id)
 import Panda.Type.State hiding (pager)
-import qualified Panda.Config.Global as Config
+import qualified Panda.Config.Global as G
 import qualified Panda.Type.Pager as Pager
 
 -- model
 import qualified Panda.Model.Post as Post
 import qualified Panda.Model.Static as Static
 import qualified Panda.Model.Tag as Tag
+import qualified Panda.Model.Comment as Comment
 
 -- view
 import qualified Panda.View.Theme.BluePrint.Post as PostV
@@ -44,38 +43,45 @@
   , ("^/tag/.*/rss.xml$"    ,tag_feed          )
   , ("^/tag/."              ,tag               )
   , ("^/search"             ,search            )
+  , ("^/comment/create"     ,comment_create    )
   ]
 
-per_page = Config.per_page
+per_page = G.per_page
 
 index = do
   blogs <- Post.list.liftIO
   p <- pager per_page $ blogs.length
   tags <- Tag.list.liftIO
   let nav = if p.Pager.current == 1 then home_nav else no_navigation
-  let state = State Config.blog_id p tags nav
+  let state = State G.blog_id p tags nav
   
-  blogs.map (Tag.fill_tag tags) .PostV.list state .output_html
+  blogs.map (Tag.fill_tag tags).mapM ( Comment.fill_comment_size >>> liftIO ) 
+    ^ PostV.list state >>= output_html
 
+
 index_feed = do
   blogs <- Post.list.liftIO
   blogs.RSSV.rss "" "" .output
 
 
 blog = do
-  id <- uri <.> ("blog/" ++)
+  id <- uri ^ ("blog/" ++)
   blog <- Post.get id .liftIO
+  comments <- Comment.list_for id .liftIO
   tags <- Tag.list.liftIO
   
   let state = State id Pager.empty tags no_navigation
-  blog.Tag.fill_tag tags .PostV.view state .output_html
+  blog.Tag.fill_tag tags .Comment.fill_comment_size .liftIO
+    ^ PostV.view state comments >>= output_html
 
+
 static = do
   id <- uri
   static_page <- Static.get id .liftIO
   tags <- Tag.list.liftIO
   
-  let nav = if title.belongs_to Config.navigation then title else no_navigation where title = static_page.Static.title
+  let nav_id = static_page.Static.uid.id_to_resource
+  let nav   = if nav_id.belongs_to G.navigation then nav_id else no_navigation
   let state = State id Pager.empty tags nav
   StaticV.view state static_page .output_html
 
@@ -87,21 +93,23 @@
   case Tag.tag_map' tags .Map.lookup tag_name of
     Nothing -> "page not found" .output
     Just blog_set -> do
-      blogs <- blog_set.to_list.rsort.mapM (Post.get) .liftIO <.> map (Tag.fill_tag tags)
+      blogs <- blog_set.to_list.rsort.mapM (Post.get) .liftIO ^ map (Tag.fill_tag tags)
       p <- pager per_page $ blogs.length
       let state = State id p tags no_navigation
       blogs.TagV.view state.output_html
 
+
 tag_feed = do
-  id <- uri <.> (split "/" >>> init >>> join "/")
+  id <- uri ^ (split "/" >>> init >>> join "/")
   tags <- Tag.list.liftIO
   let tag_name = Tag.get_name id
   case Tag.tag_map' tags .Map.lookup tag_name of
     Nothing -> "page not found" .output
     Just blog_set -> do
-      blogs <- blog_set.to_list.rsort.mapM (Post.get) .liftIO <.> map (Tag.fill_tag tags)
+      blogs <- blog_set.to_list.rsort.mapM (Post.get) .liftIO ^ map (Tag.fill_tag tags)
       blogs.RSSV.rss "tag" tag_name.output
 
+
 search = do
   s <- param_with_default "s" ""
   blogs <- Post.search s .liftIO
@@ -112,3 +120,34 @@
   let state = State query p tags no_navigation
 
   blogs.map (Tag.fill_tag tags) .SearchV.view state s.output_html
+
+
+
+comment_create = do
+  post_id <- input_with_default "post_id" "blog/nothing"
+  exists <- (G.flat_uri / post_id) .doesFileExist .liftIO
+  let valid_path = equalFilePath "blog" (takeDirectory post_id)
+  checked <- check_create
+  
+  if [checked, valid_path, exists].and
+    then
+      inputs ^ to_h >>= (Comment.create >>> liftIO)
+    else
+      return ()
+  redirect $ ("/" ++ post_id.id_to_resource.to_utf8).urlEncode
+
+
+-- create helper, should be refactored to some common aspect
+check_create =
+  [ validate "author"  ( length >>> (> 0))
+  , validate "url"     (const True)
+  , validate "comment" ( length >>> (> 0))
+  , validate "human-hack" (is "10")
+  ] .sequence ^ and
+
+
+validate s f = do
+  maybe_s <- get_input s
+  case maybe_s of
+    Nothing -> return False
+    Just v -> return $ f v
diff --git a/Panda/Helper/Env.hs b/Panda/Helper/Env.hs
--- a/Panda/Helper/Env.hs
+++ b/Panda/Helper/Env.hs
@@ -12,9 +12,11 @@
   , module System.Time.Parse
   , module Panda.Helper.Helper
   , module Data.Maybe
-  , module System.FilePath.Posix
+  , module System.FilePath
   , module System.IO.UTF8
   , module Text.XHtml.Strict
+  , module System.Time
+  , module System.Directory
 ) where
   
 import MPS hiding (base, col, sub)
@@ -27,6 +29,8 @@
 import System.Time.Parse
 import Panda.Helper.Helper
 import Data.Maybe
-import System.FilePath.Posix hiding ((<.>))
-import System.IO.UTF8 (readFile)
+import System.FilePath hiding ((<.>))
+import System.IO.UTF8 (readFile, writeFile)
 import Text.XHtml.Strict hiding (select)
+import System.Time
+import System.Directory
diff --git a/Panda/Helper/Escape.hs b/Panda/Helper/Escape.hs
deleted file mode 100644
--- a/Panda/Helper/Escape.hs
+++ /dev/null
@@ -1,18 +0,0 @@
-module Panda.Helper.Escape where
-
-import Text.ParserCombinators.Parsec
-import Char
-import Data.Either.Utils
-
-unicode_char :: Parser Char
-unicode_char = do
-  char '&'
-  char '#'
-  word <- many1 digit
-  char ';'
-  return $ chr (read word)
-
-unescape_parser :: Parser String
-unescape_parser = many (unicode_char <|> anyChar)
-
-unescape s = forceEither $ parse unescape_parser "" s
diff --git a/Panda/Helper/Helper.hs b/Panda/Helper/Helper.hs
--- a/Panda/Helper/Helper.hs
+++ b/Panda/Helper/Helper.hs
@@ -16,47 +16,60 @@
 
 import Panda.Type.Pager as Pager hiding (empty)
 import MPS
-import Prelude hiding ((.), (/), id)
-import Panda.Helper.Escape
+import Prelude hiding ((.), (/), (^), id)
+import Panda.Helper.MPSCandidate
 import Char
 import Data.List
 import Panda.Type.Reader
 import System.FilePath.Posix hiding ((<.>))
 
 (/) = (</>)
+infixl 5 /
 
+(^) = (<.>)
+infixl 9 ^
+
 -- model
 take_extension = takeExtension >>> split "\\." >>> last
 
 -- controller
-uri = requestURI <.> (uriPath >>> urlDecode >>> tail)
-  
+uri = requestURI ^ (uriPath >>> urlDecode >>> tail >>> remove_trailing_slash >>> from_utf8 )
+  where remove_trailing_slash s = if s.last.is '/' then s.init else s
+
 params = do
-  query_string <- requestURI <.> uriQuery
+  query_string <- requestURI <.> uriQuery 
   case query_string of
-    '?':s -> s.formDecode .return
+    '?':s -> s.formDecode .map_snd unescape_unicode_xml.return
     otherwise -> return []
 
-param_with_default s d = params <.> (lookup s >>> fromMaybe d >>> unescape >>> strip)
+inputs = getInputs ^ map_snd (strip >>> unescape_unicode_xml)
 
-input_with_default s d = getInput s <.> (fromMaybe d >>> unescape >>> strip)
+param_with_default s d = params <.> (lookup s >>> fromMaybe d )
+input_with_default s d = inputs <.> (lookup s >>> fromMaybe d )
 
+get_param s = params ^ lookup s
+get_input s = inputs ^ lookup s
+
+just_param s = get_param s ^ fromJust
+just_input s = get_input s ^ fromJust
+
 pager length total = liftM5 ( Pager length ) current has_next has_previous next previous where
-  current      = param_with_default "page" "1" <.> read
-  has_next     = current <.> ( (* length) >>> (< total.fromIntegral) )
-  has_previous = current <.> (> 1)
-  next         = current <.> (+ 1)
-  previous     = current <.> (+ (-1) )
+  current      = param_with_default "page" "1" ^ read
+  has_next     = current ^ ( (* length) >>> (< total.fromIntegral) )
+  has_previous = current ^ (> 1)
+  next         = current ^ (+ 1)
+  previous     = current ^ (+ (-1) )
 
 
 for_current_page p xs = xs.drop ((p.Pager.current - 1) * p.Pager.length) .take (p.Pager.length)
 
 -- id: /type/resoruce
-id_to_type id = id.from_utf8.split "/" .first
-id_to_resource id = id.from_utf8.split "/" .tail.join "/"
-no_navigation = ""
-home_nav      = "Home"
+id_to_type id     = id.split "/" .first
+id_to_resource id = id.split "/" .tail.join "/"
+no_navigation     = ""
+home_nav          = "Home"
 
+
 -- view
 id               = identifier
 
@@ -78,12 +91,4 @@
   , s.show
   , "<![endif]-->"
   ] .join' .primHtml
-
-rss_uri x = URI {
-  uriScheme    = "http://",
-  uriAuthority = Nothing,
-  uriPath      = x / "rss.xml",
-  uriQuery     = "",
-  uriFragment  = ""
-  }
 
diff --git a/Panda/Helper/MPSCandidate.hs b/Panda/Helper/MPSCandidate.hs
new file mode 100644
--- /dev/null
+++ b/Panda/Helper/MPSCandidate.hs
@@ -0,0 +1,1 @@
+module Panda.Helper.MPSCandidate where
diff --git a/Panda/Model/Comment.hs b/Panda/Model/Comment.hs
new file mode 100644
--- /dev/null
+++ b/Panda/Model/Comment.hs
@@ -0,0 +1,63 @@
+module Panda.Model.Comment where
+
+-- env
+import Panda.Helper.Env hiding (match, title, body)
+import Prelude hiding ((.), (/), (^), id, readFile, writeFile)
+import qualified Panda.Config.Global as G
+import qualified Data.Map as M
+import Panda.Type.Reader
+import qualified Panda.Model.Post as Post
+import System.Time
+import System.Directory
+
+data Comment = Comment
+  { uid    :: String     -- blog/08-09-04 blog title
+  , author :: String
+  , url    :: String
+  , body   :: String
+  }
+  deriving (Show, Eq)
+
+list_for post_id = do
+  has_comments <- doesDirectoryExist d
+  if has_comments
+    then ls d ^ map from_utf8 ^ rsort ^ map (G.comment_id / r /) >>= mapM get
+    else return []
+  where 
+    d = (G.comment_uri / r)
+    r = post_id.id_to_resource.to_utf8
+
+
+get id = do
+  xs <- (G.flat_uri / id) .readFile ^ lines
+  let author = xs.first
+  let url = xs.drop 2.first
+  let body = xs.drop 4.unlines
+  return $ Comment id author url body
+
+
+create h = do
+  let author  = at "author"
+  let url     = at "url"
+  let body    = at "comment"
+  let post_id = at "post_id" .to_utf8
+
+  timestamp <- ( getClockTime >>= toCalendarTime ) ^ format_date
+  let comment_path = G.flat_uri / G.comment_id / (post_id.split "/".last) 
+  createDirectoryIfMissing True comment_path
+  
+  let uid = comment_path / timestamp
+  let content = [author, url, body].join "\n\n"
+  writeFile uid content
+  
+  where at s = h.M.lookup s .fromJust
+
+format_date x = formatCalendarTime defaultTimeLocale "%y-%m-%d %T" x
+parse_date = parseCalendarTime defaultTimeLocale "%Y-%m-%d %T"
+date x     = x.uid.split "/".last.("20"++).parse_date.fromMaybe (parse_date "2000-1-1 00:00:00".fromJust)
+
+fill_comment_size x = do
+  size <- x.Post.uid.list_for ^ length 
+  return $ x { Post.comment_size = size }
+
+markup x  = render_to_html Markdown (x.body)
diff --git a/Panda/Model/Post.hs b/Panda/Model/Post.hs
--- a/Panda/Model/Post.hs
+++ b/Panda/Model/Post.hs
@@ -6,8 +6,8 @@
 
 -- env
 import Panda.Helper.Env hiding (match, title, body)
-import Prelude hiding ((.), (/), id, readFile)
-import qualified Panda.Config.Global as Config
+import Prelude hiding ((.), (/), (^), id, readFile)
+import qualified Panda.Config.Global as G
 import Panda.Type.Reader
 
 data Post = Post 
@@ -15,16 +15,17 @@
   , title :: String
   , body :: String
   , tags :: [String]
+  , comment_size :: Int
   , reader :: Reader
   }
   deriving (Show, Eq)
 
-list = ls Config.blog_uri <.> rsort <.> map (Config.blog_id /) >>= mapM get
+list = ls G.blog_uri ^ map from_utf8 ^ rsort ^ map (G.blog_id /) >>= mapM get
 
-get id        = liftM3 (Post id (get_title id) ) (get_body id) (return []) (return $ get_reader id)
-get_title id  = id.from_utf8.words.tail.unwords.dropExtension
-get_body id   = (Config.flat_uri / id) .readFile
-get_reader id = id.take_extension.guess_reader.fromMaybe Config.default_reader
+get id        = liftM4 (Post id (get_title id) ) (get_body id) (return []) (return 0) (return $ get_reader id)
+get_title id  = id.words.tail.unwords.dropExtension
+get_body id   = (G.flat_uri / id.to_utf8) .readFile
+get_reader id = id.take_extension.guess_reader.fromMaybe G.default_reader
 
 
 parse_date = parseCalendarTime defaultTimeLocale "%Y-%m-%d"
@@ -33,6 +34,6 @@
 
 match s x = [title, body] .map (send_to x >>> lower >>> isInfixOf (s.lower)) .or
 search "" = return []
-search s  = list <.> filter (match s)
+search s  = list ^ filter (match s)
 
-markup x = render_to_html (x.reader) (x.body)
+markup x  = render_to_html (x.reader) (x.body)
diff --git a/Panda/Model/Static.hs b/Panda/Model/Static.hs
--- a/Panda/Model/Static.hs
+++ b/Panda/Model/Static.hs
@@ -2,24 +2,23 @@
 
 -- env
 import Panda.Helper.Env hiding (match, body)
-import Prelude hiding ((.), (/), id, readFile)
-import qualified Panda.Config.Global as Config
+import Prelude hiding ((.), (/), (^), id, readFile)
+import qualified Panda.Config.Global as G
 import Panda.Type.Reader
 
 data Static = Static 
   { uid :: String
-  , title :: String
   , body :: String
-  , tags :: [String]
   , reader :: Reader
   }
   deriving (Show, Eq)
   
   
-get id        = liftM3 (Static id (get_title id) ) (get_body id) (return []) (return $ get_reader id)
+get id        = liftM2 (Static id) (get_body id) (return $ get_reader id)
 get_title     = id_to_resource >>> dropExtension
-get_body id   = (Config.flat_uri / id) .readFile
-get_reader id = id.take_extension.guess_reader.fromMaybe Config.default_reader
+get_body id   = (G.flat_uri / id.to_utf8) .readFile
+get_reader id = id.take_extension.guess_reader.fromMaybe G.default_reader
 
+title = uid >>> get_title
 
 markup x = render_to_html (x.reader) (x.body)
diff --git a/Panda/Model/Tag.hs b/Panda/Model/Tag.hs
--- a/Panda/Model/Tag.hs
+++ b/Panda/Model/Tag.hs
@@ -3,12 +3,12 @@
 import qualified Panda.Model.Post as Post
 
 -- env
-import Panda.Helper.Env hiding (readFile, name)
-import Prelude hiding ((.), (/), id)
+import Panda.Helper.Env hiding (name)
+import Prelude hiding ((.), (/), (^), id, readFile)
 import qualified Data.Set as Set
 import qualified Data.Map as Map
 import qualified Data.List as List
-import qualified Panda.Config.Global as Config
+import qualified Panda.Config.Global as G
 
 
 data Tag = Tag 
@@ -19,18 +19,18 @@
   deriving (Show, Eq)
 
 sorted xs    = xs.List.sortBy(compare_by (resources >>> Set.size)).reverse
-name_to_id x = Config.tag_id / (x.to_utf8)
+name_to_id x = G.tag_id / x
 
-list = ls Config.tag_uri <.> map (Config.tag_id /) >>= mapM get
+list             = ls G.tag_uri ^ map from_utf8 ^ map (G.tag_id /) >>= mapM get
 
-get id           = get_resources id <.> Tag id (get_name id)
-get_name id      = id.from_utf8.split "/" .tail.join'
-get_resources id = (Config.flat_uri / id) .readFile -- preserve ansi file path
-  <.> filter_comment <.> lines <.> map (Config.blog_id / ) <.> to_set
+get id           = get_resources id ^ Tag id (get_name id)
+get_name id      = id.split "/" .tail.join'
+get_resources id = (G.flat_uri / id.to_utf8) .readFile -- preserve ansi file path
+  ^ filter_comment ^ lines ^ map (G.blog_id / ) ^ to_set
 
 
 tag_map' xs       = xs . map (name &&& resources) . to_h
-tag_map           = list <.> tag_map'
+tag_map           = list ^ tag_map'
 
 for_resource xs x = xs.select (resources >>> Set.member x) .map name
 fill_tag xs x     = x { Post.tags = for_resource xs (x.Post.uid) }
diff --git a/Panda/Type/Reader.hs b/Panda/Type/Reader.hs
--- a/Panda/Type/Reader.hs
+++ b/Panda/Type/Reader.hs
@@ -1,7 +1,7 @@
 module Panda.Type.Reader where
 
 import MPS  
-import Prelude hiding ((.), (/), id)
+import Prelude hiding ((.), (/), (^), id)
 import qualified Data.Map as Map
 import Text.Pandoc
 import Control.Arrow ((>>>))
diff --git a/Panda/View/RSS.hs b/Panda/View/RSS.hs
--- a/Panda/View/RSS.hs
+++ b/Panda/View/RSS.hs
@@ -2,8 +2,8 @@
 
 -- env
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id)
-import qualified Panda.Config.Global as Config
+import Prelude hiding ((.), (/), (^), id)
+import qualified Panda.Config.Global as G
 import Panda.Type.Pager as Pager
 import Text.RSS
 
@@ -11,7 +11,7 @@
 import Panda.Model.Post as Post
 
 
-entry_uri x = "/" ++ Post.uid x.urlEncode.split "/".tail.join "/"
+entry_uri x = "/" ++ Post.uid x.split "/".tail.join "/"
 
 -- RSS
 channel_rss_template = [ Language "en-us" ]
@@ -19,22 +19,17 @@
 item_rss_template x = 
   [ Title $ x.Post.title
   , Description $ x.Post.markup.show
-  , Author $ Config.author_email
+  , Author $ G.author_email
   , Link $ x.item_uri
   , PubDate $ x.Post.date 
   ]
 
-item_uri x = URI 
-  { uriScheme = "http://"
-  , uriAuthority = Nothing
-  , uriPath = Config.host_name ++ x.entry_uri
-  , uriQuery = ""
-  , uriFragment = ""
-  }
+item_uri x = nullURI { uriScheme = "http://", uriPath = G.host_name ++ x.entry_uri }
+rss_uri x  = nullURI { uriScheme = "http://", uriPath = x / "rss.xml" }
 
 rss categary s xs = RSS title  (rss_uri link) title channel_rss_template (xs.take 20 .map item_rss_template)
   .rssToXML.showXML
   where 
-    link =  Config.host_name / categary / s
-    title = Config.blog_title ++ " / " ++ s
+    link =  G.host_name / categary / s
+    title = G.blog_title ++ " / " ++ s
   
diff --git a/Panda/View/Theme/BluePrint/Comment.hs b/Panda/View/Theme/BluePrint/Comment.hs
new file mode 100644
--- /dev/null
+++ b/Panda/View/Theme/BluePrint/Comment.hs
@@ -0,0 +1,49 @@
+module Panda.View.Theme.BluePrint.Comment where
+  
+import Panda.Helper.Env hiding (body, date)
+import Prelude hiding ((.), (/), (^), id, span)
+import qualified Panda.Type.State as State
+
+import Panda.Model.Comment
+import qualified Panda.Model.Post as Post
+
+-- view
+import Panda.View.Theme.BluePrint.Helper
+import Panda.View.Theme.BluePrint.Template.Template
+
+
+list [] = []
+list xs = 
+  [ h2 ! [id "comments"] << "Responses"
+  , olist ! [theclass "commentlist" ] << xs.zip (cycle ["comments-alt", ""]).map (splash entry)
+  ]
+
+entry alt x = li ! [theclass alt] << 
+  [ cite << a
+  , toHtml " says:"
+  , br
+  , p ! [theclass "small"] << comment_date x
+  , x.markup
+  ]
+  where a = if x.url.null then x.author.toHtml else toHtml $ hotlink (x.url) << x.author
+
+comment_date x = toHtml $ x.date.formatCalendarTime defaultTimeLocale "%b %e, %Y at %I:%M %p"
+
+-- create = spaceHtml
+create post = 
+  [ h2 ! [id "respond"] << "Leave a Response"
+  , gui "/comment/create" ! [id "commentform"] <<
+    [ field "author" 22 1 "Name (required)"
+    , field "url" 22 2 "Website"
+    , field "human-hack" 22 3 "What is 5 + 5 ?"
+    , p << hidden "post_id" (post.Post.uid)
+    , p << textarea ! [name "comment", id "comment", cols "10", rows "20", strAttr "tabindex" "4"] << ""
+    , p << submit "submit" "Submit Comment" ! [strAttr "tabindex" "5"]
+    ]
+  ]
+  
+field x s t m = p <<
+  [ label ! [thefor x] << small << m
+  , br 
+  , textfield x ! [size (s.show), strAttr "tabindex" (t.show)]
+  ]
diff --git a/Panda/View/Theme/BluePrint/Helper.hs b/Panda/View/Theme/BluePrint/Helper.hs
--- a/Panda/View/Theme/BluePrint/Helper.hs
+++ b/Panda/View/Theme/BluePrint/Helper.hs
@@ -1,7 +1,7 @@
 module Panda.View.Theme.BluePrint.Helper where
 
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
+import Prelude hiding ((.), (/), (^), id, span)
   
 import Panda.Type.Pager as Pager
 
diff --git a/Panda/View/Theme/BluePrint/Post.hs b/Panda/View/Theme/BluePrint/Post.hs
--- a/Panda/View/Theme/BluePrint/Post.hs
+++ b/Panda/View/Theme/BluePrint/Post.hs
@@ -2,17 +2,17 @@
 
 -- env
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
+import Prelude hiding ((.), (/), (^), id, span)
 
-import System.Time
-import System.Locale
 import qualified Panda.Type.State as State
 
 -- model
 import Panda.Model.Post as Post
+import qualified Panda.Model.Comment as Comment
 
 -- view
 import Panda.View.Theme.BluePrint.Helper
+import qualified Panda.View.Theme.BluePrint.Comment as CommentV
 import Panda.View.Theme.BluePrint.Template.Template
 
 -- HTML
@@ -20,22 +20,24 @@
 entry x = div_class "post" << [entry_title, entry_mark, entry_body] where
   entry_title = x.title_link
   entry_body  = div_class "entry" << x.Post.markup
-  entry_mark  = p ! [theclass "small"] << 
-    [ x.blog_date, x.blog_tags ]
+  entry_mark  = p ! [theclass "small"] << [ blog_date, blog_tags, blog_comments ].map (send_to x)
 
 title_link x              = h2 << hotlink (entry_uri x) << x.Post.title
-entry_uri x               = "/" ++ Post.uid x.urlEncode.split "/".tail.join "/"
+entry_uri x               = "/" ++ Post.uid x .id_to_resource
 blog_date x               = toHtml $ x.Post.date.formatCalendarTime defaultTimeLocale "%b %e, %Y"
 
 blog_tags x | x.tags.null = toHtml ""
-blog_tags x | otherwise   = toHtml " | " +++ toHtml ["Published in ".toHtml, x.tags.map tag_link .intersperse (", ".toHtml) .toHtml]
+blog_tags x = " | " +++ "Published in " +++ x.tags.map tag_link .intersperse (", ".toHtml)
 
+blog_comments x | x.comment_size.is 0 = toHtml ""
+blog_comments x = " | " +++ hotlink (entry_uri x / "#comments") << (x.comment_size.show ++ " Comments")
+
 tag_link s                = toHtml $ hotlink ("/tag/" ++ s ) << s
 
 
 -- entry view
-view state x = x.entry.page state
-  
+view state xs x = (x.entry +++ CommentV.list xs +++ CommentV.create x).page state
+
 -- list view
 list state = for_current_page p >>> map entry >>> (+++ nav p "/") >>> page state
   where p = state.State.pager
diff --git a/Panda/View/Theme/BluePrint/Search.hs b/Panda/View/Theme/BluePrint/Search.hs
--- a/Panda/View/Theme/BluePrint/Search.hs
+++ b/Panda/View/Theme/BluePrint/Search.hs
@@ -1,7 +1,7 @@
 module Panda.View.Theme.BluePrint.Search where
   
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
+import Prelude hiding ((.), (/), (^), id, span)
 import qualified Panda.Type.State as State
 
 -- view
@@ -9,6 +9,6 @@
 import Panda.View.Theme.BluePrint.Helper
 import Panda.View.Theme.BluePrint.Template.Template
 
-view state s = for_current_page p >>> map entry >>> (+++ nav p ("/search" ++ "?s=" ++ (s.urlEncode) ++ "&")) >>> page state
+view state s = for_current_page p >>> map entry >>> (+++ nav p ("/search" ++ "?s=" ++ s ++ "&")) >>> page state
   where p = state.State.pager
 
diff --git a/Panda/View/Theme/BluePrint/Tag.hs b/Panda/View/Theme/BluePrint/Tag.hs
--- a/Panda/View/Theme/BluePrint/Tag.hs
+++ b/Panda/View/Theme/BluePrint/Tag.hs
@@ -1,7 +1,7 @@
 module Panda.View.Theme.BluePrint.Tag where
   
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
+import Prelude hiding ((.), (/), (^), id, span)
 import qualified Panda.Type.State as State
 
 -- view
diff --git a/Panda/View/Theme/BluePrint/Template/Body.hs b/Panda/View/Theme/BluePrint/Template/Body.hs
--- a/Panda/View/Theme/BluePrint/Template/Body.hs
+++ b/Panda/View/Theme/BluePrint/Template/Body.hs
@@ -2,8 +2,8 @@
 
 -- env
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
-import qualified Panda.Config.Global as Config
+import Prelude hiding ((.), (/), (^), id, span)
+import qualified Panda.Config.Global as G
 import qualified Panda.Type.State as State
 
 -- view
@@ -11,14 +11,12 @@
 import Panda.View.Theme.BluePrint.Template.Footer
 
 
-html_body state x = body << container << 
+html_body state x = body << div_class "container" << 
   [ body_header state
   , div_id "page" << [ body_content x, html_sidebar state ]
   , html_footer
   ]
 
-container   = div_class "container"
-
 body_header state = toHtml
   [ div_class_id "column span-12 first" "header" << 
     [ search_form
@@ -28,18 +26,16 @@
   ]
 
 -- search_form = spaceHtml
-search_form = 
-  div_id "search" << form ! [action "/search", method "get"] << thediv << 
-    textfield "s" -- ! [strAttr "onFocus" "clearInput('s', 'Search')", strAttr "onBlur" "clearInput('s', 'Search')"]
+search_form = div_id "search" << form ! [action "/search", method "get"] << thediv << textfield "s"
   
 site_name = toHtml $
   [ toHtml $ hotlink "/" ! [theclass "logo"] << ""
-  , h1 << Config.blog_title
-  , div_class "description" << Config.blog_subtitle
+  , h1 << G.blog_title
+  , div_class "description" << G.blog_subtitle
   ]
 
 navigation state = div_class "content" <<
-  ulist << Config.navigation.map (nav_item (state.State.nav_location))
+  ulist << G.navigation.map (nav_item (state.State.nav_location))
 
 nav_item nav s = li ! [theclass (home_tag ++ "page_item" ++ current)] << link s where
   home_tag = if s == home_nav then "first " else ""
diff --git a/Panda/View/Theme/BluePrint/Template/Footer.hs b/Panda/View/Theme/BluePrint/Template/Footer.hs
--- a/Panda/View/Theme/BluePrint/Template/Footer.hs
+++ b/Panda/View/Theme/BluePrint/Template/Footer.hs
@@ -1,19 +1,19 @@
 module Panda.View.Theme.BluePrint.Template.Footer where
   
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
-import qualified Panda.Config.Global as Config
+import Prelude hiding ((.), (/), (^), id, span)
+import qualified Panda.Config.Global as G
 
 
-import qualified Panda.Config.Global as Config
+import qualified Panda.Config.Global as G
 
 html_footer = div_id "footer" <<
   [ toHtml $ copyright
   , toHtml $ "2008 "
-  , toHtml $ Config.blog_title
+  , toHtml $ G.blog_title
   , toHtml $ br
   , toHtml $ "Powered by "
-  , toHtml $ hotlink Config.panda_url << "Panda"
+  , toHtml $ hotlink G.panda_url << "Panda"
   , toHtml $ " using "
   , toHtml $ hotlink "http://www.haskell.org/" << "Haskell"
   ]
diff --git a/Panda/View/Theme/BluePrint/Template/Header.hs b/Panda/View/Theme/BluePrint/Template/Header.hs
--- a/Panda/View/Theme/BluePrint/Template/Header.hs
+++ b/Panda/View/Theme/BluePrint/Template/Header.hs
@@ -1,14 +1,25 @@
 module Panda.View.Theme.BluePrint.Template.Header where
 
 import Panda.Helper.Env
-import Prelude hiding ((.), (/), id, span)
-import qualified Panda.Config.Global as Config
+import Prelude hiding ((.), (/), (^), id, span)
+import qualified Panda.Config.Global as G
 
 
-html_head  = header << [meta_tag, title_tag, screen_css, wp_css, custom_css, rss_tag]
+html_head  = header << ([meta_tag, title_tag, rss_tag] ++ css_list ++ js_list )
 
-title_tag  = thetitle << Config.blog_title
+title_tag  = thetitle << G.blog_title
+rss_tag    = rss_link "rss.xml"
+
+-- css
+css_list   = [screen_css, wp_css, custom_css]
 screen_css = css_link "/theme/blueprint/wp/css/screen.css"
 wp_css     = css_link "/theme/blueprint/wp/css/blueprint-wp.css"
 custom_css = css_link "/theme/blueprint/wp/css/custom.css"
-rss_tag    = rss_link "rss.xml"
+
+
+-- js
+js_list          = [jquery_js, jquery_param, jquery_highlight, custom_js]
+jquery_js        = js_link "/js/lib/jquery/jquery-1.2.6.min.js"
+jquery_param     = js_link "/js/lib/jquery/jquery.getUrlParam.js"
+jquery_highlight = js_link "/js/lib/jquery/jquery.highlight-2.js"
+custom_js        = js_link "/js/custom.js"
diff --git a/Panda/View/Theme/BluePrint/Template/Sidebar.hs b/Panda/View/Theme/BluePrint/Template/Sidebar.hs
--- a/Panda/View/Theme/BluePrint/Template/Sidebar.hs
+++ b/Panda/View/Theme/BluePrint/Template/Sidebar.hs
@@ -1,7 +1,7 @@
 module Panda.View.Theme.BluePrint.Template.Sidebar where
 
 import Panda.Helper.Env hiding (rss_link)
-import Prelude hiding ((.), (/), id, span)
+import Prelude hiding ((.), (/), (^), id, span)
 import qualified Panda.Type.State as State
 
 import qualified Data.Set as Set
@@ -36,4 +36,4 @@
   [ h2 << "Tags"
   , unordList $ tags.Tag.sorted.map tag_link]
   
-tag_link x = hotlink ("/" ++ x.uid.urlEncode) << x.Tag.name +++ (" (" ++ x.Tag.resources.Set.size.show ++ ")")
+tag_link x = ( hotlink ("/" ++ x.uid) << x.Tag.name ) +++ ( " (" ++ x.Tag.resources.Set.size.show ++ ")" )
diff --git a/changelog.markdown b/changelog.markdown
--- a/changelog.markdown
+++ b/changelog.markdown
@@ -1,3 +1,15 @@
+2008.9.19
+----------
+
+### Features
+
+* Comment system
+* Change version schema
+
+### Improvements
+
+* uniform unicode handling ( byte8 internal, utf-8 IO )
+
 0.0.0.5.1
 ----------
 
diff --git a/panda.cabal b/panda.cabal
--- a/panda.cabal
+++ b/panda.cabal
@@ -1,5 +1,5 @@
 Name:                 panda
-Version:              0.0.0.5.1
+Version:              2008.9.19
 Build-type:           Simple
 Synopsis:             Simple Static Blog Engine
 Description:          Simple Static Blog Engine
@@ -14,16 +14,17 @@
 data-files:			      readme.markdown, changelog.markdown
 
 library
-  build-depends: base, cgi, network, haskell98, old-locale, old-time, directory, filepath, containers >= 0.1.0.0, mps >= 0.0.0.1, parsedate >= 3000.0.0, rss >= 3000.0.1, xhtml >= 3000.2.0.0, kibro >= 0.0, utf8-string >= 0.3.1, pandoc >= 0.46, MissingH, parsec
+  build-depends: base, cgi, network, haskell98, old-locale, old-time, directory, filepath, containers >= 0.1.0.0, mps >= 2008.9.19, parsedate >= 3000.0.0, rss >= 3000.0.1, xhtml >= 3000.2.0.0, kibro >= 0.0, utf8-string >= 0.3.1, pandoc >= 0.46, MissingH, parsec >= 2.1.0
   exposed-modules:  Panda
                     Panda.Config.Global
                     Panda.Controller.Application
                     Panda.Helper.Env
-                    Panda.Helper.Escape
+                    Panda.Helper.MPSCandidate
                     Panda.Helper.Helper
                     Panda.Model.Post
                     Panda.Model.Static
                     Panda.Model.Tag
+                    Panda.Model.Comment
                     Panda.Type.Pager
                     Panda.Type.Reader
                     Panda.Type.State
@@ -33,6 +34,7 @@
                     Panda.View.Theme.BluePrint.Search
                     Panda.View.Theme.BluePrint.Static
                     Panda.View.Theme.BluePrint.Tag
+                    Panda.View.Theme.BluePrint.Comment
                     Panda.View.Theme.BluePrint.Template.Body
                     Panda.View.Theme.BluePrint.Template.Footer
                     Panda.View.Theme.BluePrint.Template.Header
diff --git a/readme.markdown b/readme.markdown
--- a/readme.markdown
+++ b/readme.markdown
@@ -20,8 +20,8 @@
 Why
 ----
 
-* Blog entries are stored locally
-* Write posts in Markdown, HTML, reStructuredText or even LaTeX format ( no Math equations yet )
+* Blogs are stored locally
+* Write in Markdown, HTML, reStructuredText or even LaTeX format ( Math equations won't render yet )
 * Remote server is a mirror of local repository
 * No server side API for publishing / editing, just use Darcs, Git or any SCM
 * No need to find external hosting of your videos, images or sound. Put them in public folder ( still managed by SCM if you wish )
@@ -36,14 +36,6 @@
 
 Note: the demo might run on an experimental branch, so differences from the cabal version could occur.
         
-Status
--------
-
-Panda is in its early stage. I got tired of importing / exporting blogs when switching blogging platforms, 
-I needed a way to not be bounded to any service API.
-
-The main benefit is that if I ever wanted to stop using Panda, all my blogs and resources are in manageable states.
-
 Install
 --------
 
@@ -93,9 +85,7 @@
 Future
 ------
 
-The template db is just a starting point for you to experiment on. However, I would encourage you to keep your own db in your own SCM, that way, you will never lose your data and never have to care about application logic again.
-
-There are many things could be done. Whatever there will be, the key idea is simplest data / folder structure, absolutely no parsing, no xml, no code is data like and stuff :)
+There are many things could be done. Whatever there will be, the key idea is simplest data / folder structure.
 
 Hacking
 --------
