diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,24 @@
 # Changelog
 
+## 1.5.0 (2020-09-04)
+
+#### Added
+
+- `toc` function is now exposed for manually generating an article's associated
+  Table of Contents.
+
+#### Changed
+
+- Tables of Contents are no longer automatically injected into the `Html`
+  produced by the `html` and `body` functions.
+- The `tableOfContents` field of `OrgStyle` is no longer a `Maybe`. It must be
+  provided, but can be given any value if you don't intend to call `toc`
+  yourself.
+
+#### Removed
+
+- The `TOC` type had its `tocTitle :: Text` field removed.
+
 ## 1.4.0 (2020-07-13)
 
 #### Added
diff --git a/lib/Data/Org/Lucid.hs b/lib/Data/Org/Lucid.hs
--- a/lib/Data/Org/Lucid.hs
+++ b/lib/Data/Org/Lucid.hs
@@ -16,6 +16,7 @@
     -- | Consider `defaultStyle` as the style to pass to these functions.
     html
   , body
+  , toc
     -- * Styling
   , OrgStyle(..)
   , defaultStyle
@@ -44,9 +45,9 @@
   { includeTitle    :: Bool
     -- ^ Whether to include the @#+TITLE: ...@ value as an @<h1>@ tag at the top
     -- of the document.
-  , tableOfContents :: Maybe TOC
-    -- ^ Optionally include a Table of Contents after the title. The displayed
-    -- depth is configurable.
+  , tableOfContents :: TOC
+    -- ^ Settings for the generated Table of Contents. The displayed depth is
+    -- configurable.
   , bootstrap       :: Bool
     -- ^ Whether to add Twitter Bootstrap classes to certain elements.
   , highlighting    :: Highlighting
@@ -59,10 +60,8 @@
   }
 
 -- | Options for rendering a Table of Contents in the document.
-data TOC = TOC
-  { tocTitle :: T.Text
-    -- ^ The text of the TOC to be rendered in an @<h2>@ element.
-  , tocDepth :: Word
+newtype TOC = TOC
+  { tocDepth :: Word
     -- ^ The number of levels to give the TOC.
   }
 
@@ -81,7 +80,7 @@
 defaultStyle :: OrgStyle
 defaultStyle = OrgStyle
   { includeTitle = True
-  , tableOfContents = Just $ TOC "Table of Contents" 3
+  , tableOfContents = TOC 3
   , bootstrap = False
   , highlighting = codeHTML
   , sectionStyling = \_ a b -> a >> b
@@ -100,16 +99,16 @@
 body :: OrgStyle -> OrgFile -> Html ()
 body os (OrgFile m od) = do
   when (includeTitle os) . traverse_ (h1_ [class_ "title"] . toHtml) $ M.lookup "TITLE" m
-  traverse_ (\t -> toc os t od) $ tableOfContents os
   orgHTML os od
 
 -- | A unique identifier that can be used as an HTML @id@ attribute.
 tocLabel :: NonEmpty Words -> T.Text
 tocLabel = ("org" <>) . T.pack . take 6 . printf "%x" . hash
 
-toc :: OrgStyle -> TOC -> OrgDoc -> Html ()
-toc _ _ (OrgDoc _ []) = pure ()
-toc os t od           = h2_ (toHtml $ tocTitle t) *> toc' os t 1 od
+-- | Generate a Table of Contents that matches some `Html` produced by `html` or
+-- `body`.
+toc :: OrgStyle -> OrgFile -> Html ()
+toc os (OrgFile _ od) = toc' os (tableOfContents os) 1 od
 
 toc' :: OrgStyle -> TOC -> Word -> OrgDoc -> Html ()
 toc' _ _ _ (OrgDoc _ []) = pure ()
diff --git a/org-mode-lucid.cabal b/org-mode-lucid.cabal
--- a/org-mode-lucid.cabal
+++ b/org-mode-lucid.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               org-mode-lucid
-version:            1.4.0
+version:            1.5.0
 synopsis:           Lucid integration for org-mode.
 description:        Lucid integration for org-mode.
 category:           Web
