diff --git a/Yesod/Comments.hs b/Yesod/Comments.hs
--- a/Yesod/Comments.hs
+++ b/Yesod/Comments.hs
@@ -4,9 +4,9 @@
 -------------------------------------------------------------------------------
 -- |
 -- Module      :  Yesod.Comments
--- Copyright   :  (c) Patrick Brisbin 2010 
+-- Copyright   :  (c) Patrick Brisbin 2010
 -- License     :  as-is
--- Maintainer  :  pbrisbin@gmail.com 
+-- Maintainer  :  pbrisbin@gmail.com
 -- Stability   :  unstable
 -- Portability :  unportable
 --
@@ -23,6 +23,8 @@
 import Yesod
 import Yesod.Auth
 import Yesod.Comments.Core
+import Network.Gravatar
+import Data.Text (Text)
 
 -- | Comments that anyone can enter anonymously
 addComments :: (RenderMessage m FormMessage, YesodComments m)
@@ -33,20 +35,16 @@
     ((res, form), enctype) <- lift $ runFormPost commentForm
 
     handleForm res tid
-    addStyling
+
     [whamlet|
         <div .yesod_comments>
-            <h4>Add a comment:
-            <div .yesod_comment_input>
-                <form enctype="#{enctype}" method="post">^{form}
-                <p .helptext>Comments are parsed as pandoc-style markdown
-
-            $if not $ null comments
-                <h4>Showing #{toHtml $ helper $ length comments}:
-
-                $forall comment <- comments
-                    <div .yesod_comment>^{showComment comment}
+            ^{showComments comments showComment}
 
+            <div .input>
+                <form enctype="#{enctype}" method="post" .form-stacked>
+                    ^{form}
+                    <div .actions>
+                        <button .btn .primary type="submit">Add comment
     |]
 
 -- | Comments that require authentication
@@ -61,40 +59,48 @@
             Just uid -> do
                 uname <- displayUser uid
                 email <- displayEmail uid
-                return (True, toSinglePiece uid, uname, email)
+                return (True, toPathPiece uid, uname, email)
 
     comments               <- lift $ loadComments (Just tid)
-    ((res, form), enctype) <- lift $ runFormPost (commentFormAuth uid username email)
+    ((res, form), enctype) <- lift $ runFormPost (commentFormAuth uid email)
 
     handleForm res tid
-    addStyling
+
     [whamlet|
         <div .yesod_comments>
+            ^{showComments comments showCommentAuth}
+
             $if isAuthenticated
-                <h4>Add a comment:
-                <div .yesod_comment_input>
-                    <form enctype="#{enctype}" method="post">^{form}
-                    <p .helptext>Comments are parsed as pandoc-style markdown
-            $else
-                <h4>Please ^{login} to post a comment.
+                <div .avatar>
+                    <a target="_blank" title="change your profile picture at gravatar" href="http://gravatar.com/emails/">
+                        <img src="#{img email}">
 
-            $if not $ null comments
-                <h4>Showing #{toHtml $ helper $ length comments}:
+                <div .input>
+                    <form enctype="#{enctype}" method="post" .form-stacked>
+                        <div .clearfix .optional>
+                            <label for="username">Username
+                            <div .input>
+                                <p #username>#{username}
 
-                $forall comment <- comments
-                    <div .yesod_comment>^{showCommentAuth comment}
+                        ^{form}
+
+                        <div .actions>
+                            <button .btn .primary type="submit">Add comment
+
+            $else
+                <h4>Please ^{login} to post a comment.
     |]
 
-helper :: Int -> String
-helper 0 = "no comments"
-helper 1 = "1 comment"
-helper n = show n ++ " comments"
+    where
+        img :: Text -> String
+        img = gravatar def { gDefault = Just MM, gSize = Just $ Size 48 }
 
--- | Show the authroute as a link if set up
-login :: Yesod m => GWidget s m ()
-login = do
-    lift $ setUltDest' -- so we come back here after login
-    mroute <- lift $ fmap authRoute getYesod
-    case mroute of
-        Just r  -> [whamlet|<a href="@{r}">log in|]
-        Nothing -> [whamlet|log in|]
+        login :: Yesod m => GWidget s m ()
+        login = do
+            mroute <- lift $ do
+                setUltDestCurrent
+                fmap authRoute getYesod
+
+            case mroute of
+                Just r  -> [whamlet|<a href="@{r}">log in|]
+                Nothing -> [whamlet|log in|]
diff --git a/Yesod/Comments/Core.hs b/Yesod/Comments/Core.hs
--- a/Yesod/Comments/Core.hs
+++ b/Yesod/Comments/Core.hs
@@ -4,7 +4,7 @@
 -------------------------------------------------------------------------------
 -- |
 -- Module      :  Yesod.Comments.Core
--- Copyright   :  (c) Patrick Brisbin 2010 
+-- Copyright   :  (c) Patrick Brisbin 2010
 -- License     :  as-is
 --
 -- Maintainer  :  pbrisbin@gmail.com
@@ -18,13 +18,13 @@
     , CommentId
     , ThreadId
     , YesodComments (..)
+    , Form
     , commentFromForm
     , commentForm
     , commentFormAuth
-    , commentFormEdit
+    , commentLabel
     , handleForm
-    , handleFormEdit
-    , addStyling
+    , showComments
     , showComment
     , showCommentAuth
     , getNextCommentId
@@ -33,53 +33,44 @@
 
 import Yesod
 import Yesod.Auth
-import Yesod.Goodies.Gravatar
-import Yesod.Goodies.Markdown
-import Yesod.Goodies.Time
-import Control.Applicative ((<$>), (<*>))
+import Yesod.Markdown
+import Control.Applicative ((<$>), (<*>), pure)
+import Data.Text           (Text)
 import Data.Time           (UTCTime, getCurrentTime)
+import Data.Time.Format.Human
+import Network.Gravatar
 import Network.Wai         (remoteHost)
-
 import qualified Data.Text as T
 
-type ThreadId  = T.Text
+type ThreadId  = Text
 type CommentId = Int
 
 class Yesod m => YesodComments m where
-    -- | Find a specific comment
-    getComment :: ThreadId -> CommentId -> GHandler s m (Maybe Comment)
-
-    -- | Store a new comment
-    storeComment :: Comment -> GHandler s m ()
-
-    -- | Update a comment
+    getComment    :: ThreadId -> CommentId -> GHandler s m (Maybe Comment)
+    storeComment  :: Comment -> GHandler s m ()
     updateComment :: Comment -> Comment -> GHandler s m ()
-
-    -- | Remove a comment
     deleteComment :: Comment -> GHandler s m ()
-
-    -- | Load all comments, possibly filtered to a single thread.
-    loadComments :: Maybe ThreadId -> GHandler s m [Comment]
+    loadComments  :: Maybe ThreadId -> GHandler s m [Comment]
 
-    -- | If using Auth, provide the function to get from a user id to 
-    --   the string to use as the commenter's username. This should 
+    -- | If using Auth, provide the function to get from a user id to
+    --   the string to use as the commenter's username. This should
     --   return something friendly probably pulled from the user's
     --   profile on your site.
-    displayUser :: AuthId m -> GHandler s m T.Text
-    displayUser _ = return "" -- fixme: use toSinglePiece in new auth pkg
+    displayUser :: AuthId m -> GHandler s m Text
+    displayUser _ = return ""
 
-    -- | If using Auth, provide the function to get from a user id to 
+    -- | If using Auth, provide the function to get from a user id to
     --   the string to use as the commenter's email.
-    displayEmail :: AuthId m -> GHandler s m T.Text
+    displayEmail :: AuthId m -> GHandler s m Text
     displayEmail _ = return ""
 
 data Comment = Comment
     { threadId  :: ThreadId
     , commentId :: CommentId
     , timeStamp :: UTCTime
-    , ipAddress :: T.Text
-    , userName  :: T.Text
-    , userEmail :: T.Text
+    , ipAddress :: Text
+    , userName  :: Text
+    , userEmail :: Text
     , content   :: Markdown
     , isAuth    :: Bool
     }
@@ -88,18 +79,20 @@
     a == b = (threadId a == threadId b) && (commentId a == commentId b)
 
 data CommentForm = CommentForm
-    { formUser    :: T.Text
-    , formEmail   :: T.Text
+    { formUser    :: Text
+    , formEmail   :: Text
     , formComment :: Markdown
     , formIsAuth  :: Bool
     }
 
--- | Cleanse form input and create a 'Comment' to be stored
+type Form s m x = Html -> MForm s m (FormResult x, GWidget s m ())
+
 commentFromForm :: YesodComments m => ThreadId -> CommentForm -> GHandler s m Comment
 commentFromForm tid cf = do
     now <- liftIO getCurrentTime
-    ip  <- return . show . remoteHost =<< waiRequest
+    ip  <- fmap (show . remoteHost) waiRequest
     cid <- getNextCommentId tid
+
     return Comment 
         { threadId  = tid 
         , commentId = cid 
@@ -111,155 +104,42 @@
         , isAuth    = formIsAuth  cf
         }
 
--- | The comment form itself
-commentForm :: RenderMessage m FormMessage => Html -> Form s m (FormResult CommentForm, GWidget s m ())
-commentForm fragment = do
-    (user   , fiUser   ) <- mreq textField     "name:"    Nothing
-    (email  , fiEmail  ) <- mreq emailField    "email:"   Nothing
-    (comment, fiComment) <- mreq markdownField "comment:" Nothing
-    return (CommentForm <$> user <*> email <*> comment <*> FormSuccess False, [whamlet|
-        #{fragment}
-        <table>
-            ^{fieldRow fiUser}
-            ^{fieldRow fiEmail}
-            ^{fieldRow fiComment}
-            <tr>
-                <td>&nbsp;
-                <td colspan="2">
-                    <input type="submit" value="Add comment">
-        |])
+commentForm :: RenderMessage m FormMessage => Form s m CommentForm
+commentForm = renderBootstrap $ CommentForm
+    <$> areq textField  "Name"  Nothing
+    <*> areq emailField "Email" Nothing
+    <*> areq markdownField commentLabel Nothing
+    <*> pure False
 
--- | The comment form if using authentication (uid is hidden and display
---   name is shown)
 commentFormAuth :: RenderMessage m FormMessage
-                => T.Text -- ^ text version of uid
-                -> T.Text -- ^ friendly name
-                -> T.Text -- ^ email
-                -> Html   -- ^ nonce fragment
-                -> Form s m (FormResult CommentForm, GWidget s m ())
-commentFormAuth user username email fragment = do
-    let img = gravatarImg email defaultOptions { gDefault = Just MM }
+                => Text -- ^ Text version of uid
+                -> Text -- ^ user's email
+                -> Form s m CommentForm
+commentFormAuth user email = renderBootstrap $ CommentForm
+    <$> pure user <*> pure email
+    <*> areq markdownField commentLabel Nothing
+    <*> pure True
 
-    (fComment, fiComment) <- mreq markdownField "comment:" Nothing
-    return (CommentForm <$> FormSuccess user <*> FormSuccess email <*> fComment <*> FormSuccess True, [whamlet|
-        #{fragment}
-        <div .yesod_comment_avatar_input>
-            <a title="change your profile picture at gravatar" href="http://gravatar.com/emails/">
-                <img src="#{img}">
 
-        <table>
-            <tr>
-                <th>name:
-                <td colspan="2">#{username}
+handleForm :: YesodComments m => FormResult CommentForm -> ThreadId -> GWidget s m ()
+handleForm (FormSuccess cf) tid = lift $ do
+    storeComment =<< commentFromForm tid cf
+    setMessage "comment added."
+    redirectCurrentRoute
 
-            ^{fieldRow fiComment}
-            <tr>
-                <td>&nbsp;
-                <td colspan="2">
-                    <input type="submit" value="Add comment">
-        |])
+handleForm _ _ = return ()
 
--- | The comment form used in the management edit page.
-commentFormEdit :: RenderMessage m FormMessage
-                => Comment
-                -> Html
-                -> Form s m (FormResult CommentForm, GWidget s m ())
-commentFormEdit comment fragment = do
-    (fComment, fiComment) <- mreq markdownField "comment:" (Just $ content comment)
-    return (CommentForm <$> FormSuccess "" <*> FormSuccess "" <*> fComment <*> FormSuccess True, [whamlet|
-        #{fragment}
-        <table>
-            ^{fieldRow fiComment}
-            <tr>
-                <td>&nbsp;
-                <td colspan="2">
-                    <input type="submit" value="Update comment">
-        |])
 
-fieldRow :: FieldView s m -> GWidget s m ()
-fieldRow fv = [whamlet|
-    <tr .#{clazz fv}>
-        <th>
-            <label for="#{fvId fv}">#{fvLabel fv}
-            $maybe tt <- fvTooltip fv
-                <div .tooltip>#{tt}
-        <td>
-            ^{fvInput fv}
-        <td>
-            $maybe error <- fvErrors fv
-                #{error}
-            $nothing
-                &nbsp;
-    |]
-
-clazz :: FieldView s m -> String
-clazz fv = if fvRequired fv then "required" else "optional"
-
--- | Add some cassius that is common to all the yesod-comments pages
-addStyling :: Yesod m => GWidget s m ()
-addStyling = addCassius [cassius|
-    .yesod_comment_input th
-        text-align: left
-        vertical-align: top
-    .yesod_comment_input textarea
-        height: 10ex
-        width: 50ex
-    .yesod_comment_avatar_input, .yesod_comment_avatar_list
-        float: left
-    .yesod_comment_avatar_input
-        margin-right: 5px
-    .yesod_comment_avatar_list
-        margin-right: 3px
-    |]
-
--- | POST the form and insert the new comment
-handleForm :: YesodComments m
-           => FormResult CommentForm
-           -> ThreadId
-           -> GWidget s m ()
-handleForm res tid = case res of
-    FormMissing    -> return ()
-    FormFailure _  -> return ()
-    FormSuccess cf -> lift $ do
-        storeComment =<< commentFromForm tid cf
-        setMessage "comment added."
-        redirectCurrentRoute
-
--- | POST the form and update an existing comment
-handleFormEdit :: YesodComments m
-               => Route m
-               -> FormResult CommentForm
-               -> Comment
-               -> GWidget s m ()
-handleFormEdit r res comment = case res of
-    FormMissing    -> return ()
-    FormFailure _  -> return ()
-    FormSuccess cf -> lift $ do
-        updateComment comment $ comment { content = formComment cf }
-        setMessage "comment updateded."
-        redirect RedirectTemporary r
-
--- | Redirect back to the current route after a POST request
-redirectCurrentRoute :: Yesod m => GHandler s m ()
-redirectCurrentRoute = do
-    tm <- getRouteToMaster
-    mr <- getCurrentRoute
-    case mr of
-        Just r  -> redirect RedirectTemporary $ tm r
-        Nothing -> notFound
-
--- | Show a single comment
-showComment :: Yesod m => Comment -> GWidget s m ()
+showComment :: Comment -> GWidget s m ()
 showComment comment = showHelper comment (userName comment, userEmail comment)
 
--- | Show a single comment, auth version
-showCommentAuth :: (Yesod m, YesodAuth m, YesodComments m) => Comment -> GWidget s m ()
+showCommentAuth :: (YesodAuth m, YesodComments m) => Comment -> GWidget s m ()
 showCommentAuth comment = do
     let cusername = userName comment
 
     (cuname, cemail) <-
         if isAuth comment
-            then case fromSinglePiece $ cusername of
+            then case fromPathPiece $ cusername of
                 Just uid -> do
                     uname <- lift $ displayUser  uid
                     email <- lift $ displayEmail uid
@@ -269,27 +149,51 @@
 
     showHelper comment (cuname, cemail)
 
--- | Factor out common code
-showHelper :: Yesod m => Comment -> (T.Text,T.Text) -> GWidget s m ()
+showComments :: [Comment] -> (Comment -> GWidget s m ()) -> GWidget s m ()
+showComments comments f = [whamlet|
+    <div .list>
+        $if not $ null comments
+            <h4>Showing #{toHtml $ helper $ length comments}:
+
+            $forall comment <- comments
+                ^{f comment}
+    |]
+
+    where
+        -- pluralize comments
+        helper :: Int -> String
+        helper 0 = "no comments"
+        helper 1 = "1 comment"
+        helper n = show n ++ " comments"
+
+showHelper :: Comment -> (Text,Text) -> GWidget s m ()
 showHelper comment (username, email) = do
-    commentTimestamp <- lift . humanReadableTime $ timeStamp comment
+    commentTimestamp <- lift . liftIO . humanReadableTime $ timeStamp comment
+
     let anchor = "comment_" ++ show (commentId comment)
-    let img    = gravatarImg email defaultOptions { gDefault = Just MM, gSize = Just $ Size 20 }
-    addHamlet [hamlet|
-        <div .yesod_comment_avatar_list>
-            <img src="#{img}">
 
-        <p>
-            <a href="##{anchor}" id="#{anchor}">#{commentTimestamp}
-            , #{username} wrote:
+    [whamlet|
+        <div .comment>
+            <div .attribution>
+                <p>
+                    <span .avatar>
+                        <img src="#{img email}">
 
-        <blockquote>
-            #{markdownToHtml $ content comment}
+                    <a href="##{anchor}" id="#{anchor}">#{commentTimestamp}
+                    , #{username} wrote:
+
+            <div .content>
+                <blockquote>
+                    #{markdownToHtml $ content comment}
         |]
 
+    where
+        img :: Text -> String
+        img = gravatar def { gDefault = Just MM, gSize = Just $ Size 20 }
+
 -- | As the final step before insert, this is called to get the next
 --   comment id for the thread. super-high concurrency is probably not
---   well-supported here...
+--   well-supported here.
 getNextCommentId :: YesodComments m => ThreadId -> GHandler s m CommentId
 getNextCommentId tid = go =<< loadComments (Just tid)
 
@@ -298,13 +202,23 @@
         go [] = return 1
         go cs = return $ maximum (map commentId cs) + 1
 
--- | Note: this function does not requireAuthId so a non-logged in user
---   just returns false.
-isCommentingUser :: (YesodAuth m, YesodComments m)
-                 => Comment
-                 -> GHandler s m Bool
+-- | Returns False when not logged in.
+isCommentingUser :: YesodAuth m => Comment -> GHandler s m Bool
 isCommentingUser comment = do
     muid <- maybeAuthId
-    case muid of
-        Just uid -> return $ isAuth comment && toSinglePiece uid == userName comment
-        _        -> return False
+    return $ case muid of
+        Just uid -> isAuth comment && toPathPiece uid == userName comment
+        _        -> False
+
+-- | Redirect back to the current route after a POST request. Calls not
+--   found if the current route is unknown.
+redirectCurrentRoute :: Yesod m => GHandler s m ()
+redirectCurrentRoute = do
+    tm <- getRouteToMaster
+    mr <- getCurrentRoute
+    case mr of
+        Just r  -> redirect $ tm r
+        Nothing -> notFound
+
+commentLabel ::  FieldSettings master
+commentLabel = "Comment" { fsTooltip = Just "Comments are parsed as pandoc-style markdown." }
diff --git a/Yesod/Comments/Management.hs b/Yesod/Comments/Management.hs
--- a/Yesod/Comments/Management.hs
+++ b/Yesod/Comments/Management.hs
@@ -32,28 +32,29 @@
 -------------------------------------------------------------------------------
 module Yesod.Comments.Management
     ( CommentsAdmin
-    , CommentsAdminRoute(..)
     , getCommentsAdmin
+    , Route(..)
     ) where
 
 import Yesod
 import Yesod.Auth
 import Yesod.Comments.Core
-import Yesod.Goodies.Markdown
+import Yesod.Markdown
+import Control.Applicative ((<$>), (<*>), pure)
 import Control.Monad (forM, unless)
-import Data.List (nub, sort)
+import Data.List (sortBy, nub)
 import Data.Time (UTCTime, formatTime)
-import System.Locale (defaultTimeLocale, rfc822DateFormat)
 import Language.Haskell.TH.Syntax hiding (lift)
+import System.Locale (defaultTimeLocale, rfc822DateFormat)
 
 data CommentsAdmin = CommentsAdmin
 
 getCommentsAdmin :: a -> CommentsAdmin
 getCommentsAdmin = const CommentsAdmin
 
-mkYesodSub "CommentsAdmin" 
+mkYesodSub "CommentsAdmin"
     [ ClassP ''YesodAuth     [ VarT $ mkName "master" ]
-    , ClassP ''YesodComments [ VarT $ mkName "master" ] ] 
+    , ClassP ''YesodComments [ VarT $ mkName "master" ] ]
     [parseRoutes|
         /                               OverviewR  GET
         /view/#ThreadId/#CommentId      ViewR      GET
@@ -67,10 +68,10 @@
     threads <- getThreadedComments
     defaultLayout $ do
         setTitle "Comments administration"
-        addStyling
+
         [whamlet|
             <h1>Comments overview
-            <article .yesod_comments_overview>
+            <div .yesod_comments .overview>
                 $if null threads
                     <p>No comments found.
                 $else
@@ -82,10 +83,10 @@
 getViewR tid cid = withUserComment tid cid $ \comment ->
     defaultLayout $ do
         setTitle "View comment"
-        addStyling
+
         [whamlet|
             <h1>View comment
-            <article .yesod_comments_view_comment>
+            <div .yesod_comments .view>
                 <table>
                     <tr>
                         <th>Thread:
@@ -120,14 +121,16 @@
     defaultLayout $ do
         setTitle "Edit comment"
         handleFormEdit (tm OverviewR) res comment
-        addStyling
         [whamlet|
             <h1>Edit comment
-            <article .yesod_comments_edit_comment>
+            <div .yesod_comments .edit>
                 <h3>Update comment
-                <div .yesod_comment_input>
-                    <form enctype="#{enctype}" method="post">^{form}
-                    <p .helptext>Comments are parsed as pandoc-style markdown
+                <div .input>
+                    <form enctype="#{enctype}" method="post" .form-stacked>
+                        ^{form}
+
+                        <div .actions>
+                            <button .btn .primary type="submit">Add comment
         |]
 
 postEditR :: (YesodAuth m, YesodComments m) => ThreadId -> CommentId -> GHandler CommentsAdmin m RepHtml
@@ -138,7 +141,7 @@
     tm <- getRouteToMaster
     deleteComment comment
     setMessage "comment deleted."
-    redirect RedirectTemporary $ tm OverviewR
+    redirect $ tm OverviewR
 
 getThreadedComments :: (YesodAuth m, YesodComments m) => GHandler s m [(ThreadId, [Comment])]
 getThreadedComments = do
@@ -147,12 +150,27 @@
         mine <- isCommentingUser comment
         return $ if mine then [threadId comment] else []
 
-    forM (sort . nub $ concat allThreads) $ \tid ->
+    unsorted <- forM (nub $ concat allThreads) $ \tid ->
         return (tid, filter ((== tid) . threadId) allComments)
 
+    return . sortBy latest $ unsorted
+
+latest :: (ThreadId, [Comment]) -> (ThreadId, [Comment]) -> Ordering
+latest (t1, cs1) (t2,cs2) =
+    -- note the comparason is reversed so that the more recent threads
+    -- will sort first
+    case compare (latest' cs1) (latest' cs2) of
+        EQ -> compare t1 t2
+        GT -> LT
+        LT -> GT
+
+    where
+        latest' :: [Comment] -> UTCTime
+        latest' = maximum . map timeStamp
+
 showThreadedComments :: (YesodAuth m, YesodComments m) => (ThreadId, [Comment]) -> GWidget CommentsAdmin m ()
 showThreadedComments (tid, comments) = [whamlet|
-    <div .yesod_comments_overview_thread>
+    <div .yesod_comments .thread>
         <h3>#{tid}
         $forall comment <- comments
             ^{showThreadComment comment}
@@ -164,11 +182,11 @@
             mine <- lift $ isCommentingUser comment
             [whamlet|
                 $if mine
-                    <div .yesod_comments_overview_comment_yours>
+                    <div .yours>
                         ^{showCommentAuth comment}
                         ^{updateLinks comment}
                 $else
-                    <div .yesod_comments_overview_comment>
+                    <div>
                         ^{showCommentAuth comment}
                 |]
 
@@ -176,7 +194,7 @@
 updateLinks (Comment tid cid _ _ _ _ _ _ )= do
     tm <- lift $ getRouteToMaster
     [whamlet|
-        <div .yesod_comments_update_links>
+        <div .update_links>
             <p>
                 <a href=@{tm $ ViewR tid cid}>View
                 \ | 
@@ -186,7 +204,7 @@
         |]
 
 -- | Find a comment by thread/id, ensure it's the logged in user's
---   comment and execute and action on it. Gives notFound or
+--   comment and execute an action on it. Gives notFound or
 --   permissionDenied in failing cases.
 withUserComment :: (YesodAuth m, YesodComments m)
                 => ThreadId
@@ -197,9 +215,23 @@
     mcomment <- getComment tid cid
     case mcomment of
         Just comment -> do
-            _     <- requireAuthId
+            _    <- requireAuthId
             mine <- isCommentingUser comment
             unless mine $ permissionDenied "you can only manage your own comments"
             f comment
 
         Nothing -> notFound
+
+commentFormEdit :: RenderMessage m FormMessage => Comment -> Form s m CommentForm
+commentFormEdit comment = renderBootstrap $ CommentForm
+    <$> pure "" <*> pure ""
+    <*> areq markdownField commentLabel (Just $ content comment)
+    <*> pure True
+
+handleFormEdit :: YesodComments m => Route m -> FormResult CommentForm -> Comment -> GWidget s m ()
+handleFormEdit r (FormSuccess cf) comment = lift $ do
+    updateComment comment $ comment { content = formComment cf }
+    setMessage "comment updated."
+    redirect r
+
+handleFormEdit _ _ _ = return ()
diff --git a/Yesod/Comments/Storage.hs b/Yesod/Comments/Storage.hs
--- a/Yesod/Comments/Storage.hs
+++ b/Yesod/Comments/Storage.hs
@@ -7,7 +7,7 @@
 -------------------------------------------------------------------------------
 -- |
 -- Module      :  Yesod.Comments.Storage
--- Copyright   :  (c) Patrick Brisbin 2010 
+-- Copyright   :  (c) Patrick Brisbin 2010
 -- License     :  as-is
 --
 -- Maintainer  :  pbrisbin@gmail.com
@@ -18,7 +18,7 @@
 --
 -------------------------------------------------------------------------------
 module Yesod.Comments.Storage
-    ( 
+    (
     -- * Persist
     -- $persist
       getCommentPersist
@@ -32,8 +32,9 @@
     ) where
 
 import Yesod
-import Yesod.Comments.Core    (Comment(..), ThreadId, CommentId)
-import Yesod.Goodies.Markdown (Markdown(..))
+import Database.Persist.GenericSql (SqlPersist)
+import Yesod.Comments.Core    (Comment(..))
+import Yesod.Markdown         (Markdown(..))
 import Data.Time.Clock        (UTCTime)
 import qualified Data.Text as T
 
@@ -88,27 +89,27 @@
     , isAuth    = sqlCommentIsAuth    sqlComment
     }
 
-getCommentPersist :: (YesodPersist m, PersistBackend (YesodPersistBackend m) (GGHandler s m IO)) => ThreadId -> CommentId -> GHandler s m (Maybe Comment)
-getCommentPersist tid cid = return . fmap (fromSqlComment . snd) =<< runDB (getBy $ UniqueSqlComment tid cid)
+getCommentPersist :: (YesodPersistBackend m ~ SqlPersist, YesodPersist m) => T.Text -> Int -> GHandler s m (Maybe Comment)
+getCommentPersist tid cid = return . fmap (fromSqlComment . entityVal) =<< runDB (getBy $ UniqueSqlComment tid cid)
 
-storeCommentPersist :: (YesodPersist m, PersistBackend (YesodPersistBackend m) (GGHandler s m IO)) => Comment -> GHandler s m ()
+storeCommentPersist :: (YesodPersist m, PersistStore (YesodPersistBackend m) (GHandler s m)) => Comment -> GHandler s m ()
 storeCommentPersist c = return . const () =<< runDB (insert $ toSqlComment c)
 
 -- | Note, only updates the content record
-updateCommentPersist :: (YesodPersist m, PersistBackend (YesodPersistBackend m) (GGHandler s m IO)) => Comment -> Comment -> GHandler s m ()
+updateCommentPersist :: (YesodPersist m, PersistUnique (YesodPersistBackend m) (GHandler s m), PersistQuery (YesodPersistBackend m) (GHandler s m)) => Comment -> Comment -> GHandler s m ()
 updateCommentPersist (Comment tid cid _ _ _ _ _ _) (Comment _ _ _ _ _ _ newContent _) = do
     mres <- runDB (getBy $ UniqueSqlComment tid cid)
     case mres of
-        Just (k,_) -> runDB $ update k [SqlCommentContent =. newContent]
+        Just (Entity k _) -> runDB $ update k [SqlCommentContent =. newContent]
         _          -> return ()
 
-deleteCommentPersist :: (YesodPersist m, PersistBackend (YesodPersistBackend m) (GGHandler s m IO)) => Comment -> GHandler s m ()
+deleteCommentPersist :: (YesodPersist m, PersistUnique (YesodPersistBackend m) (GHandler s m)) => Comment -> GHandler s m ()
 deleteCommentPersist c = return . const () =<< runDB (deleteBy $ UniqueSqlComment (threadId c) (commentId c))
 
 -- | Use @'Nothing'@ to retrieve all comments site-wide
-loadCommentsPersist :: (YesodPersist m, PersistBackend (YesodPersistBackend m) (GGHandler s m IO)) => Maybe ThreadId -> GHandler s m [Comment]
-loadCommentsPersist (Just tid) = return . fmap (fromSqlComment . snd) =<< runDB (selectList [SqlCommentThreadId ==. tid] [Asc SqlCommentCommentId])
-loadCommentsPersist Nothing    = return . fmap (fromSqlComment . snd) =<< runDB (selectList []                           [Asc SqlCommentCommentId])
+loadCommentsPersist :: (YesodPersistBackend m ~ SqlPersist, YesodPersist m) => Maybe T.Text -> GHandler s m [Comment]
+loadCommentsPersist (Just tid) = return . fmap (fromSqlComment . entityVal) =<< runDB (selectList [SqlCommentThreadId ==. tid] [Asc SqlCommentCommentId])
+loadCommentsPersist Nothing    = return . fmap (fromSqlComment . entityVal) =<< runDB (selectList []                           [Asc SqlCommentCommentId])
 
 -- $todo
 --
diff --git a/yesod-comments.cabal b/yesod-comments.cabal
--- a/yesod-comments.cabal
+++ b/yesod-comments.cabal
@@ -1,5 +1,5 @@
 name:                yesod-comments
-version:             0.5.0
+version:             0.7
 synopsis:            A generic comments interface for a Yesod application
 description:         A generic comments interface for a Yesod application
 homepage:            http://github.com/pbrisbin/yesod-comments
@@ -19,15 +19,18 @@
                  , Yesod.Comments.Management
   
   -- Packages needed in order to build this package.
-  build-depends: base          >= 4     && < 5
-               , text          >= 0.11  && < 0.12
-               , bytestring    >= 0.9.1 && < 0.10
-               , wai           >= 0.4   && < 0.5
-               , yesod         >= 0.9   && < 1.0
-               , yesod-form    >= 0.3   && < 0.4
-               , yesod-auth    >= 0.7   && < 0.8
-               , yesod-goodies >= 0.0.3 && < 0.1
-               , persistent    >= 0.6   && < 0.7
+  build-depends: base           >= 4     && < 5
+               , text           >= 0.11  && < 0.12
+               , bytestring     >= 0.9.1 && < 0.10
+               , friendly-time  >= 0.2   && < 0.3
+               , gravatar       >= 0.5   && < 0.6
+               , persistent     >= 0.9   && < 0.10
+               , wai            >= 1.2   && < 1.3
+               , yesod          >= 1.0   && < 1.1
+               , yesod-auth     >= 1.0   && < 1.1
+               , yesod-form     >= 1.0   && < 1.1
+               , yesod-markdown >= 0.4   && < 0.5
+
                , template-haskell
                , directory
                , time
