diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2016 Tony Morris
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions, the following disclaimer and the following SHA-512 checksum.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions, the following disclaimer and the following SHA-512
+checksum in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THIS SOFTWARE IS PROVIDED WITH A SHA-512 CHECKSUM.
+ecdfdf543fd166b13b76b11e0b010e00d693028771880ffd8f9252ae0b8ac42bddf8eb7a23c21c86a3b50039d642ad9eeb7e8a0e82f6a345f60feb4a54808362
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,44 @@
+#!/usr/bin/env runhaskell
+\begin{code}
+{-# OPTIONS_GHC -Wall #-}
+module Main (main) where
+
+import Data.List ( nub )
+import Data.Version ( showVersion )
+import Distribution.Package ( PackageName(PackageName), PackageId, InstalledPackageId, packageVersion, packageName )
+import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) )
+import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )
+import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )
+import Distribution.Simple.BuildPaths ( autogenModulesDir )
+import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )
+import Distribution.Simple.LocalBuildInfo ( withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )
+import Distribution.Verbosity ( Verbosity )
+import System.FilePath ( (</>) )
+
+main :: IO ()
+main = defaultMainWithHooks simpleUserHooks
+  { buildHook = \pkg lbi hooks flags -> do
+     generateBuildModule (fromFlag (buildVerbosity flags)) pkg lbi
+     buildHook simpleUserHooks pkg lbi hooks flags
+  }
+
+generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()
+generateBuildModule verbosity pkg lbi = do
+  let dir = autogenModulesDir lbi
+  createDirectoryIfMissingVerbose verbosity True dir
+  withLibLBI pkg lbi $ \_ libcfg -> do
+    withTestLBI pkg lbi $ \suite suitecfg -> do
+      rewriteFile (dir </> "Build_" ++ testName suite ++ ".hs") $ unlines
+        [ "module Build_" ++ testName suite ++ " where"
+        , "deps :: [String]"
+        , "deps = " ++ (show $ formatdeps (testDeps libcfg suitecfg))
+        ]
+  where
+    formatdeps = map (formatone . snd)
+    formatone p = case packageName p of
+      PackageName n -> n ++ "-" ++ showVersion (packageVersion p)
+
+testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]
+testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys
+
+\end{code}
diff --git a/casr-logbook.cabal b/casr-logbook.cabal
new file mode 100644
--- /dev/null
+++ b/casr-logbook.cabal
@@ -0,0 +1,99 @@
+name:               casr-logbook
+version:            0.0.1
+license:            OtherLicense
+license-file:       LICENSE
+author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
+maintainer:         Tony Morris
+copyright:          Copyright (C) 2016 Tony Morris
+synopsis:           CASR 61.345 Pilot Personal Logbook
+category:           Aviation
+description:        
+  <<https://i.imgur.com/p6LT40r.png>>
+  .
+  CASR 61.345 Pilot Personal Logbook
+  .
+  <<https://i.imgur.com/Lfhcmtg.png>>
+
+homepage:           https://github.com/tonymorris/casr-61.345
+bug-reports:        https://github.com/tonymorris/casr-61.345/issues
+cabal-version:      >= 1.10
+build-type:         Custom
+extra-source-files: changelog
+
+source-repository   head
+  type:             git
+  location:         git@github.com:tonymorris/casr-61.345.git
+
+flag                small_base
+  description:      Choose the new, split-up base package.
+
+library
+  default-language:
+                    Haskell2010
+
+  build-depends:
+                    base < 5 && >= 4.8
+                    , containers < 0.6 && >= 0.4
+                    
+  ghc-options:
+                    -Wall
+
+  hs-source-dirs:
+                    src
+
+  exposed-modules:
+                    Data.Aviation.Casr.Logbook
+                    Data.Aviation.Casr.Logbook.Aircraft
+                    Data.Aviation.Casr.Logbook.ARN
+                    Data.Aviation.Casr.Logbook.Date
+                    Data.Aviation.Casr.Logbook.DayNight
+                    Data.Aviation.Casr.Logbook.DOB
+                    Data.Aviation.Casr.Logbook.Engine
+                    Data.Aviation.Casr.Logbook.FlightLogEntries
+                    Data.Aviation.Casr.Logbook.FlightLogEntry
+                    Data.Aviation.Casr.Logbook.FlightLog
+                    Data.Aviation.Casr.Logbook.FlightPath
+                    Data.Aviation.Casr.Logbook.Hours
+                    Data.Aviation.Casr.Logbook.Image
+                    Data.Aviation.Casr.Logbook.Images
+                    Data.Aviation.Casr.Logbook.ImageType
+                    Data.Aviation.Casr.Logbook.Printer.Markdown
+                    Data.Aviation.Casr.Logbook.Name
+                    Data.Aviation.Casr.Logbook.PiC
+                    Data.Aviation.Casr.Logbook.PoB
+                    Data.Aviation.Casr.Logbook.Sequence
+                    Data.Aviation.Casr.Logbook.Totals
+                    Data.Aviation.Casr.Logbook.TrackLog
+                    Data.Aviation.Casr.Logbook.TrackLogs
+                    Data.Aviation.Casr.Logbook.TrackLogType
+                    Data.Aviation.Casr.Logbook.Video
+                    Data.Aviation.Casr.Logbook.Videos
+                    Data.Aviation.Casr.Logbook.VideoType
+                    Data.Aviation.Casr.Logbook.Visualisation
+                    Data.Aviation.Casr.Logbook.Visualisations
+                    Data.Aviation.Casr.Logbook.VisualisationType
+
+test-suite doctests
+  type:
+                    exitcode-stdio-1.0
+
+  main-is:
+                    doctests.hs
+
+  default-language:
+                    Haskell2010
+
+  build-depends:
+                    base < 5 && >= 3
+                    , doctest >= 0.9.7
+                    , filepath >= 1.3
+                    , directory >= 1.1
+                    , QuickCheck >= 2.0
+                    , template-haskell >= 2.8
+
+  ghc-options:
+                    -Wall
+                    -threaded
+
+  hs-source-dirs:
+                    test
diff --git a/changelog b/changelog
new file mode 100644
--- /dev/null
+++ b/changelog
@@ -0,0 +1,8 @@
+0.0.1
+
+* Initial release
+* Initial data structures for a CASR 61.345 Pilot Personal Logbook.
+
+  These data structures are open to change as more is understood about the necessity of logbooks.
+  In particular, logging the particulars of IFR flights are currently not accounted for.
+
diff --git a/src/Data/Aviation/Casr/Logbook.hs b/src/Data/Aviation/Casr/Logbook.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook.hs
@@ -0,0 +1,33 @@
+module Data.Aviation.Casr.Logbook(
+  module L
+) where
+
+import Data.Aviation.Casr.Logbook.Aircraft as L
+import Data.Aviation.Casr.Logbook.ARN as L
+import Data.Aviation.Casr.Logbook.Date as L
+import Data.Aviation.Casr.Logbook.DayNight as L
+import Data.Aviation.Casr.Logbook.DOB as L
+import Data.Aviation.Casr.Logbook.Engine as L
+import Data.Aviation.Casr.Logbook.FlightLogEntries as L
+import Data.Aviation.Casr.Logbook.FlightLogEntry as L
+import Data.Aviation.Casr.Logbook.FlightLog as L
+import Data.Aviation.Casr.Logbook.FlightPath as L
+import Data.Aviation.Casr.Logbook.Hours as L
+import Data.Aviation.Casr.Logbook.Image as L
+import Data.Aviation.Casr.Logbook.Images as L
+import Data.Aviation.Casr.Logbook.ImageType as L
+import Data.Aviation.Casr.Logbook.Printer.Markdown as L
+import Data.Aviation.Casr.Logbook.Name as L
+import Data.Aviation.Casr.Logbook.PiC as L
+import Data.Aviation.Casr.Logbook.PoB as L
+import Data.Aviation.Casr.Logbook.Sequence as L
+import Data.Aviation.Casr.Logbook.Totals as L
+import Data.Aviation.Casr.Logbook.TrackLog as L
+import Data.Aviation.Casr.Logbook.TrackLogs as L
+import Data.Aviation.Casr.Logbook.TrackLogType as L
+import Data.Aviation.Casr.Logbook.Video as L
+import Data.Aviation.Casr.Logbook.Videos as L
+import Data.Aviation.Casr.Logbook.VideoType as L
+import Data.Aviation.Casr.Logbook.Visualisation as L
+import Data.Aviation.Casr.Logbook.Visualisations as L
+import Data.Aviation.Casr.Logbook.VisualisationType as L
diff --git a/src/Data/Aviation/Casr/Logbook/ARN.hs b/src/Data/Aviation/Casr/Logbook/ARN.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/ARN.hs
@@ -0,0 +1,19 @@
+module Data.Aviation.Casr.Logbook.ARN (
+  ARN(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.String
+
+newtype ARN =
+  ARN
+    String
+  deriving (Eq, Ord, Show)
+
+instance IsString ARN where
+  fromString =
+    ARN
+    
+instance Markdown ARN where
+  markdown (ARN s) =
+    "* Aviation Reference Number: **`" ++ s ++ "`**\n"
diff --git a/src/Data/Aviation/Casr/Logbook/Aircraft.hs b/src/Data/Aviation/Casr/Logbook/Aircraft.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Aircraft.hs
@@ -0,0 +1,27 @@
+module Data.Aviation.Casr.Logbook.Aircraft (
+  Aircraft(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Engine
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data Aircraft =
+  Aircraft
+    String -- type
+    String -- registration
+    Engine
+  deriving (Eq, Ord, Show)
+
+instance Markdown Aircraft where
+  markdown (Aircraft t r e) =
+    concat
+      [
+        "* Aircraft"
+      , "\n  * Type: **"
+      , t
+      , "**\n  * Registration: **`"
+      , r
+      , "`**\n  * Engine: **`"
+      , markdown e
+      , "`**\n"
+      ]
diff --git a/src/Data/Aviation/Casr/Logbook/DOB.hs b/src/Data/Aviation/Casr/Logbook/DOB.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/DOB.hs
@@ -0,0 +1,19 @@
+module Data.Aviation.Casr.Logbook.DOB (
+  DOB(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.String
+
+newtype DOB =
+  DOB
+    String
+  deriving (Eq, Ord, Show)
+
+instance IsString DOB where
+  fromString =
+    DOB
+
+instance Markdown DOB where
+  markdown (DOB s) =
+    "* Date of Birth: **`" ++ s ++ "`**\n"
diff --git a/src/Data/Aviation/Casr/Logbook/Date.hs b/src/Data/Aviation/Casr/Logbook/Date.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Date.hs
@@ -0,0 +1,19 @@
+module Data.Aviation.Casr.Logbook.Date (
+  Date(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.String
+    
+newtype Date =
+  Date
+    String
+  deriving (Eq, Ord, Show)
+
+instance IsString Date where
+  fromString =
+    Date
+    
+instance Markdown Date where
+  markdown (Date s) =
+    "* Date: **`" ++ s ++ "`**\n"
diff --git a/src/Data/Aviation/Casr/Logbook/DayNight.hs b/src/Data/Aviation/Casr/Logbook/DayNight.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/DayNight.hs
@@ -0,0 +1,23 @@
+module Data.Aviation.Casr.Logbook.DayNight (
+  DayNight(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data DayNight =
+  Day
+  | Night
+  | DayNight
+  deriving (Eq, Ord, Show)
+    
+instance Markdown DayNight where
+  markdown x =
+    concat
+      [
+        "* Day/Night: **"
+      , case x of
+          Day -> "Day"
+          Night -> "Night"
+          DayNight -> "Day & Night"
+      , "**\n"
+      ]
diff --git a/src/Data/Aviation/Casr/Logbook/Engine.hs b/src/Data/Aviation/Casr/Logbook/Engine.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Engine.hs
@@ -0,0 +1,16 @@
+module Data.Aviation.Casr.Logbook.Engine (
+  Engine(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data Engine =
+  Single
+  | Multi
+  deriving (Eq, Ord, Show)
+    
+instance Markdown Engine where
+  markdown Single =
+    "single"
+  markdown Multi =
+    "multi"
diff --git a/src/Data/Aviation/Casr/Logbook/FlightLog.hs b/src/Data/Aviation/Casr/Logbook/FlightLog.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/FlightLog.hs
@@ -0,0 +1,35 @@
+module Data.Aviation.Casr.Logbook.FlightLog (
+  FlightLog(..)
+) where
+
+import Data.Aviation.Casr.Logbook.ARN
+import Data.Aviation.Casr.Logbook.DOB
+import Data.Aviation.Casr.Logbook.FlightLogEntries
+import Data.Aviation.Casr.Logbook.Name
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.Totals
+
+data FlightLog =
+  FlightLog
+    Name
+    DOB
+    ARN
+    FlightLogEntries
+  deriving (Eq, Ord, Show)
+    
+instance Markdown FlightLog where
+  markdown (FlightLog (Name name) dob arn entries) =
+    concat
+      [
+        "# Pilot Personal Log Book\n"
+      , "### Civil Aviation Safety Regulation 1998 (61.345) [*austlii.edu.au*](http://www.austlii.edu.au/au/legis/cth/consol_reg/casr1998333/s61.345.html)\n\n"
+      , "* "
+      , name
+      , "\n"
+      , markdown dob
+      , markdown arn
+      , "\n----\n\n"
+      , markdown (totals entries)
+      , "\n----\n\n"
+      , markdown entries
+      ]
diff --git a/src/Data/Aviation/Casr/Logbook/FlightLogEntries.hs b/src/Data/Aviation/Casr/Logbook/FlightLogEntries.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/FlightLogEntries.hs
@@ -0,0 +1,22 @@
+module Data.Aviation.Casr.Logbook.FlightLogEntries (
+  FlightLogEntries(..)
+) where
+
+import Data.Aviation.Casr.Logbook.FlightLogEntry
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.List
+
+newtype FlightLogEntries =
+  FlightLogEntries
+    [FlightLogEntry]
+  deriving (Eq, Ord, Show)
+
+instance Monoid FlightLogEntries where
+  mempty =
+    FlightLogEntries []
+  FlightLogEntries e1 `mappend` FlightLogEntries e2 =
+    FlightLogEntries (e1 `mappend` e2)
+
+instance Markdown FlightLogEntries where
+  markdown (FlightLogEntries g) =
+    intercalate "\n\n----\n\n" (fmap markdown g)
diff --git a/src/Data/Aviation/Casr/Logbook/FlightLogEntry.hs b/src/Data/Aviation/Casr/Logbook/FlightLogEntry.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/FlightLogEntry.hs
@@ -0,0 +1,60 @@
+module Data.Aviation.Casr.Logbook.FlightLogEntry (
+  FlightLogEntry(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Aircraft
+import Data.Aviation.Casr.Logbook.Date
+import Data.Aviation.Casr.Logbook.DayNight
+import Data.Aviation.Casr.Logbook.FlightPath
+import Data.Aviation.Casr.Logbook.Hours
+import Data.Aviation.Casr.Logbook.Images
+import Data.Aviation.Casr.Logbook.Name
+import Data.Aviation.Casr.Logbook.PiC
+import Data.Aviation.Casr.Logbook.PoB
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.Sequence
+import Data.Aviation.Casr.Logbook.TrackLogs
+import Data.Aviation.Casr.Logbook.Videos
+import Data.Aviation.Casr.Logbook.Visualisations
+
+{-
+
+This data structure currently only handles Day VFR. More modifications are
+likely to result in a complete flight log entry structure.
+
+-}
+data FlightLogEntry =
+  FlightLogEntry
+    Name
+    Sequence
+    Date 
+    Aircraft
+    Hours
+    PoB
+    FlightPath
+    DayNight
+    PiC
+    TrackLogs
+    Visualisations
+    Images
+    Videos
+  deriving (Eq, Ord, Show)
+    
+instance Markdown FlightLogEntry where
+  markdown (FlightLogEntry name sequ date aircraft hours pob flightpath daynight pic tracklogs visualisations images videos) =
+    concat
+      [
+        markdown name
+      , markdown date
+      , markdown sequ
+      , markdown aircraft
+      , markdown hours
+      , markdown pob
+      , markdown flightpath
+      , markdown daynight
+      , markdown pic
+      , markdown tracklogs
+      , markdown videos
+      , markdown visualisations
+      , markdown images
+      ]
diff --git a/src/Data/Aviation/Casr/Logbook/FlightPath.hs b/src/Data/Aviation/Casr/Logbook/FlightPath.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/FlightPath.hs
@@ -0,0 +1,35 @@
+module Data.Aviation.Casr.Logbook.FlightPath (
+  FlightPath(..)
+, directPath
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data FlightPath =
+  FlightPath
+    String -- start
+    [String] -- touch-downs
+    String -- end
+  deriving (Eq, Ord, Show)
+
+directPath ::
+  String
+  -> String
+  -> FlightPath
+directPath fr to =
+  FlightPath
+    fr
+    []
+    to
+
+instance Markdown FlightPath where
+  markdown (FlightPath s x e) =
+    concat
+      [
+        "* Path: **"
+      , s
+      , x >>= (" - " ++)
+      , " - "
+      , e
+      , "**\n"
+      ]
diff --git a/src/Data/Aviation/Casr/Logbook/Hours.hs b/src/Data/Aviation/Casr/Logbook/Hours.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Hours.hs
@@ -0,0 +1,37 @@
+module Data.Aviation.Casr.Logbook.Hours (
+  Hours(..)
+, zeroHours
+, addHours
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+-- abstract
+data Hours =
+  Hours
+    Int -- full
+    Int  -- partial
+  deriving (Eq, Ord, Show)
+
+zeroHours ::
+  Hours
+zeroHours =
+  Hours 0 0
+
+addHours ::
+  Hours 
+  -> Hours
+  -> Hours
+Hours f1 p1 `addHours` Hours f2 p2 =
+  let (h, q) = divMod (p1 + p2) 10
+  in  Hours (f1 + f2 + h) q 
+
+instance Monoid Hours where
+  mempty =
+    zeroHours
+  mappend =
+    addHours
+
+instance Markdown Hours where
+  markdown (Hours t p) =
+    "* Hours: **`" ++ show t ++ "." ++ show p ++ "`**\n"
diff --git a/src/Data/Aviation/Casr/Logbook/Image.hs b/src/Data/Aviation/Casr/Logbook/Image.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Image.hs
@@ -0,0 +1,29 @@
+module Data.Aviation.Casr.Logbook.Image (
+  Image(..)  
+) where
+
+import Data.Aviation.Casr.Logbook.ImageType
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Maybe
+
+data Image =
+  Image
+    String -- uri
+    (Maybe String) -- name
+    ImageType
+  deriving (Eq, Ord, Show)
+
+instance Markdown Image where
+  markdown (Image uri name itype) =
+    let t = markdown itype
+        n = fromMaybe ("Image (" ++ t ++ ")") name
+    in  concat
+          [
+            "<a href=\""
+          , uri
+          , "\"><img src=\""
+          , uri
+          , "\" width=\"120\" alt=\""
+          , n
+          , "\"/></a>"
+          ]
diff --git a/src/Data/Aviation/Casr/Logbook/ImageType.hs b/src/Data/Aviation/Casr/Logbook/ImageType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/ImageType.hs
@@ -0,0 +1,16 @@
+module Data.Aviation.Casr.Logbook.ImageType (
+  ImageType(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data ImageType =
+  Png
+  | Jpg
+  deriving (Eq, Ord, Show)
+
+instance Markdown ImageType where
+  markdown Png =
+    "png"
+  markdown Jpg =
+    "jpg"
diff --git a/src/Data/Aviation/Casr/Logbook/Images.hs b/src/Data/Aviation/Casr/Logbook/Images.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Images.hs
@@ -0,0 +1,25 @@
+module Data.Aviation.Casr.Logbook.Images (
+  Images(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Image
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+newtype Images =
+  Images
+    [Image]
+  deriving (Eq, Ord, Show)
+    
+instance Monoid Images where
+  mempty =
+    Images []
+  Images i1 `mappend` Images i2 =
+    Images (i1 `mappend` i2)
+
+instance Markdown Images where
+  markdown (Images i) =
+    case i of
+      [] ->
+        []        
+      _ ->
+        "\n<div style=\"text-align: justify\">\n" ++ (i >>= \j -> markdown j ++ "\n") ++ "</div>"
diff --git a/src/Data/Aviation/Casr/Logbook/Name.hs b/src/Data/Aviation/Casr/Logbook/Name.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Name.hs
@@ -0,0 +1,19 @@
+module Data.Aviation.Casr.Logbook.Name (
+  Name(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.String
+
+newtype Name =
+  Name
+    String
+  deriving (Eq, Ord, Show)
+
+instance IsString Name where
+  fromString =
+    Name
+
+instance Markdown Name where
+  markdown (Name s) =
+    "### " ++ s ++ "\n"
diff --git a/src/Data/Aviation/Casr/Logbook/PiC.hs b/src/Data/Aviation/Casr/Logbook/PiC.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/PiC.hs
@@ -0,0 +1,19 @@
+module Data.Aviation.Casr.Logbook.PiC (
+  PiC(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.String
+
+newtype PiC =
+  PiC
+    String
+  deriving (Eq, Ord, Show)
+
+instance IsString PiC where
+  fromString =
+    PiC
+    
+instance Markdown PiC where
+  markdown (PiC s) =
+    "* Pilot in Command: **" ++ s ++ "**\n"
diff --git a/src/Data/Aviation/Casr/Logbook/PoB.hs b/src/Data/Aviation/Casr/Logbook/PoB.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/PoB.hs
@@ -0,0 +1,34 @@
+module Data.Aviation.Casr.Logbook.PoB (
+  PoB(..)
+, solo
+, dual
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data PoB =
+  PoB Int
+  deriving (Eq, Ord, Show)
+
+solo ::
+  PoB
+solo =
+  PoB 1
+
+dual ::
+  PoB
+dual =
+  PoB 2
+
+instance Markdown PoB where  
+  markdown (PoB n) =
+    concat
+      [
+        "* PoB: **`"
+      , case n of
+          0 -> "unmanned"
+          1 -> "solo"
+          2 -> "dual"
+          _ -> show n
+      , "`**\n"
+      ]
diff --git a/src/Data/Aviation/Casr/Logbook/Printer/Markdown.hs b/src/Data/Aviation/Casr/Logbook/Printer/Markdown.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Printer/Markdown.hs
@@ -0,0 +1,26 @@
+module Data.Aviation.Casr.Logbook.Printer.Markdown (
+  Markdown(..)
+, printMarkdownFile
+, writeMarkdownFile
+) where
+
+class Markdown s where
+  markdown ::
+    s
+    -> String
+
+printMarkdownFile ::
+  Markdown s =>
+  s
+  -> IO ()
+printMarkdownFile =
+  putStrLn . markdown
+
+writeMarkdownFile ::
+  Markdown s =>
+  FilePath
+  -> s
+  -> IO ()
+writeMarkdownFile p =
+  writeFile p . markdown
+  
diff --git a/src/Data/Aviation/Casr/Logbook/Sequence.hs b/src/Data/Aviation/Casr/Logbook/Sequence.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Sequence.hs
@@ -0,0 +1,19 @@
+module Data.Aviation.Casr.Logbook.Sequence (
+  Sequence(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.String
+
+newtype Sequence =
+  Sequence
+    String
+  deriving (Eq, Ord, Show)
+
+instance IsString Sequence where
+  fromString =
+    Sequence
+
+instance Markdown Sequence where
+  markdown (Sequence s) =
+    "* Sequence: **" ++ s ++ "**\n"
diff --git a/src/Data/Aviation/Casr/Logbook/Totals.hs b/src/Data/Aviation/Casr/Logbook/Totals.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Totals.hs
@@ -0,0 +1,150 @@
+module Data.Aviation.Casr.Logbook.Totals (
+  Totals(..)
+, zeroTotals
+, singleTotals
+, updateTotals
+, totals
+) where
+
+import Data.Aviation.Casr.Logbook.Aircraft
+import Data.Aviation.Casr.Logbook.DayNight
+import Data.Aviation.Casr.Logbook.Engine
+import Data.Aviation.Casr.Logbook.FlightLogEntry
+import Data.Aviation.Casr.Logbook.FlightLogEntries
+import Data.Aviation.Casr.Logbook.Hours
+import Data.Aviation.Casr.Logbook.PoB
+import Data.Aviation.Casr.Logbook.PiC
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Foldable(foldl')
+import Data.Map(Map)
+import qualified Data.Map as Map
+
+data Totals =
+  Totals
+    Hours -- total
+    Hours -- dual
+    Hours -- solo
+    (Map String Hours) -- type
+    (Map String Hours) -- aircraft
+    Hours -- single-engine
+    Hours -- multi-engine
+    Hours -- day
+    Hours -- night
+    Hours -- day & night
+    (Map String Hours) -- pilot in command
+  deriving (Eq, Ord, Show)
+
+instance Monoid Totals where
+  mempty =
+    zeroTotals
+  Totals total1 dualhours1 solohours1 intype1 inreg1 singleengine1 multiengine1 day1 night1 daynight1 pic1 `mappend` Totals total2 dualhours2 solohours2 intype2 inreg2 singleengine2 multiengine2 day2 night2 daynight2 pic2 =
+    Totals
+      (total1 `mappend` total2)
+      (dualhours1 `mappend` dualhours2)
+      (solohours1 `mappend` solohours2)
+      (intype1 `mappend` intype2)
+      (inreg1 `mappend` inreg2)
+      (singleengine1 `mappend` singleengine2)
+      (multiengine1 `mappend` multiengine2)
+      (day1 `mappend` day2)
+      (night1 `mappend` night2)
+      (daynight1 `mappend` daynight2)
+      (pic1 `mappend` pic2)
+
+instance Markdown Totals where
+  markdown (Totals total dualhours solohours intype inreg singleengine multiengine day night daynight pic) =
+    let displayHours (Hours f p) =
+          show f ++ "." ++ show p
+        displayPoint x h =
+          "* " ++ x ++ ": **`" ++ displayHours h ++ "`**\n"
+        displayMap x m =
+          "* " ++ x ++ "\n" ++ Map.foldrWithKey (\k h s -> "  * " ++ k ++ ": **`" ++ displayHours h ++ "`**\n" ++ s) "" m
+    in  concat
+          [
+            "##### Summary\n"
+          , displayPoint "Total Hours" total
+          , displayPoint "Dual Hours" dualhours
+          , displayPoint "Solo Hours" solohours
+          , displayMap "Hours in type" intype
+          , displayMap "Hours in registration" inreg
+          , displayPoint "Single-engine Hours" singleengine
+          , displayPoint "Multi-engine Hours" multiengine
+          , displayPoint "Day Hours" day
+          , displayPoint "Night Hours" night
+          , displayPoint "Day & Night Hours" daynight
+          , displayMap "Hours with PiC" pic            
+          ]
+
+zeroTotals ::
+  Totals
+zeroTotals =
+  Totals
+    zeroHours
+    zeroHours
+    zeroHours
+    Map.empty
+    Map.empty
+    zeroHours
+    zeroHours
+    zeroHours
+    zeroHours
+    zeroHours
+    Map.empty
+
+singleTotals ::
+ FlightLogEntry
+ -> Totals
+singleTotals (FlightLogEntry _ _ _ (Aircraft atype areg aeng) hours (PoB pob) _ dn (PiC pic) _ _ _ _) =
+  Totals
+    hours
+    (
+      case pob of
+        2 -> hours
+        _ -> zeroHours
+    )
+    (
+      case pob of
+        1 -> hours
+        _ -> zeroHours
+    )
+    (Map.singleton atype hours)
+    (Map.singleton areg hours)
+    (
+      case aeng of
+        Single -> hours
+        _ -> zeroHours
+    )
+    (
+      case aeng of
+        Multi -> hours
+        _ -> zeroHours
+    )
+    (
+      case dn of
+        Day -> hours
+        _ -> zeroHours
+    )
+    (
+      case dn of
+        Night -> hours
+        _ -> zeroHours
+    )
+    (
+      case dn of
+        Night -> hours
+        _ -> zeroHours
+    )
+    (Map.singleton pic hours)
+
+updateTotals ::
+  FlightLogEntry
+  -> Totals
+  -> Totals
+updateTotals =
+  mappend . singleTotals
+
+totals ::
+  FlightLogEntries
+  -> Totals
+totals (FlightLogEntries e) =
+  foldl' (flip updateTotals) zeroTotals e
diff --git a/src/Data/Aviation/Casr/Logbook/TrackLog.hs b/src/Data/Aviation/Casr/Logbook/TrackLog.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/TrackLog.hs
@@ -0,0 +1,53 @@
+module Data.Aviation.Casr.Logbook.TrackLog (
+  TrackLog(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.TrackLogType
+import Data.Maybe
+
+data TrackLog =
+  TrackLog
+    String -- uri
+    (Maybe String) -- name
+    TrackLogType
+  deriving (Eq, Ord, Show)
+
+instance Markdown TrackLog where
+  markdown (TrackLog uri name ttype) =
+    let t = markdown ttype        
+        n = fmap (\z -> "**" ++ z ++ "**") name
+    in  case ttype of 
+          ImageLog _ ->
+            concat
+              [
+                "  * "
+              , case n of
+                  Nothing ->
+                    "*" ++ t ++ "*"
+                  Just n' ->
+                    n'
+              , "\n\n    "
+              , "<a href=\""
+              , uri
+              , "\"><img src=\""
+              , uri
+              , "\" width=\"360\" alt=\""
+              , fromMaybe t name
+              , "\"/></a>"
+              ]
+          _ ->
+            concat
+              [
+                "  * "
+              , case n of
+                  Nothing ->
+                    ""
+                  Just n' ->
+                    n' ++ ": "
+              , "["
+              , t
+              , "]("
+              , uri
+              , ")"
+              ]
diff --git a/src/Data/Aviation/Casr/Logbook/TrackLogType.hs b/src/Data/Aviation/Casr/Logbook/TrackLogType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/TrackLogType.hs
@@ -0,0 +1,23 @@
+module Data.Aviation.Casr.Logbook.TrackLogType (
+  TrackLogType(..)
+) where
+
+import Data.Aviation.Casr.Logbook.ImageType
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data TrackLogType =
+  Gpx
+  | Kml
+  | Kmz
+  | ImageLog ImageType
+  deriving (Eq, Ord, Show)
+    
+instance Markdown TrackLogType where
+  markdown Gpx =
+    "gpx"
+  markdown Kml =
+    "kml"
+  markdown Kmz =
+    "kmz"
+  markdown (ImageLog i) =
+    markdown i
diff --git a/src/Data/Aviation/Casr/Logbook/TrackLogs.hs b/src/Data/Aviation/Casr/Logbook/TrackLogs.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/TrackLogs.hs
@@ -0,0 +1,25 @@
+module Data.Aviation.Casr.Logbook.TrackLogs (
+  TrackLogs(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.TrackLog
+
+newtype TrackLogs =
+  TrackLogs
+    [TrackLog]
+  deriving (Eq, Ord, Show)
+
+instance Monoid TrackLogs where
+  mempty =
+    TrackLogs []
+  TrackLogs t1 `mappend` TrackLogs t2 =
+    TrackLogs (t1 `mappend` t2)
+
+instance Markdown TrackLogs where
+  markdown (TrackLogs t) =
+    case t of
+      [] ->
+        ""
+      _ ->
+        "* **Track**\n" ++ (t >>= \u -> markdown u ++ "\n")
diff --git a/src/Data/Aviation/Casr/Logbook/Video.hs b/src/Data/Aviation/Casr/Logbook/Video.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Video.hs
@@ -0,0 +1,29 @@
+module Data.Aviation.Casr.Logbook.Video (
+  Video(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.VideoType
+import Data.Maybe
+
+data Video =
+  Video
+    String -- uri
+    (Maybe String) -- name
+    VideoType
+  deriving (Eq, Ord, Show)
+
+instance Markdown Video where
+  markdown (Video uri name vtype) =
+    let t = markdown vtype
+        n = fromMaybe ("Video (" ++ t ++ ")") name
+    in  concat
+          [
+            "**"
+          , n
+          , ":** ["
+          , t
+          , "]("
+          , uri
+          , ")"
+          ]
diff --git a/src/Data/Aviation/Casr/Logbook/VideoType.hs b/src/Data/Aviation/Casr/Logbook/VideoType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/VideoType.hs
@@ -0,0 +1,16 @@
+module Data.Aviation.Casr.Logbook.VideoType (
+  VideoType(..)  
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data VideoType =
+  YouTube
+  | Vimeo
+  deriving (Eq, Ord, Show)
+
+instance Markdown VideoType where
+  markdown YouTube =
+    "youtube"
+  markdown Vimeo =
+    "vimeo"
diff --git a/src/Data/Aviation/Casr/Logbook/Videos.hs b/src/Data/Aviation/Casr/Logbook/Videos.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Videos.hs
@@ -0,0 +1,25 @@
+module Data.Aviation.Casr.Logbook.Videos (
+  Videos(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.Video
+
+newtype Videos =
+  Videos
+    [Video]
+  deriving (Eq, Ord, Show)
+    
+instance Monoid Videos where
+  mempty =
+    Videos []
+  Videos v1 `mappend` Videos v2 =
+    Videos (v1 `mappend` v2)
+
+instance Markdown Videos where
+  markdown (Videos v) =
+    case v of
+      [] ->
+        ""
+      _ ->
+        "* **Videos**\n" ++ (v >>= \w -> "  * " ++ markdown w ++ "\n")
diff --git a/src/Data/Aviation/Casr/Logbook/Visualisation.hs b/src/Data/Aviation/Casr/Logbook/Visualisation.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Visualisation.hs
@@ -0,0 +1,29 @@
+module Data.Aviation.Casr.Logbook.Visualisation (
+  Visualisation(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.VisualisationType
+
+data Visualisation =
+  Visualisation
+    String -- uri
+    (Maybe String) -- name
+    VisualisationType
+  deriving (Eq, Ord, Show)
+
+instance Markdown Visualisation where
+  markdown (Visualisation uri name vtype) =
+    let t = markdown vtype
+        n = case name of
+              Nothing -> ""
+              Just n' -> "**" ++ n' ++ "**: "
+    in  concat
+          [
+            n
+          , "["
+          , t
+          , "]("
+          , uri
+          , ")"
+          ]
diff --git a/src/Data/Aviation/Casr/Logbook/VisualisationType.hs b/src/Data/Aviation/Casr/Logbook/VisualisationType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/VisualisationType.hs
@@ -0,0 +1,13 @@
+module Data.Aviation.Casr.Logbook.VisualisationType (
+  VisualisationType(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+
+data VisualisationType =
+  Doarama
+  deriving (Eq, Ord, Show)
+
+instance Markdown VisualisationType where
+  markdown Doarama =
+    "doarama"
diff --git a/src/Data/Aviation/Casr/Logbook/Visualisations.hs b/src/Data/Aviation/Casr/Logbook/Visualisations.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aviation/Casr/Logbook/Visualisations.hs
@@ -0,0 +1,25 @@
+module Data.Aviation.Casr.Logbook.Visualisations (
+  Visualisations(..)
+) where
+
+import Data.Aviation.Casr.Logbook.Printer.Markdown
+import Data.Aviation.Casr.Logbook.Visualisation
+
+newtype Visualisations =
+  Visualisations
+    [Visualisation]
+  deriving (Eq, Ord, Show)
+    
+instance Monoid Visualisations where
+  mempty =
+    Visualisations []
+  Visualisations v1 `mappend` Visualisations v2 =
+    Visualisations (v1 `mappend` v2)
+       
+instance Markdown Visualisations where
+  markdown (Visualisations v) =
+    case v of
+      [] ->
+        ""
+      _ ->
+        "* **Visualisations**\n" ++ (v >>= \w -> "  * " ++ markdown w ++ "\n")
diff --git a/test/doctests.hs b/test/doctests.hs
new file mode 100644
--- /dev/null
+++ b/test/doctests.hs
@@ -0,0 +1,32 @@
+module Main where
+
+import Build_doctests (deps)
+import Control.Applicative
+import Control.Monad
+import Data.List
+import System.Directory
+import System.FilePath
+import Test.DocTest
+
+main ::
+  IO ()
+main =
+  getSources >>= \sources -> doctest $
+      "-isrc"
+    : "-idist/build/autogen"
+    : "-optP-include"
+    : "-optPdist/build/autogen/cabal_macros.h"
+    : "-hide-all-packages"
+    : map ("-package="++) deps ++ sources
+
+getSources :: IO [FilePath]
+getSources = filter (isSuffixOf ".hs") <$> go "src"
+  where
+    go dir = do
+      (dirs, files) <- getFilesAndDirectories dir
+      (files ++) . concat <$> mapM go dirs
+
+getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])
+getFilesAndDirectories dir = do
+  c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir
+  (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c
