diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Revision history for djot
 
+## 0.1.2.1 -- 2024-06-24
+
+* Djot writer: include separator line in table when the table has
+  non-default alignments but no header (#7).
+
 ## 0.1.2 -- 2024-05-10
 
 * Allow `_` in symbols (see jgm/djot#296).
diff --git a/djot.cabal b/djot.cabal
--- a/djot.cabal
+++ b/djot.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               djot
-version:            0.1.2
+version:            0.1.2.1
 synopsis:           Parser and renderer for djot light markup syntax.
 description:        Djot (<https://djot.net>) is a light markup language.
                     This package provides a data structure to represent
diff --git a/src/Djot/Djot.hs b/src/Djot/Djot.hs
--- a/src/Djot/Djot.hs
+++ b/src/Djot/Djot.hs
@@ -287,6 +287,10 @@
            AlignRight -> T.replicate (width + 1) "-" <> ":"
            AlignCenter -> ":" <> T.replicate width "-" <> ":"
            AlignDefault -> T.replicate width "-"
+  let initialSep = case rowContents of
+                     cells@(((BodyCell,al),_):_):_ | al /= AlignDefault
+                       -> mkLines (zipWith toUnderline colwidths cells)
+                     _ -> mempty
   let toRow cells =
          let isHeader = case cells of
                           ((HeadCell,_),_) : _ -> True
@@ -296,7 +300,7 @@
             if isHeader
                then mkLines (zipWith toUnderline colwidths cells)
                else mempty
-  pure $ vcat $ map toRow rowContents
+  pure $ initialSep $$ vcat (map toRow rowContents)
 
 toDefinitionListItem :: (Inlines, Blocks) -> State BState (Layout.Doc Text)
 toDefinitionListItem (term, def) = do
