diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Bardur Arantsson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#! /usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
diff --git a/cqrs-types.cabal b/cqrs-types.cabal
new file mode 100644
--- /dev/null
+++ b/cqrs-types.cabal
@@ -0,0 +1,37 @@
+Name:                cqrs-types
+Version:             0.9.0
+Synopsis:            Command-Query Responsibility Segregation. Modules for the basic types.
+Description:         Haskell implementation of the CQRS architectural pattern.
+License:             MIT
+License-file:        LICENSE
+Category:            Data
+Cabal-version:       >=1.10
+Build-type:          Simple
+Author:              Bardur Arantsson
+Maintainer:          Bardur Arantsson <bardur@scientician.net>
+
+Library
+  Build-Depends:       base == 4.*
+                     , base16-bytestring >= 0.1.1.3 && < 0.2
+                     , base64-bytestring >= 1 && < 2
+                     , bytestring >= 0.9.0.1
+                     , conduit >= 1.0 && < 2
+                     , deepseq >= 1.3 && < 2
+                     , derive >= 2.5.11 && < 2.6
+                     , random >= 1.0 && < 1.1
+  Default-language:    Haskell2010
+  Default-Extensions:
+                       DeriveDataTypeable
+                       DeriveFunctor
+                       FunctionalDependencies
+                       MultiParamTypeClasses
+                       Rank2Types
+                       TemplateHaskell
+  ghc-options:         -Wall
+  hs-source-dirs:      src
+  Exposed-modules:     Data.CQRS.Aggregate
+                       Data.CQRS.Eventable
+                       Data.CQRS.EventStore.Backend
+                       Data.CQRS.GUID
+                       Data.CQRS.PersistedEvent
+                       Data.CQRS.Serializable
diff --git a/src/Data/CQRS/Aggregate.hs b/src/Data/CQRS/Aggregate.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/Aggregate.hs
@@ -0,0 +1,10 @@
+-- | Aggregate type class.
+module Data.CQRS.Aggregate
+       ( Aggregate
+       ) where
+
+import Data.CQRS.Serializable
+
+-- | Type class for aggregates.
+class Serializable a => Aggregate a where
+    -- No functions at the current time.
diff --git a/src/Data/CQRS/EventStore/Backend.hs b/src/Data/CQRS/EventStore/Backend.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/EventStore/Backend.hs
@@ -0,0 +1,56 @@
+-- | Event store backend. You only need to import this
+-- module if you're planning on implementing a custom
+-- event store backend.
+module Data.CQRS.EventStore.Backend
+       ( EventStoreBackend(..)
+       , RawEvent
+       , RawSnapshot(..)
+       ) where
+
+import Data.ByteString (ByteString)
+import Data.Conduit (ResourceT, Source)
+import Data.CQRS.GUID
+import Data.CQRS.PersistedEvent (PersistedEvent)
+
+-- | Raw event type. The data associated with an event is not
+-- translated in any way.
+type RawEvent = PersistedEvent ByteString
+
+-- | Raw snapshot.
+data RawSnapshot =
+  RawSnapshot { rsVersion :: Int
+              , rsSnapshotData :: ByteString
+              }
+  deriving (Eq,Ord,Show)
+
+-- | Event stores are the backend used for reading and storing all the
+-- information about recorded events.
+class EventStoreBackend esb where
+    -- | Store a sequence of events for aggregate identified by GUID
+    -- into the event store, starting at the provided version number.
+    -- If the version number does not match the expected value, a
+    -- failure occurs.
+    esbStoreEvents :: esb -> GUID -> Int -> [RawEvent] -> IO ()
+    -- | Retrieve the sequence of events associated with the aggregate
+    -- identified by the given GUID. Only events at or after the given
+    -- version number are retrieved. The events are returned in
+    -- increasing order of version number.
+    esbRetrieveEvents :: esb -> GUID -> Int -> Source (ResourceT IO) RawEvent
+    -- | Enumerate all events. There is no guarantee on the ordering
+    -- of events /except/ that events for any specific aggregate root
+    -- are returned in order of version number.
+    esbEnumerateAllEvents :: esb -> Source (ResourceT IO) RawEvent
+    -- | Write snapshot for aggregate identified by GUID and
+    -- the given version number. The version number is NOT checked
+    -- for validity. If the event store does not support snapshots
+    -- this function may do nothing.
+    esbWriteSnapshot :: esb -> GUID -> RawSnapshot -> IO ()
+    -- | Get latest snapshot of an aggregate identified by GUID.
+    -- Returns the version number of the snapshot in addition to the
+    -- data. An event store which does not support snapshots is
+    -- permitted to return 'Nothing' in all cases.
+    esbGetLatestSnapshot :: esb -> GUID -> IO (Maybe RawSnapshot)
+    -- | Run transaction against the event store. The transaction is
+    -- expected to commit if the supplied IO action runs to completion
+    -- (i.e. doesn't throw an exception) and to rollback otherwise.
+    esbWithTransaction :: forall a . esb -> IO a -> IO a
diff --git a/src/Data/CQRS/Eventable.hs b/src/Data/CQRS/Eventable.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/Eventable.hs
@@ -0,0 +1,9 @@
+-- | Eventable type class.
+module Data.CQRS.Eventable
+       ( Eventable(..)
+       ) where
+
+-- | Type class for applying events to aggregates.
+class Eventable a e | a -> e where
+  -- | Apply an event to the aggregate and return the updated aggregate.
+  applyEvent :: Maybe a -> e -> Maybe a
diff --git a/src/Data/CQRS/GUID.hs b/src/Data/CQRS/GUID.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/GUID.hs
@@ -0,0 +1,81 @@
+-- | Globally Unique IDentifiers.
+module Data.CQRS.GUID
+       ( GUID
+       , fromByteString
+       , base64Decode
+       , base64Encode
+       , hexDecode
+       , hexEncode
+       , newGUID
+       , toByteString
+       ) where
+
+import           Control.DeepSeq (NFData(..))
+import           Data.ByteString (ByteString)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Base16 as B16
+import qualified Data.ByteString.Base64 as B64
+import           Data.ByteString.Char8 ()
+import           Data.Data (Data)
+import           Data.DeriveTH (derive, makeNFData)
+import           Data.Typeable (Typeable)
+import           Data.Word (Word8)
+import           System.Random (randomRIO)
+
+import           Data.CQRS.Serializable
+
+-- | A Globally Unique IDentifier.
+newtype GUID = GUID ByteString
+              deriving (Typeable, Eq, Ord, Data)
+
+-- | Get a random byte.
+randomWord8 :: IO Word8
+randomWord8 = fmap fromInteger $ randomRIO (0,255)
+
+-- | Create a new random GUID.
+newGUID :: IO GUID
+newGUID = do
+  uuid <- sequence $ replicate 16 randomWord8
+  return $ GUID $ B.pack uuid
+
+-- | Serialize instance.
+instance Serializable GUID where
+    serialize = toByteString
+    deserialize = Just . GUID
+
+-- | Hex encode a GUID.
+hexEncode :: GUID -> ByteString
+hexEncode (GUID s) = B16.encode s
+
+-- | Base64 encode a GUID.
+base64Encode :: GUID -> ByteString
+base64Encode (GUID s) = B64.encode s
+
+-- | Showing a GUID.
+instance Show GUID where
+    show = show . base64Encode
+
+-- | Decode a GUID from hex representation.
+hexDecode :: ByteString -> Maybe GUID
+hexDecode s =
+  case B16.decode s of
+    (a,b) | B.length b == 0 -> Just $ GUID a
+    _                       -> Nothing
+
+-- | Decode a GUID from base64 representation.
+base64Decode :: ByteString -> Maybe GUID
+base64Decode s =
+  case B64.decode s of
+    Right a -> Just $ GUID a
+    Left _  -> Nothing
+
+-- | Convert from ByteString.
+fromByteString :: ByteString -> GUID
+fromByteString = GUID
+
+-- | Convert to ByteString.
+toByteString :: GUID -> ByteString
+toByteString (GUID g) = g
+
+-- Instances
+$(derive makeNFData ''GUID)
diff --git a/src/Data/CQRS/PersistedEvent.hs b/src/Data/CQRS/PersistedEvent.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/PersistedEvent.hs
@@ -0,0 +1,17 @@
+module Data.CQRS.PersistedEvent
+       ( PersistedEvent(..)
+       ) where
+
+import Control.DeepSeq (NFData(..))
+import Data.CQRS.GUID (GUID)
+import Data.DeriveTH (derive, makeNFData)
+
+-- | Persisted Event.
+data PersistedEvent e =
+  PersistedEvent { peAggregateGUID :: !GUID -- ^ GUID of the aggregate.
+                 , peEvent :: !e            -- ^ Event.
+                 , peSequenceNumber :: !Int -- ^ Sequence number within the aggregate.
+                 }
+  deriving (Show, Eq, Ord, Functor)
+
+$(derive makeNFData ''PersistedEvent)
diff --git a/src/Data/CQRS/Serializable.hs b/src/Data/CQRS/Serializable.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/Serializable.hs
@@ -0,0 +1,20 @@
+-- | Serialization support. This is mainly used for compatibility
+-- with whatever serialization library you want to use.
+
+module Data.CQRS.Serializable
+    ( Serializable(..)
+    ) where
+
+import Data.ByteString (ByteString)
+
+-- | Serialization support for values of type 'a'.
+class Serializable a where
+    -- | Serialize a value. The serialized representation
+    -- should contain some metadata (a UUID for example)
+    -- which can be used to check reliably whether the encoded
+    -- representation is semantically valid upon decoding.
+    serialize :: a -> ByteString
+    -- | De-serialize a value from a byte string. Should return
+    -- 'Nothing' if decoding is not possible due to a now-invalid
+    -- representation.
+    deserialize :: ByteString -> Maybe a
