--- dtplite.tcl
+++ dtplite.tcl
@@ -275,10 +275,14 @@
     # anchor in the index output. Requires support for the engine
     # parameter 'kwid' in the index engine.
 
     variable  kwid
     array set kwid {}
+
+    # Note whether keywords are present. In the directory or merge modes
+    # if no keywords are present links to keywords page are not output.
+    variable kwpresent 1
 
     # Cache. This array maps from the path of an input file/document
     # (relative to 'input'), to the paths of the file to generate
     # (relative to 'output', including extension and such). In other
     # words we derive the output paths from the inputs only once and
@@ -817,10 +821,12 @@
     variable module
     variable meta
     variable format
     variable utoc
     variable mtoc
+    variable kwid;              # Only used to check if any keywords present...
+    variable kwpresent;         # ...and set this accordingly
 
     # Phase 0. Find the documents to convert.
     # Phase I. Collect meta data, and compute the map from input to
     # ........ output files. This is also the map for the symbolic
     # ........ references. We extend an existing map (required for use
@@ -836,10 +842,16 @@
     }
 
     MetadataGet $files
     StyleMakeLocal
 
+    # Need to ensure kwid initialized before writing ToC so that
+    # kwpresent is valid when TocWrite is called
+    set idx_data [IdxGenerate $module [IdxGet]]
+    # kwid array set at this point
+    set kwpresent [array size kwid]; # Remember if any keywords
+
     if {$utoc ne {}} {
 	if {[file exists $utoc]} { set utoc [Get $utoc] }
 	TocWrite toc index $utoc
     } else {
 	TocWrite toc index [TocGenerate [TocGet $module toc]]
@@ -849,11 +861,11 @@
     foreach item $mtoc {
 	if {[file exists $item]} { set item [Get $item] }
 	TocWrite toc$n index $item
 	incr n
     }
-    IdxWrite index toc [IdxGenerate $module [IdxGet]]
+    IdxWrite index toc $idx_data
 
     dt configure -module $module
     XrefGet
     XrefSetup   dt
     FooterSetup dt
@@ -863,24 +875,29 @@
 	Print stdout \t$f
 
 	set o $out($f)
 	dt configure -file [At $o] -ibase $input/$f
 
-	NavbuttonPush {Keyword Index}     [Output index] $o
+        if {$kwpresent} {
+            NavbuttonPush {Keyword Index}     [Output index] $o
+        }
 	NavbuttonPush {Table Of Contents} [Output toc]   $o
 	HeaderSetup dt $o
 	NavbuttonPop
-	NavbuttonPop
+        if {$kwpresent} {
+            NavbuttonPop
+        }
 	StyleSetup dt $o
 
 	if {[string equal $format null]} {
 	    dt format [Get [Pick $f]]
 	} else {
 	    Write [At $o] [dt format [Get [Pick $f]]]
 	}
 	Warnings
     }
+
     return
 }
 
 proc ::dtplite::Do.Directory.Merge {} {
     # See Do.Directory, but merge the TOC/Index information from this
@@ -892,10 +909,11 @@
     variable meta
     variable output
     variable format
     variable utoc
     variable mtoc
+    variable kwpresent;         # To remember if any keywords present
 
     # Phase 0. Find the documents to process.
     # Phase I. Collect meta data, and compute the map from input to
     # ........ output files. This is also the map for the symbolic
     # ........ references. We extend an existing map (required for use
@@ -913,10 +931,13 @@
     }
 
     MetadataGet $files $module
     StyleMakeLocal     $module
 
+    set saved_index [IdxGetSaved index]
+    set kwpresent [llength $saved_index]
+
     set localtoc [TocGet $module $module/toc]
     TocWrite $module/toc index [TocGenerate $localtoc] [TocMap $localtoc]
     if {$utoc ne {}} {
 	if {[file exists $utoc]} { set utoc [Get $utoc] }
 	TocWrite toc index $utoc
@@ -928,11 +949,11 @@
     foreach item $mtoc {
 	if {[file exists $item]} { set item [Get $item] }
 	TocWrite toc$n index $item
 	incr n
     }
-    IdxWrite index toc [IdxGenerate {} [IdxGetSaved index]]
+    IdxWrite index toc [IdxGenerate {} $saved_index]
 
     dt configure -module $module
     XrefGetSaved
     XrefSetup   dt
     FooterSetup dt
@@ -941,18 +962,21 @@
     foreach f [lsort -dict $files] {
 	Print stdout \t$f
 
 	set o $out($f)
 	dt configure -file [At $o] -ibase $input/$f
-
-	NavbuttonPush {Keyword Index}          [Output index]       $o
+        if {$kwpresent} {
+            NavbuttonPush {Keyword Index}          [Output index]       $o
+        }
 	NavbuttonPush {Table Of Contents}      [Output $module/toc] $o
 	NavbuttonPush {Main Table Of Contents} [Output toc]         $o
 	HeaderSetup dt $o
 	NavbuttonPop
 	NavbuttonPop
-	NavbuttonPop
+        if {$kwpresent} {
+            NavbuttonPop
+        }
 	StyleSetup dt $o
 
 	if {[string equal $format null]} {
 	    dt format [Get [Pick $f]]
 	} else {
@@ -1124,21 +1148,25 @@
     return [join $lines \n]\n
 }
 
 proc ::dtplite::TocWrite {ftoc findex text {map {}}} {
     variable format
+    variable kwpresent
 
     if {[string equal $format null]} return
     Write [At .tocdoc] $text
 
     set ft [Output $ftoc]
 
     doctools::toc::new toc -format $format -file $ft
-
-    NavbuttonPush {Keyword Index} [Output $findex] $ftoc
+    if {$kwpresent} {
+        NavbuttonPush {Keyword Index} [Output $findex] $ftoc
+    }
     HeaderSetup  toc $ft
-    NavbuttonPop
+    if {$kwpresent} {
+        NavbuttonPop
+    }
     FooterSetup  toc
     StyleSetup   toc $ftoc
 
     foreach {k v} $map {toc map $k $v}
 
@@ -1577,13 +1605,17 @@
 ## Caching the merge result for quicker future access.
 
 proc ::dtplite::HeaderSetup {o ref} {
     variable header
     variable nav
+    variable prenav
+    variable postnav
 
-    if {[string equal $header ""] && ![llength $nav]} return
-    if {![in [$o parameters] header]}                 return
+    if {[llength $prenav] == 0 && [llength $postnav] == 0} {
+        if {[string equal $header ""] && ![llength $nav]} return
+        if {![in [$o parameters] header]}                 return
+    }
 
     $o setparam header [Navbar $nav $ref]
     return
 }
 

