diff --git a/LICENCE b/LICENCE
deleted file mode 100644
--- a/LICENCE
+++ /dev/null
@@ -1,32 +0,0 @@
-Publishing tools for papers, books, and presentations
-
-Copyright © 2016-2018 Operational Dynamics Consulting, Pty Ltd and Others
-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 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 project 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
-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/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright © 2016-2019 Operational Dynamics and Others
+
+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/publish.cabal b/publish.cabal
--- a/publish.cabal
+++ b/publish.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.31.1.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 547ada31362d64dd2c988a4b125cd34de323ad166da373e7cec366b84f9b4352
+-- hash: 001dfdaebed2195690eab746f62b3674eb4439f4f1bec491329118c1033da4bc
 
 name:           publish
-version:        2.0.1
+version:        2.1.0
 synopsis:       Publishing tools for papers, books, and presentations
 description:    Tools for rendering markdown-centric documents into PDFs.
                 .
@@ -24,9 +24,9 @@
 bug-reports:    https://github.com/oprdyn/publish/issues
 author:         Andrew Cowie <andrew@operationaldynamics.com>
 maintainer:     Andrew Cowie <andrew@operationaldynamics.com>
-copyright:      © 2016-2019 Operational Dynamics Consulting Pty Ltd, and Others
-license:        BSD3
-license-file:   LICENCE
+copyright:      © 2016-2019 Operational Dynamics and Others
+license:        MIT
+license-file:   LICENSE
 tested-with:    GHC == 8.6
 build-type:     Simple
 
@@ -46,6 +46,8 @@
       base >=4.11 && <5
     , bytestring
     , chronologique
+    , core-program >=0.2.2.3
+    , core-text >=0.2.2.3
     , deepseq
     , directory
     , filepath
@@ -56,7 +58,6 @@
     , template-haskell
     , text
     , typed-process
-    , unbeliever >=0.9.3.2
     , unix
     , unordered-containers
   default-language: Haskell2010
@@ -66,7 +67,6 @@
   other-modules:
       Environment
       LatexPreamble
-      NotifyChanges
       LatexOutputReader
       PandocToMarkdown
       ParseBookfile
@@ -79,6 +79,8 @@
       base >=4.11 && <5
     , bytestring
     , chronologique
+    , core-program >=0.2.2.3
+    , core-text >=0.2.2.3
     , deepseq
     , directory
     , filepath
@@ -89,7 +91,6 @@
     , template-haskell
     , text
     , typed-process
-    , unbeliever >=0.9.3.2
     , unix
     , unordered-containers
   default-language: Haskell2010
@@ -113,6 +114,8 @@
       base >=4.11 && <5
     , bytestring
     , chronologique
+    , core-program >=0.2.2.3
+    , core-text >=0.2.2.3
     , deepseq
     , directory
     , filepath
@@ -124,7 +127,6 @@
     , template-haskell
     , text
     , typed-process
-    , unbeliever >=0.9.3.2
     , unix
     , unordered-containers
   default-language: Haskell2010
diff --git a/src/Environment.hs b/src/Environment.hs
--- a/src/Environment.hs
+++ b/src/Environment.hs
@@ -25,4 +25,5 @@
     { versionFrom :: Int
     , preamblesFrom :: [FilePath]
     , fragmentsFrom :: [FilePath]
+    , trailersFrom :: [FilePath]
     } deriving (Show, Eq)
diff --git a/src/NotifyChanges.hs b/src/NotifyChanges.hs
deleted file mode 100644
--- a/src/NotifyChanges.hs
+++ /dev/null
@@ -1,73 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module NotifyChanges
-(
-    waitForChange
-)
-where
-
-import Core.Program
-import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar)
-import qualified Data.ByteString.Char8 as C (ByteString, pack)
-import Data.Foldable (foldr, foldrM)
-import Data.HashSet (HashSet)
-import qualified Data.HashSet as HashSet (empty, insert, member)
-import System.FilePath.Posix (dropFileName)
-import System.INotify (EventVariety(..), Event(..), withINotify
-    , addWatch, removeWatch)
-
-{-
-Ideally we'd just set up inotifies on individual files we have manifested
-from the .book file, but that doesn't work when programs like vim move the
-original file, save a new one, then delete the renamed original. From
-previous work we know that CLOSE_WRITE is emitted reliably through these
-sequences, so we can just check to see if a that happens on a filename we
-care about (rather then the original inodes those files were stored in).
-
-Insert a 100ms pause before rebuilding to allow whatever the editor
-was to finish its write and switcheroo sequence.
--}
-waitForChange :: [FilePath] -> Program t ()
-waitForChange files =
-  let
-    f :: FilePath -> HashSet C.ByteString -> HashSet C.ByteString
-    f path acc = HashSet.insert (C.pack path) acc
-
-    g :: FilePath -> HashSet C.ByteString -> HashSet C.ByteString
-    g path acc = HashSet.insert (C.pack (dropFileName path)) acc
-  in do
-    event "Watching for changes"
-
-    let paths = foldr f HashSet.empty files
-    let dirs  = foldr g HashSet.empty files
-
-    withContext $ \runProgram -> do
-        block <- newEmptyMVar
-        withINotify $ \notify -> do
-            -- setup inotifies
-            watches <- foldrM (\dir acc -> do
-                runProgram (debugS "watching" dir)
-                watch <- addWatch notify [CloseWrite] dir (\trigger ->
-                    case trigger of
-                        Closed _ (Just file) _  -> do
-                            let path = if dir == "./"
-                                        then file
-                                        else dir <> file
-                            runProgram (debugS "changed" path)
-                            if HashSet.member path paths
-                                then do
-                                    runProgram (debugS "trigger" path)
-                                    putMVar block False
-                                else
-                                    return ()
-                        _ -> return ())
-                return (watch:acc)) [] dirs
-
-            -- wait
-            _ <- readMVar block
-
-            -- cleanup
-            mapM_ removeWatch watches
-
-    sleep 0.1
-
diff --git a/src/ParseBookfile.hs b/src/ParseBookfile.hs
--- a/src/ParseBookfile.hs
+++ b/src/ParseBookfile.hs
@@ -53,8 +53,10 @@
     parseBeginLine
     fragments <- many (parseBlank *> parseFileLine <* parseBlank)
     parseEndLine
+    trailers <- many (parseBlank *> parseFileLine <* parseBlank)
     return Bookfile
         { versionFrom = version
         , preamblesFrom = preambles
         , fragmentsFrom = fragments
+        , trailersFrom = trailers
         }
diff --git a/src/RenderDocument.hs b/src/RenderDocument.hs
--- a/src/RenderDocument.hs
+++ b/src/RenderDocument.hs
@@ -28,10 +28,9 @@
 import Text.Megaparsec (runParser, errorBundlePretty)
 import Text.Pandoc (runIOorExplode, readMarkdown, writeLaTeX, def
     , readerExtensions, readerColumns, pandocExtensions
-    , writerTopLevelDivision, TopLevelDivision(TopLevelChapter))
+    , writerTopLevelDivision, TopLevelDivision(TopLevelSection))
 
 import Environment (Env(..), Bookfile(..))
-import NotifyChanges (waitForChange)
 import LatexPreamble (preamble, beginning, ending)
 import LatexOutputReader (parseOutputForError)
 import ParseBookfile (parseBookfile)
@@ -68,15 +67,18 @@
 
     let preambles = preamblesFrom book
     let fragments = fragmentsFrom book
+    let trailers  = trailersFrom book
 
-    event "Convert preamble and begin fragments to LaTeX"
+    event "Convert preamble fragments and begin marker to LaTeX"
     mapM_ processFragment preambles
     setupBeginningFile
 
     event "Convert document fragments to LaTeX"
     mapM_ processFragment fragments
 
+    event "Convert end marker and trailing fragments to LaTeX"
     setupEndingFile
+    mapM_ processFragment trailers
 
     event "Write intermediate LaTeX file"
     produceResult
@@ -270,7 +272,10 @@
     list2 <- filterM skipNotFound (fragmentsFrom bookfile)
     debugS "fragments" (length list2)
 
-    return bookfile { preamblesFrom = list1, fragmentsFrom = list2 }
+    list3 <- filterM skipNotFound (trailersFrom bookfile)
+    debugS "trailers" (length list3)
+
+    return bookfile { preamblesFrom = list1, fragmentsFrom = list2, trailersFrom = list3}
   where
     skipNotFound :: FilePath -> Program t Bool
     skipNotFound fragment = do
@@ -324,7 +329,7 @@
         }
 
     writingOptions = def
-        { writerTopLevelDivision = TopLevelChapter
+        { writerTopLevelDivision = TopLevelSection
         }
 
   in do
diff --git a/tests/CheckBookfileParser.hs b/tests/CheckBookfileParser.hs
--- a/tests/CheckBookfileParser.hs
+++ b/tests/CheckBookfileParser.hs
@@ -55,7 +55,7 @@
 Introduction.markdown
 Conclusion.markdown
 % end
-            |] `shouldBe` Just (Bookfile 2 ["preamble.latex"] ["Introduction.markdown", "Conclusion.markdown"])
+            |] `shouldBe` Just (Bookfile 2 ["preamble.latex"] ["Introduction.markdown", "Conclusion.markdown"] [])
 
         it "Correctly parses a complete bookfile with no preamble" $ do
             parseMaybe parseBookfile [quote|
@@ -64,4 +64,13 @@
 Introduction.markdown
 Conclusion.markdown
 % end
-            |] `shouldBe` Just (Bookfile 2 [] ["Introduction.markdown", "Conclusion.markdown"])
+            |] `shouldBe` Just (Bookfile 2 [] ["Introduction.markdown", "Conclusion.markdown"] [])
+
+        it "Correctly parses a complete bookfile with trailing fragments" $ do
+            parseMaybe parseBookfile [quote|
+% publish v2
+% begin
+Introduction.markdown
+% end
+Conclusion.markdown
+            |] `shouldBe` Just (Bookfile 2 [] ["Introduction.markdown"] ["Conclusion.markdown"])
