diff --git a/changelog.markdown b/changelog.markdown
--- a/changelog.markdown
+++ b/changelog.markdown
@@ -1,3 +1,10 @@
+2008.12.16
+-----------
+
+### Fix
+
+* Add more modules in panda.cabal
+
 2008.12.15
 ----------
 
diff --git a/panda.cabal b/panda.cabal
--- a/panda.cabal
+++ b/panda.cabal
@@ -1,5 +1,5 @@
 Name:                 panda
-Version:              2008.12.15
+Version:              2008.12.16
 Build-type:           Simple
 Synopsis:             A simple static blog engine
 Description:          A simple static blog engine
@@ -26,23 +26,29 @@
 
                     Panda.Helper.Env
                     Panda.Helper.Helper
+                    Panda.Helper.Html
                     Panda.Helper.PreludeEnv
                     Panda.Helper.StateHelper
                     Panda.Helper.ThumbHelper
 
+                    Panda.Model.Album
                     Panda.Model.Comment
+                    Panda.Model.Helper
                     Panda.Model.Post
                     Panda.Model.Static
                     Panda.Model.Tag
                     
+                    
                     Panda.Type.Extension
                     Panda.Type.Pager
                     Panda.Type.Reader
+                    Panda.Type.Plugin
                     Panda.Type.State
                     Panda.Type.StaticWidget
                     Panda.Type.Theme
 
                     
+                    Panda.View.Atom.Album
                     Panda.View.Atom.Comment
                     Panda.View.Atom.Post
                     Panda.View.Atom.Static
diff --git a/src/Panda/Helper/Html.hs b/src/Panda/Helper/Html.hs
new file mode 100644
--- /dev/null
+++ b/src/Panda/Helper/Html.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE NoMonomorphismRestriction#-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Panda.Helper.Html where
+
+import Text.XHtml.Strict
+import Panda.Helper.PreludeEnv
+import Char
+
+
+span = thespan
+
+div = thediv
+id = identifier
+klass = theclass
+
+d = div
+c x = d ! [klass x]
+i x = d ! [id x]
+
+ic x y = d ! [id x, klass y]
+ci x y = ic y x
+
+ul = ulist
+
+
+
+escape_html_unicode = concatMap fixChar
+    where
+      fixChar '<' = "<"
+      fixChar '>' = ">"
+      fixChar '&' = "&"
+      fixChar '"' = "\""
+      fixChar c | ord c < 0x80 = [c]
+      fixChar c = "&#" ++ show (ord c) ++ ";"
+
+link = hotlink
+img = image
diff --git a/src/Panda/Model/Album.hs b/src/Panda/Model/Album.hs
new file mode 100644
--- /dev/null
+++ b/src/Panda/Model/Album.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Panda.Model.Album where
+
+-- env
+import Panda.Helper.Env hiding (title, body, size, path, meta, get)
+import qualified Panda.Config.Global as G
+import Panda.Helper.StateHelper
+import Panda.Helper.ThumbHelper
+
+data AlbumType = Galleria | Fade | SlideViewer | Popeye deriving (Eq, Show, Read)
+
+instance Default AlbumType where
+  def = Fade
+
+data Album = Album
+  { uid    :: String -- album/08-06-10
+  , prefix :: String
+  , show_description :: Bool
+  , album_type :: AlbumType
+  , width :: Int
+  , pictures :: [String]
+  }
+  deriving (Show, Eq)
+
+instance Resource Album where
+  resource_title = uid > spaced_url
+  
+-- CRUD
+ls_l x = ls x ^ map (x /)
+image_path id = G.image_uri / id
+
+get pre desc t w id = do
+  id.image_path.convert_if_missing_thumb w
+  get_pictures id ^ Album id pre desc t w
+  
+get_pictures = image_path > ls > (^ filter is_image)
+
+get_picture_title pre x 
+  | pre.empty = x
+  | otherwise = x.split pre.last.dropExtension
+
+for_post pre id = get pre def def def (G.album_id / id.id_to_resource)
+
+picture_links x = x.pictures .map ("/" / G.image_id / x.uid /)
+picture_thumbs x = x.pictures .map ("/" / G.image_id / x.uid / G.thumb_id /)
+picture_titles x = x.pictures .map (get_picture_title (x.prefix))
+
+data_list x = zip3 (x.picture_links) (x.picture_titles) (x.picture_thumbs)
+
+data AlbumData = 
+    Prefix
+  | Name
+  | Pictures
+  | ShowDescription
+  | Type
+  | Width
+  deriving (Show)
+
+from_list xs = get prefix show_description t w (G.album_id / at Name) where
+  at x = xs.lookup (x.show_data).fromJust
+  at' x d = xs.lookup (x .show_data) .fromMaybe d
+  prefix = at' Prefix G.picture_prefix
+  show_description = at' ShowDescription "y" .parse_boolean
+  t = at' Type "fade" .camel_case .read
+  w = at' Width "400" .read
+
diff --git a/src/Panda/Model/Helper.hs b/src/Panda/Model/Helper.hs
new file mode 100644
--- /dev/null
+++ b/src/Panda/Model/Helper.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Panda.Model.Helper where
+
+import Panda.Helper.Env
+import qualified Panda.Config.Global as G
+import Panda.Type.Reader
+import Panda.Type.Plugin (apply_plugin)
+
+get_body id   = (G.flat_uri / id) .read_file >>= apply_plugin_for_resource id
+get_reader id = id.take_extension.guess_reader.fromMaybe G.default_reader
+
+apply_plugin_for_resource id
+  | id.id_to_type.belongs_to [G.post_id, G.static_id] = apply_plugin
+  | otherwise = return
diff --git a/src/Panda/Type/Plugin.hs b/src/Panda/Type/Plugin.hs
new file mode 100644
--- /dev/null
+++ b/src/Panda/Type/Plugin.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Panda.Type.Plugin where
+
+import Panda.Helper.Env hiding (body, name)
+import qualified Panda.Model.Album as Album
+import qualified Panda.View.Atom.Album as AlbumV
+
+data PluginType = PhotoAlbum | None deriving (Show, Eq)
+
+data Plugin = Plugin 
+  { plugin_type :: PluginType
+  , args :: [(String, String)]
+  }
+  deriving (Show, Eq)
+
+-- album-plugin
+-- plugin is simple inline substitution, since markdown handles html natively
+-- [[
+--    plugin: album,
+--    name:   first-album,
+--    prefix: \d{2}-\d{2}-\d{2}
+-- ]]
+
+plugin_expression = "\n\\[\\[((.|\n)*?)\n\\]\\]"
+plugin_id = "plugin"
+
+infix_of = flip isInfixOf
+
+optimized_match x 
+  | "[[".infix_of x = x.match plugin_expression
+  | otherwise = Nothing
+
+
+parse_plugin x = x.gsub "\n" "".split "," .map (split ":") .inner_map strip .map tuple2.parse_it where
+  parse_it xs = Plugin { plugin_type = xs.at plugin_id, args = xs.reject (fst > (is plugin_id)) }
+  at x xs = case (xs.lookup x) >>= parse_plugin_type of
+    Nothing -> None
+    Just x -> x
+  parse_plugin_type x = [PhotoAlbum].label_by (show_data).lookup (x)
+
+match_result x = x.fromJust.snd.first.snd.b2u
+
+apply_plugin x = if r.isNothing then return x else r.sub_it where
+  r = x.optimized_match
+  plugin = r.match_result.parse_plugin
+  sub_it y = case plugin.plugin_type of
+    None -> return x
+    PhotoAlbum -> do 
+      album <- plugin.args.Album.from_list ^ render_plugin
+      x.sub plugin_expression album .apply_plugin
+
+
+render_plugin = render_data > show
diff --git a/src/Panda/View/Atom/Album.hs b/src/Panda/View/Atom/Album.hs
new file mode 100644
--- /dev/null
+++ b/src/Panda/View/Atom/Album.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Panda.View.Atom.Album where
+  
+import Panda.Helper.Env hiding (name, id)
+import Panda.Model.Album
+import qualified Panda.Config.Global as G
+import Panda.Helper.Html
+
+instance DataRenderer Album where
+  render_data = show_album
+
+
+show_album x = case x.album_type of
+  Fade -> show_fade x
+  Galleria -> show_galleria x
+  SlideViewer -> show_slide_viewer x
+  Popeye -> show_popeye x
+
+show_popeye x = c "popeye" << ul << x.data_list.map picture_li where 
+    picture_li (l, t, i) = li << 
+      link l << img ! [src i, alt t]
+
+show_slide_viewer x = ul ! [id "slide-viewer", klass "svw"] << x.data_list.map picture_li where 
+  picture_li (l, t, i) = li << 
+    img ! [src i, alt t]
+
+show_galleria x = ul ! [klass "gallery"] << x.data_list.map picture_li where 
+  picture_li (l, t, i) = li << 
+    img ! [src i, alt t]
+
+show_fade x = ul ! [klass "fade-album"] << x.data_list.map picture_li where 
+  picture_li (l, t, i) = li << 
+    [ toHtml $ link l << img ! [src i, alt t]
+    , if x.show_description then p << t else empty_html
+    ]
