diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, 2016, 2017, Konstantin Zudov
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Konstantin Zudov nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+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
+OWNER 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.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/comark-syntax.cabal b/comark-syntax.cabal
new file mode 100644
--- /dev/null
+++ b/comark-syntax.cabal
@@ -0,0 +1,32 @@
+-- This file has been generated from package.yaml by hpack version 0.17.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           comark-syntax
+version:        0.1.0
+synopsis:       Definitions of AST that represents a Commonmark (markdown) document.
+description:    See <https://github.com/zudov/haskell-comark#readme README>
+category:       Text
+author:         Konstantin Zudov
+maintainer:     co@zudov.me
+copyright:      (c) Konstantin Zudov, 2014, 2015, 2016, 2017
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+library
+  hs-source-dirs:
+      src/
+  other-extensions: DeriveDataTypeable DeriveGeneric
+  ghc-options: -Wall
+  build-depends:
+      base >=4.7 && <5.0
+    , containers
+    , deepseq
+  exposed-modules:
+      Comark.Syntax
+      Comark.Syntax.Builder
+  other-modules:
+      Paths_comark_syntax
+  default-language: Haskell2010
diff --git a/src/Comark/Syntax.hs b/src/Comark/Syntax.hs
new file mode 100644
--- /dev/null
+++ b/src/Comark/Syntax.hs
@@ -0,0 +1,180 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveFoldable     #-}
+{-# LANGUAGE DeriveFunctor      #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE DeriveTraversable  #-}
+{-# LANGUAGE FlexibleInstances  #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE ViewPatterns       #-}
+
+-- | A definition of Commonmark's AST
+
+module Comark.Syntax
+    ( Doc(..)
+    -- * Block Elements
+    , Blocks
+    , Block(..)
+    , HeadingLevel(..)
+    , ListType(..)
+    , Delimiter(..)
+    , BulletMarker(..)
+    -- * Inline Elements
+    , Inlines
+    , Inline(..)
+    , normalize
+    , asText
+    ) where
+
+import Control.DeepSeq (NFData)
+import Data.Data       (Data, Typeable)
+import Data.Monoid
+import Data.Sequence   (Seq, ViewL(..), viewl, (<|))
+import Data.String     (IsString(..))
+import GHC.Generics    (Generic)
+
+-- | A Document
+newtype Doc t = Doc (Blocks t)
+  deriving ( Show, Read, Eq
+           , Typeable, Data, Generic
+           , Functor, Foldable, Traversable
+           )
+
+instance NFData t => NFData (Doc t)
+
+instance Monoid (Doc t) where
+    mempty = Doc mempty
+    (Doc bs1) `mappend` (Doc bs2) = Doc (bs1 `mappend` bs2)
+
+type Blocks t = Seq (Block t)
+
+-- | Block elements
+data Block t
+  -- | Thematic break
+  = ThematicBreak
+  -- | Heading: level, sequnce of inlines that define content
+  | Heading HeadingLevel (Inlines t)
+  -- | Block of code: info string, literal content
+  | CodeBlock (Maybe t) t
+  -- | Raw HTML Block
+  | HtmlBlock t
+  -- | Paragraph (a grouped sequence of inlines)
+  | Para (Inlines t)
+  -- | Block Quote (a quoted sequence of blocks)
+  | Quote (Blocks t)
+  -- | List: Type of the list, tightness, a sequnce of blocks (list item)
+  | List ListType Bool (Seq (Blocks t))
+  deriving
+    ( Show, Read, Eq, Ord
+    , Typeable, Data, Generic
+    , Functor, Foldable, Traversable
+    )
+
+instance (NFData t) => NFData (Block t)
+
+data HeadingLevel
+  = Heading1
+  | Heading2
+  | Heading3
+  | Heading4
+  | Heading5
+  | Heading6
+  deriving
+    ( Show, Read, Eq, Ord
+    , Typeable, Data, Generic
+    )
+
+instance NFData HeadingLevel
+
+data ListType
+  = Ordered Delimiter Int
+  | Bullet BulletMarker
+  deriving
+    ( Show, Read, Eq, Ord
+    , Typeable, Data, Generic
+    )
+
+instance NFData ListType
+
+data Delimiter
+  = Period
+  | Paren
+  deriving
+    ( Show, Read, Eq, Ord
+    , Typeable, Data, Generic
+    )
+
+instance NFData Delimiter
+
+data BulletMarker
+  = Minus    -- ^ @-@
+  | Plus     -- ^ @+@
+  | Asterisk -- ^ @*@
+  deriving
+    ( Show, Read, Eq, Ord
+    , Typeable, Data, Generic
+    )
+
+instance NFData BulletMarker
+
+type Inlines t = Seq (Inline t)
+
+-- | Inline elements
+data Inline t
+  -- | Text (string)
+  = Str t
+  -- | Inline code
+  | Code t
+  -- | Emphasized text (a sequence of inlines)
+  | Emph (Inlines t)
+  -- | Strongly emphasized text (a sequence of inlines)
+  | Strong (Inlines t)
+  -- | Hyperlink: visible link text (sequence of inlines), destination, title
+  | Link (Inlines t) t (Maybe t) -- TODO: special types
+  -- | Image hyperlink: image description, destination, title
+  | Image (Inlines t) t (Maybe t) -- TODO: special types
+  -- | Inline Raw HTML tag
+  | RawHtml t
+  -- | A regular linebreak. A conforming renderer may render a soft
+  --   line break in HTML either as line break or as a space.
+  | SoftBreak
+  -- | A line break that is marked as hard (either with spaces or
+  --   backslash, see the spec for details). In html it would be rendered
+  --   as @<br />@
+  | HardBreak
+  deriving
+    ( Show, Read, Eq, Ord
+    , Typeable, Data, Generic
+    , Functor, Foldable, Traversable
+    )
+
+instance IsString t => IsString (Inline t) where
+  fromString = Str . fromString
+
+instance NFData t => NFData (Inline t)
+
+-- | Consolidate adjacent text nodes
+normalize :: Monoid t => Inlines t -> Inlines t
+normalize inlines =
+  case viewl inlines of
+    Str t       :< (viewl -> Str ts :< is) -> normalize (Str (t <> ts) <| is)
+    Image i u t :< is -> Image  (normalize i) u t  <| normalize is
+    Link i u t  :< is -> Link   (normalize i) u t  <| normalize is
+    Emph i      :< is -> Emph   (normalize i)      <| normalize is
+    Strong i    :< is -> Strong (normalize i)      <| normalize is
+    i           :< is -> i                         <| normalize is
+    EmptyL            -> mempty
+
+
+-- | Extract textual content from an inline.
+--   Note that it extracts only the 'primary' content (the one that is shown in
+--   first place). For example it wouldn't extract an URL from the link.
+asText :: (Monoid a, IsString a) => Inline a -> a
+asText (Str t)        = t
+asText (Emph is)      = foldMap asText is
+asText (Strong is)    = foldMap asText is
+asText (Code t)       = t
+asText (Link is _ _)  = foldMap asText is
+asText (Image is _ _) = foldMap asText is
+asText (RawHtml t)    = t
+asText SoftBreak      = " "
+asText HardBreak      = "\n"
diff --git a/src/Comark/Syntax/Builder.hs b/src/Comark/Syntax/Builder.hs
new file mode 100644
--- /dev/null
+++ b/src/Comark/Syntax/Builder.hs
@@ -0,0 +1,13 @@
+-- | Common AST-constructing functions
+
+module Comark.Syntax.Builder
+    ( str
+    ) where
+
+import Data.Sequence (singleton)
+
+import Comark.Syntax
+
+-- | A singleton string
+str :: a -> Inlines a
+str = singleton . Str
