diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Revision history for pandoc-builder-monadic
+
+## 1.0.0
+
+* Add Text.Pandoc.Builder.Monadic.Utils
+* Add Text.Pandoc.Builder.Monadic.Veneer, which contains extra builders
+* Add Text.Pandoc.Builder.Monadic.Verbatim, which is a faithful monadic mirror of Text.Pandoc.Builder
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+BSD 3-Clause License
+
+Copyright (c) 2023, Owen Shepherd
+
+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 and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the copyright holder nor the names of its
+   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 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.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,27 @@
+# pandoc-builder-monadic
+
+
+[![CI status badge](https://img.shields.io/github/actions/workflow/status/414owen/pandoc-builder-monadic/haskell-ci.yml)](https://github.com/414owen/pandoc-builder-monadic/actions/workflows/haskell-ci.yml) [![license](https://img.shields.io/github/license/414owen/pandoc-builder-monadic)](https://github.com/414owen/pandoc-builder-monadic/blob/master/LICENSE)
+
+This library provides a monadic DSL for constructing Pandoc documents.
+
+## Usage
+
+```haskell
+{-# LANGUAGE OverloadedStrings #-}
+
+import Text.Pandoc.Builder.Monadic
+
+myDoc :: Pandoc
+myDoc = doc $ do
+  h1 "Hello, World!"
+  para $ do
+    str "Lorem ipsum "
+    () <- "dolor sit amet"
+    traverse (str . T.pack . show) [1..10 :: Int]
+    pure ()
+  para $ do
+    strong "Wow, such code!"
+    softbreak
+    "It's a " <> strong "monoid" <> " too" <> emph "'cos why not"
+```
diff --git a/pandoc-builder-monadic.cabal b/pandoc-builder-monadic.cabal
new file mode 100644
--- /dev/null
+++ b/pandoc-builder-monadic.cabal
@@ -0,0 +1,35 @@
+cabal-version:   2.2
+name:            pandoc-builder-monadic
+version:         1.0.0
+synopsis:        A monadic DSL for building pandoc documents
+description:     
+  A convenient way to build pandoc documents.
+  Supports all of the applicative and monadic utilities, and
+  reduces syntactic noise via do notation.
+homepage:        https://github.com/414owen/pandoc-builder-monadic
+license:         BSD-3-Clause
+license-file:    LICENSE
+author:          Owen Shepherd
+maintainer:      owen@owen.cafe
+category:        Text
+build-type:      Simple
+extra-source-files: README.md CHANGELOG.md
+tested-with:     GHC==9.6.2, GHC==9.4.5, GHC==9.2.8, GHC==8.0.2
+
+common warnings
+    ghc-options: -Wall -Wextra -Wunused-packages
+
+library
+    import:           warnings
+    exposed-modules:  Text.Pandoc.Builder.Monadic
+                    , Text.Pandoc.Builder.Monadic.Veneer
+                    , Text.Pandoc.Builder.Monadic.Verbatim
+                    , Text.Pandoc.Builder.Monadic.Utils
+                    , Text.Pandoc.Builder.Monadic.Internal
+    build-depends:    base >=4.9.0.0 && <5
+                    , dlist >=0.2 && <2
+                    , mtl >=1.1.0.0 && <3
+                    , pandoc-types >= 1.21 && < 2
+                    , text >=0.2 && <3
+    hs-source-dirs:   src
+    default-language: Haskell2010
diff --git a/src/Text/Pandoc/Builder/Monadic.hs b/src/Text/Pandoc/Builder/Monadic.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Builder/Monadic.hs
@@ -0,0 +1,197 @@
+{-# LANGUAGE CPP #-}
+
+{-|
+This module exports an API similar to pandoc-types' "Text.Pandoc.Builder", but
+with the `simple*` versions as the default versions, and with a few extras
+from "Text.Pandoc.Builder.Monadic.Veneer".
+
+In general, Builder.simple{a} becomes Builder.Monadic.{a} and Builder.{a}
+becomes Builder.Monadic.{a}'.
+
+If you want to match the "Text.Pandoc.Builder" API more precisely, you can use
+"Text.Pandoc.Builder.Monadic.Verbatim" instead.
+-}
+
+module Text.Pandoc.Builder.Monadic
+  (
+  -- * Monadic element builder
+    Builder
+
+  -- * Pandoc element types
+  , module Text.Pandoc.Definition
+
+  -- * Top-level
+  , doc
+  , setTitle
+  , setAuthors
+  , setDate
+  , setMeta
+
+  -- * Inline builders
+  , text
+  , str
+  , strshow
+  , emph
+  , underline
+  , strong
+  , strikeout
+  , superscript
+  , subscript
+  , smallcaps
+  , singleQuoted
+  , doubleQuoted
+  , cite
+  , code
+  , codeWith
+  , space
+  , softbreak
+  , linebreak
+  , math
+  , displayMath
+  , rawInline
+  , link
+  , linkWith
+  , image
+  , imageWith
+  , note
+  , spanWith
+  , trimInlines
+
+  -- * Block builders
+  , h1
+  , h2
+  , h3
+  , h4
+  , h5
+
+  , para
+  , plain
+  , div'
+  , span'
+  , lineBlock
+  , codeBlockWith
+  , codeBlock
+  , rawBlock
+  , blockQuote
+  , bulletList
+  , orderedListWith
+  , orderedList
+  , definitionList
+  , header
+  , headerWith
+  , horizontalRule
+  , cell
+  , cell'
+  , emptyCell
+  , cellWith
+  , table
+  , table'
+  , tableWithColspec
+  , tableWith
+  , tableWith'
+#if MIN_VERSION_pandoc_types(1,23,0)
+  , figure
+  , figureWith
+#endif
+  , caption
+  , caption'
+  , emptyCaption
+#if MIN_VERSION_pandoc_types(1,22,1)
+  , imgFigure
+  , imgFigureWith
+#endif
+  , divWith
+
+  -- * Table processing
+  , normalizeTableHead
+  , normalizeTableBody
+  , normalizeTableFoot
+  , placeRowSection
+  , clipRows
+  ) where
+
+import Text.Pandoc.Definition
+import Data.Text                            (Text)
+import Text.Pandoc.Builder.Monadic.Verbatim hiding
+  ( simpleCell, cell, table, simpleTable
+  , caption, simpleCaption
+#if MIN_VERSION_pandoc_types(1,22,1)
+  , simpleFigure
+  , simpleFigureWith
+#endif
+  , tableWith
+  )
+import Text.Pandoc.Builder.Monadic.Internal (tellOne, runToList)
+import Text.Pandoc.Builder.Monadic.Veneer
+
+import qualified Text.Pandoc.Builder.Monadic.Verbatim as V
+
+-- | Build a 1x1 cell with default alignment, given some pandoc.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.simpleCell'.
+cell :: Builder Block -> Cell
+cell = V.simpleCell
+
+-- | Build a cell of a table, full API excluding attributes.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.cell'.
+cell' :: Alignment -> RowSpan -> ColSpan -> Builder Block -> Cell
+cell' = V.cell
+
+-- | Build a table, given a list of header cells, and a list of rows.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.simpleTable'.
+table :: [Builder Block] -> [[Builder Block]] -> Builder Block
+table = V.simpleTable
+
+-- | Build a table, given attributes, a list of header cells, and a list of rows.
+-- This is equivalent to 'Text.Pandoc.Builder.Monadic.Verbatim.simpleTable' with
+-- attributes.
+tableWith :: Attr -> [Builder Block] -> [[Builder Block]] -> Builder Block
+tableWith attr headings body =
+  case runToList $ table headings body of
+    [Table _ a b c d e] -> tellOne $ Table attr a b c d e
+    _ -> error "Invariant broken. Table builder didn't return one element."
+
+-- | Build a table, full API excluding attributes.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.table'.
+table'
+  :: Caption
+  -> [ColSpec]
+  -> TableHead
+  -> [TableBody]
+  -> TableFoot
+  -> Builder Block
+table' = V.table
+
+-- | Build a table, full API including attributes.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.tableWith'.
+tableWith'
+  :: Attr
+  -> Caption
+  -> [ColSpec]
+  -> TableHead
+  -> [TableBody]
+  -> TableFoot
+  -> Builder Block
+tableWith' = V.tableWith
+
+-- | Make a caption, without a short version.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.simpleCaption'.
+caption :: Builder Block -> Caption
+caption = V.simpleCaption
+
+-- | Make a caption, with an optional short version.
+-- Same as 'Text.Pandoc.Builder.Monadic.Verbatim.caption'.
+caption' :: Maybe ShortCaption -> Builder Block -> Caption
+caption' = V.caption
+
+#if MIN_VERSION_pandoc_types(1,22,1)
+-- | Build a captioned figure, containing an image.
+-- This is available in pandoc-types >= 1.22.1, which corresponds to pandoc >= 2.15.
+imgFigure :: Builder Inline -> Text -> Text
+                  -> Builder Block
+imgFigure = V.simpleFigure
+
+-- | Build a captioned figure containing an image, with attributes.
+-- This is available in pandoc-types >= 1.22.1, which corresponds to pandoc >= 2.15.
+imgFigureWith :: Attr -> Builder Inline -> Text -> Text -> Builder Block
+imgFigureWith = V.simpleFigureWith
+#endif
diff --git a/src/Text/Pandoc/Builder/Monadic/Internal.hs b/src/Text/Pandoc/Builder/Monadic/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Builder/Monadic/Internal.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+{-|
+Internal module, exposing the Builder(..) type, you should
+prefer using 'Text.Pandoc.Builder.Monadic.Utils.mapBuilder',
+or adding something to 'Text.Pandoc.Builder.Monadic.Utils'.
+-}
+
+module Text.Pandoc.Builder.Monadic.Internal
+  ( BuilderM(..)
+  , Builder
+  , buildMany
+  , runToList
+  , runToDList
+  , runToMany
+  , tellOne
+  , tellAll
+  ) where
+
+import Control.Monad.Writer.Strict (Writer, execWriter, tell)
+import Data.DList                  (DList)
+import Data.Foldable               (traverse_)
+import Text.Pandoc.Builder         (Inline)
+#if __GLASGOW_HASKELL__ < 804
+import Data.Semigroup
+#endif
+
+import qualified Text.Pandoc.Builder         as B
+import qualified Data.DList                  as DList
+
+-- | The pandoc element builder type. It wraps a writer monad.
+-- Chances are, you only need t'Builder' (a 'BuilderM el ()').
+-- All builders in this library have an `el` type in the set
+-- {'B.Inline', 'B.Block'}.
+newtype BuilderM el a = Builder { unBuilder :: Writer (DList el) a }
+
+-- | Pandoc element builder. Stores written pandoc elements.
+type Builder el = BuilderM el ()
+
+instance Functor (BuilderM el) where
+  fmap f = Builder . fmap f . unBuilder
+
+instance Applicative (BuilderM el) where
+  pure a = Builder $ pure a
+  Builder f <*> Builder a = Builder $ f <*> a
+
+instance Monad (BuilderM el) where
+  Builder a >>= f = Builder $ do
+    a' <- a
+    unBuilder $ f a'
+
+instance Semigroup (BuilderM el a) where
+  Builder a <> Builder b = Builder $ a >> b
+
+instance Monoid a => Monoid (BuilderM el a) where
+  mempty = Builder $ pure mempty
+
+instance B.ToMetaValue (Builder Inline) where
+  toMetaValue = B.MetaInlines . runToList
+
+-- | Useful for setting authors
+instance B.ToMetaValue (Builder (Builder Inline)) where
+  toMetaValue = B.MetaList . map B.toMetaValue . runToList
+
+-- | Get elements written in the t'Builder' as a difference list
+runToDList :: Builder el -> DList el
+runToDList = execWriter . unBuilder
+
+-- | Get elements written in the t'Builder' as a list
+runToList :: Builder el -> [el]
+runToList = DList.toList . runToDList
+
+-- | Get elements written in a t'Builder' as a 'B.Many'.
+-- This might be useful if you need to interact with pandoc-types.
+runToMany :: Builder a -> B.Many a
+runToMany = B.fromList . DList.toList . execWriter . unBuilder
+
+-- | Get pandoc-types' 'B.Many' as a t'Builder'.
+buildMany :: B.Many a -> Builder a
+buildMany = Builder . traverse_ (tell . pure)
+
+-- | Write a single element to a t'Builder'.
+tellOne :: a -> Builder a
+tellOne = Builder . tell . DList.singleton
+
+-- | Write multiple element to a t'Builder'.
+tellAll :: DList a -> Builder a
+tellAll = Builder . tell
diff --git a/src/Text/Pandoc/Builder/Monadic/Utils.hs b/src/Text/Pandoc/Builder/Monadic/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Builder/Monadic/Utils.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{-|
+Utility functions for working with builders, and constructed pandoc ASTs
+-}
+
+module Text.Pandoc.Builder.Monadic.Utils
+  ( mapBuilder
+  , intersperseTablesWithBlankRows
+  , vspace
+  ) where
+
+import Data.List                            (intersperse)
+import Text.Pandoc.Builder.Monadic.Internal (tellAll, runToDList)
+import Text.Pandoc.Builder.Monadic.Verbatim hiding (caption)
+
+-- | Map every element written in a t'Builder'.
+-- This is useful if you have laid out bespoke elements, such as
+-- 
+-- > mapBuilder boldStrings $ do
+-- >   div "lorem ipsum "
+-- >   str "dolor sit amet"
+-- >
+-- > boldStrings s@(Str _) = Strong s
+-- > boldStrings a = a
+--
+-- It's also useful for creating custom pandoc builders.
+-- See 'Text.Pandoc.Builder.Monadic.Veneer.tableWithColspec'.
+mapBuilder :: (a -> b) -> Builder a -> Builder b
+mapBuilder f = tellAll . fmap f . runToDList
+
+-- | Intersperse table with blank rows, this is useful for
+-- clarity (with some backends) when using multiline cells.
+-- This is exposed as a modifier, because there are already
+-- too many ways to construct a table.
+intersperseTablesWithBlankRows :: Builder Block -> Builder Block
+intersperseTablesWithBlankRows = mapBuilder updateBlock
+  where
+    updateBlock :: Block -> Block
+    updateBlock block = case block of
+      Table attr caption colspec tableHead tableBodies tableFoot ->
+        Table attr caption colspec tableHead (updateBody <$> tableBodies) tableFoot
+      a -> a
+
+    updateBody :: TableBody -> TableBody
+    updateBody (TableBody attr rowHeadCols headRows rows)
+      = TableBody attr rowHeadCols headRows $ intersperse blankRow rows
+
+    blankRow :: Row
+    blankRow = Row nullAttr mempty
+
+-- | Vertical space - a paragraph containing a non-breaking space
+vspace :: Builder Block
+vspace = para "\x00A0"
diff --git a/src/Text/Pandoc/Builder/Monadic/Veneer.hs b/src/Text/Pandoc/Builder/Monadic/Veneer.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Builder/Monadic/Veneer.hs
@@ -0,0 +1,72 @@
+{-|
+This module exports extra convenient builders, that don't have equivalents
+in pandoc-types' Text.Pandoc.Builder.
+-}
+
+module Text.Pandoc.Builder.Monadic.Veneer
+  (
+  -- * Block list builders
+    div'
+  , span'
+  , h1
+  , h2
+  , h3
+  , h4
+  , h5
+  , tableWithColspec
+  , strshow
+  ) where
+
+import Text.Pandoc.Builder.Monadic.Verbatim
+  ( Builder, Inline(..), Block(..), ColSpec, header, simpleTable
+  , divWith, spanWith, nullAttr, str
+  )
+import Text.Pandoc.Builder.Monadic.Utils
+
+import qualified Data.Text as T
+
+-- | Build a level 1 header.
+h1 :: Builder Inline -> Builder Block
+h1 = header 1
+
+-- | Build a level 2 header.
+h2 :: Builder Inline -> Builder Block
+h2 = header 2
+
+-- | Build a level 3 header.
+h3 :: Builder Inline -> Builder Block
+h3 = header 3
+
+-- | Build a level 4 header.
+h4 :: Builder Inline -> Builder Block
+h4 = header 4
+
+-- | Build a level 5 header.
+h5 :: Builder Inline -> Builder Block
+h5 = header 5
+
+-- | Colspans seem to be quite important for controlling
+-- table layout, so much so that a version of
+-- `Builder.SimpleTable` which takes a [ColSpan] seemed
+-- in order.
+tableWithColspec :: [ColSpec] -> [Builder Block] -> [[Builder Block]] -> Builder Block
+tableWithColspec colspec headers rows = mapBuilder f $ simpleTable headers rows
+  where
+    f :: Block -> Block
+    f (Table attr caption _ tableHead tableBodies tableFoot)
+      = Table attr caption colspec tableHead tableBodies tableFoot
+    f a = a
+
+-- | Build a generic block container.
+-- This would be named 'div', but that clashes with prelude's 'div'.
+div' :: Builder Block -> Builder Block
+div' = divWith nullAttr
+
+-- | Build a generic inline container.
+-- This would be named 'span', but that clashes with prelude's 'span'.
+span' :: Builder Inline -> Builder Inline
+span' = spanWith nullAttr
+
+-- | Build a v'Str' using a values's `Show` instance.
+strshow :: Show a => a -> Builder Inline
+strshow = str . T.pack . show
diff --git a/src/Text/Pandoc/Builder/Monadic/Verbatim.hs b/src/Text/Pandoc/Builder/Monadic/Verbatim.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Builder/Monadic/Verbatim.hs
@@ -0,0 +1,425 @@
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- We define some instances for Builder here, because this is where we
+-- have functions to implement them.
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+-- We use named parameters as a form of documentation.
+{- HLINT ignore "Eta reduce" -}
+
+-- | This module exports a 1:1 monadic version of pandoc-types' 'Text.Pandoc.Builder'.
+
+module Text.Pandoc.Builder.Monadic.Verbatim
+  ( module Text.Pandoc.Definition
+  , Builder
+  , URL
+  , Title
+  , Raw
+
+  -- * Top-level
+  , doc
+  , setTitle
+  , setAuthors
+  , setDate
+  , setMeta
+
+  -- * Inline builders
+  , text
+  , str
+  , emph
+  , underline
+  , strong
+  , strikeout
+  , superscript
+  , subscript
+  , smallcaps
+  , singleQuoted
+  , doubleQuoted
+  , cite
+  , code
+  , codeWith
+  , space
+  , softbreak
+  , linebreak
+  , math
+  , displayMath
+  , rawInline
+  , link
+  , linkWith
+  , image
+  , imageWith
+  , note
+  , spanWith
+  , trimInlines
+
+  -- * Block builders
+  , para
+  , plain
+  , lineBlock
+  , codeBlockWith
+  , codeBlock
+  , rawBlock
+  , blockQuote
+  , bulletList
+  , orderedListWith
+  , orderedList
+  , definitionList
+  , header
+  , headerWith
+  , horizontalRule
+  , cell
+  , simpleCell
+  , emptyCell
+  , cellWith
+  , table
+  , simpleTable
+  , tableWith
+#if MIN_VERSION_pandoc_types(1,23,0)
+  , figure
+  , figureWith
+#endif
+  , caption
+  , simpleCaption
+  , emptyCaption
+#if MIN_VERSION_pandoc_types(1,22,1)
+  , simpleFigureWith
+  , simpleFigure
+#endif
+  , divWith
+
+  -- * Table processing
+  , B.normalizeTableHead
+  , B.normalizeTableBody
+  , B.normalizeTableFoot
+  , B.placeRowSection
+  , B.clipRows
+  ) where
+
+import Control.Arrow               ((***))
+import Data.Text                   (Text)
+
+import Text.Pandoc.Definition
+import Data.String (IsString(..))
+
+import Text.Pandoc.Builder.Monadic.Internal
+  ( Builder
+  , buildMany
+  , runToMany
+  , runToList
+  , tellOne
+  )
+
+import qualified Data.Text           as Text
+import qualified Text.Pandoc.Builder as B
+
+-- | Type alias for raw output.
+type Raw = Text
+
+-- | Type alias for URLs.
+type URL = Text
+
+-- | Type alias for Titles.
+type Title = Text
+
+instance IsString (Builder Inline) where
+  fromString = str . Text.pack
+
+instance IsString (Builder Block) where
+  fromString = plain . str . Text.pack
+
+-- | Lifts something (usually a Pandoc data constructor), into
+-- a builder which takes a builder.
+liftWrapper :: ([a] -> b) -> Builder a -> Builder b
+liftWrapper f = tellOne . f . runToList
+
+liftWrapper' :: (B.Many a -> B.Many b) -> Builder a -> Builder b
+liftWrapper' f = buildMany . f . runToMany
+
+-- | Build a pandoc document from a 'Builder' of top-level elements.
+doc :: Builder Block -> Pandoc
+doc = B.Pandoc mempty . runToList
+
+-- | Set the document's title in the metadata.
+setTitle :: Builder Inline -> Pandoc -> Pandoc
+setTitle = B.setTitle . runToMany
+
+-- | Set the document's authors in the metadata.
+setAuthors :: [Builder Inline] -> Pandoc -> Pandoc
+setAuthors = B.setAuthors . fmap runToMany
+
+-- | Set the document's date in the metadata.
+setDate :: Builder Inline -> Pandoc -> Pandoc
+setDate = B.setDate . runToMany
+
+-- | Set a value in the document's metadata.
+setMeta :: (B.HasMeta a, B.ToMetaValue b) => Text -> b -> a -> a 
+setMeta = B.setMeta
+
+-- | Convert a 'Text' to a 'Builder' 'Inline', treating interword spaces as 'B.Space's
+-- or 'B.SoftBreak's. If you want a 'B.Str' with literal spaces, use 'str'.
+text :: Text -> Builder Inline
+text = buildMany . B.text
+
+-- | Build a string.
+str :: Text -> Builder Inline
+str = tellOne . B.Str
+
+-- | Build an emphasized (usually italicized) inline.
+emph :: Builder Inline -> Builder Inline
+emph = liftWrapper B.Emph
+
+-- | Build an underlined inline.
+underline :: Builder Inline -> Builder Inline
+underline = liftWrapper B.Underline
+
+-- | Build a strong (bold) inline.
+strong :: Builder Inline -> Builder Inline
+strong = liftWrapper B.Strong
+
+-- | Build a strikeout (crossed out) inline.
+strikeout :: Builder Inline -> Builder Inline
+strikeout = liftWrapper B.Strikeout
+
+-- | Build a superscripted inline.
+superscript :: Builder Inline -> Builder Inline
+superscript = liftWrapper B.Superscript
+
+-- | Build a subscripted inline.
+subscript :: Builder Inline -> Builder Inline
+subscript = liftWrapper B.Subscript
+
+-- | Build a smallcaps inline. See the example in the font-family [MDN page](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant#examples).
+smallcaps :: Builder Inline -> Builder Inline
+smallcaps = liftWrapper B.SmallCaps
+
+-- | Build a single-quoted inline.
+singleQuoted :: Builder Inline -> Builder Inline
+singleQuoted = liftWrapper $ B.Quoted B.SingleQuote
+
+-- | Build a double-quoted inline.
+doubleQuoted :: Builder Inline -> Builder Inline
+doubleQuoted = liftWrapper $ B.Quoted B.DoubleQuote
+
+-- | Build a citation. See
+-- [Citations in note style](https://pandoc.org/chunkedhtml-demo/9.3-citations-in-note-styles.html)
+-- and [Specifying a citation style](https://pandoc.org/chunkedhtml-demo/9.2-specifying-a-citation-style.html).
+cite :: [B.Citation] -> Builder Inline -> Builder Inline
+cite citations = liftWrapper $ B.Cite citations
+
+-- | Build some inline code.
+code :: Text -> Builder Inline
+code = codeWith B.nullAttr
+
+-- | Build some inline code with attributes.
+codeWith :: B.Attr -> Text -> Builder Inline
+codeWith = (tellOne .) . B.Code
+
+-- | Build an inter-word space.
+space :: Builder Inline
+space = tellOne B.Space
+
+-- | Build a soft line-break.
+softbreak :: Builder Inline
+softbreak = tellOne B.SoftBreak
+
+-- | Build a hard line-break.
+linebreak :: Builder Inline
+linebreak = tellOne B.LineBreak
+
+-- | Build some inline TeX math.
+math :: Text -> Builder Inline
+math = tellOne . B.Math B.InlineMath
+
+-- | Build some display-mode TeX math.
+-- Display mode is for math that is set apart from the main text.
+displayMath :: Text -> Builder Inline
+displayMath = tellOne . B.Math B.DisplayMath
+
+-- | Embed some of the output directly.
+-- This is useful to gain access to features of the underlying
+-- output which aren't supported by pandoc directly.
+rawInline :: Format -> Raw -> Builder Inline
+rawInline format = tellOne . B.RawInline format
+
+-- | Build a link from a URL, a title, and some inline pandoc.
+link :: URL -> Title -> Builder Inline -> Builder Inline
+link url title = linkWith B.nullAttr url title
+
+-- | Build a link from some attributes, a URL, a title, and some inline pandoc.
+linkWith :: B.Attr -> URL -> Title -> Builder Inline -> Builder Inline
+linkWith attr url title x = tellOne $ B.Link attr (runToList x) (url, title)
+
+-- | Build an image from a URL, a title, and some inline pandoc.
+image :: URL -> Title -> Builder Inline -> Builder Inline
+image url title = imageWith B.nullAttr url title
+
+-- | Build an image from some attributes, a URL, a title, and some inline pandoc.
+imageWith :: B.Attr -> Text -> Text -> Builder Inline -> Builder Inline
+imageWith attr url title x = tellOne $ B.Image attr (runToList x) (url, title)
+
+-- | Build a footnote or endnote from some pandoc blocks.
+note :: Builder B.Block -> Builder Inline
+note = liftWrapper B.Note
+
+-- | Build a generic inline container from attributes and more inline pandoc.
+spanWith :: B.Attr -> Builder Inline -> Builder Inline
+spanWith attr = liftWrapper $ B.Span attr
+
+-- | Trim leading and trailing spaces and softbreaks from some inline pandoc.
+trimInlines :: Builder Inline -> Builder Inline
+trimInlines = liftWrapper' B.trimInlines
+
+-- Block list builders
+
+-- | Build a paragraph.
+para :: Builder Inline -> Builder Block
+para = liftWrapper B.Para
+
+-- | Build some plain text (not a paragraph).
+plain :: Builder Inline -> Builder Block
+plain = liftWrapper' B.plain
+
+-- | Build multiple non-breaking lines.
+lineBlock :: [Builder Inline] -> Builder Block
+lineBlock = tellOne . B.LineBlock . fmap runToList
+
+-- | Build a code block.
+codeBlock :: Text -> Builder Block
+codeBlock = codeBlockWith B.nullAttr
+
+-- | Build a code block with attributes.
+codeBlockWith :: B.Attr -> Text -> Builder Block
+codeBlockWith attrs = tellOne . B.CodeBlock attrs
+
+-- | Embed some of the output directly.
+-- This is useful to gain access to features of the underlying
+-- output which aren't supported by pandoc directly.
+rawBlock :: Format -> Raw -> Builder Block
+rawBlock format = tellOne . B.RawBlock format
+
+-- | Build a block quote.
+blockQuote :: Builder Block -> Builder Block
+blockQuote = liftWrapper B.BlockQuote
+
+-- | Build an ordered list.
+orderedList :: [Builder Block] -> Builder Block
+orderedList = orderedListWith (1, B.DefaultStyle, B.DefaultDelim)
+
+-- | Build an ordered list with attributes.
+orderedListWith :: B.ListAttributes -> [Builder Block] -> Builder Block
+orderedListWith attrs = tellOne . B.OrderedList attrs . fmap runToList
+
+-- | Build a bullet list.
+bulletList :: [Builder Block] -> Builder Block
+bulletList = tellOne . B.BulletList . fmap runToList
+
+-- | Build an definition list given a list of tuples, where the first element
+-- of each tuple is a term, and the second element is the definition.
+definitionList :: [(Builder Inline, [Builder Block])] -> Builder Block
+definitionList = tellOne . B.DefinitionList . fmap (runToList *** fmap runToList)
+
+-- | Build a header, given a level and some inline pandoc.
+-- You may consider using 'Text.Pandoc.Builder.Monadic.h1' and friends,
+-- for a more concise API.
+header :: Int -> Builder Inline -> Builder Block
+header level x = headerWith B.nullAttr level x
+
+-- | Build a header from some attributes, a level and some inline pandoc.
+headerWith :: B.Attr -> Int -> Builder Inline -> Builder Block
+headerWith attr level = liftWrapper $ B.Header level attr
+
+-- | Build a horizontal rule.
+horizontalRule :: Builder Block
+horizontalRule = tellOne B.HorizontalRule
+
+-- | Build a 1x1 cell with default alignment, given some pandoc.
+simpleCell :: Builder Block -> B.Cell
+simpleCell = cell B.AlignDefault 1 1
+
+-- | Build a cell of a table, full API excluding attributes.
+cell
+  :: B.Alignment
+  -> B.RowSpan
+  -> B.ColSpan
+  -> Builder Block
+  -> B.Cell
+cell = cellWith B.nullAttr
+
+-- | Build a cell of a table, full API including attributes.
+cellWith
+  :: B.Attr
+  -> B.Alignment
+  -> B.RowSpan
+  -> B.ColSpan
+  -> Builder Block
+  -> B.Cell
+cellWith attrs align rowspan colspan = B.Cell attrs align rowspan colspan . runToList
+
+-- | Build a 1x1 empty cell.
+emptyCell :: B.Cell
+emptyCell = simpleCell $ pure ()
+
+-- | Build a table, full API excluding attributes.
+table :: B.Caption
+      -> [B.ColSpec]
+      -> B.TableHead
+      -> [B.TableBody]
+      -> B.TableFoot
+      -> Builder Block
+table = tableWith B.nullAttr
+
+-- | Build a table, full API including attributes.
+tableWith :: B.Attr
+          -> B.Caption
+          -> [B.ColSpec]
+          -> B.TableHead
+          -> [B.TableBody]
+          -> B.TableFoot
+          -> Builder Block
+tableWith = (((((buildMany .) .) .) .) .) . B.tableWith
+
+-- | Build a table, given a list of header cells, and a list of rows.
+simpleTable :: [Builder Block] -> [[Builder Block]] -> Builder Block
+simpleTable headers rows = buildMany $ B.simpleTable (fmap runToMany headers) (fmap runToMany <$> rows)
+
+#if MIN_VERSION_pandoc_types(1,23,0)
+-- | Build a captioned figure.
+-- This is available in pandoc-types >= 1.23, which corresponds to pandoc >= 3.0.
+figure :: B.Caption -> Builder Block -> Builder Block
+figure = figureWith B.nullAttr
+
+-- | Build a captioned figure, with attributes.
+-- This is available in pandoc-types >= 1.23, which corresponds to pandoc >= 3.0.
+figureWith :: B.Attr -> B.Caption -> Builder Block -> Builder Block
+figureWith attr capt = liftWrapper $ B.Figure attr capt
+#endif
+
+-- | Make a caption, with an optional short version.
+caption :: Maybe B.ShortCaption -> Builder Block -> B.Caption
+caption x = B.Caption x . runToList
+
+-- | Make a caption, without a short version.
+simpleCaption :: Builder Block -> B.Caption
+simpleCaption = caption Nothing
+
+-- | Make an empty caption
+emptyCaption :: B.Caption
+emptyCaption = simpleCaption mempty
+
+#if MIN_VERSION_pandoc_types(1,22,1)
+-- | Build a captioned figure, containing an image.
+-- This is available in pandoc-types >= 1.22.1, which corresponds to pandoc >= 2.15.
+simpleFigure :: Builder Inline -> Text -> Text -> Builder Block
+simpleFigure figureCaption url title = simpleFigureWith B.nullAttr figureCaption url title
+
+-- | Build a captioned figure containing an image, with attributes.
+-- This is available in pandoc-types >= 1.22.1, which corresponds to pandoc >= 2.15.
+simpleFigureWith :: B.Attr -> Builder Inline -> URL -> Title-> Builder Block
+simpleFigureWith attr figureCaption url title
+  = buildMany $ B.simpleFigureWith attr (runToMany figureCaption) url title
+#endif
+
+-- | Build a generic block container with attributes.
+divWith :: B.Attr -> Builder Block -> Builder Block
+divWith attr = liftWrapper $ B.Div attr
