Factored out boilerplate from all html docs in doc directory:
- the first HTML comment in those files is extracted as page
  title when serving them
- lib/godoc.html is top-level template for all pages served
- experimented a bit with package documentation layout
  (feedback welcome)
- various related cleanups

TODO:
- The / page (doc/root.html) content repeats links that are
  in the navigation bar. It needs to be cleaned up.

R=rsc
DELTA=826  (86 added, 692 deleted, 48 changed)
OCL=35230
CL=35245
diff --git a/doc/effective_go.html b/doc/effective_go.html
index e9a1e25..d72525c 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -1,64 +1,7 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
+<!-- Effective Go -->
 
 <!-- interfaces; slices; embedding; value vs. pointer receivers; methods on anything; errors; testing -->
 
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>Effective Go</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-<style type="text/css">
-pre.bad {
-  background-color: #ffeeee;
-}
-</style>
-
-</head>
-
-
-<body>  <!-- onload="prettyPrint()" will color the programs -->
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList" style="clear:both">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="effective_go">Effective Go</h1>
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
-
 <h2 id="introduction">Introduction</h2>
 
 <p>
@@ -187,7 +130,7 @@
 <h2>Commentary</h2>
 
 <p>
-Go provides C-style <code>/* */</code> block comments 
+Go provides C-style <code>/* */</code> block comments
 and C++-style <code>//</code> line comments.
 Line comments are the norm;
 block comments appear mostly as package comments and
@@ -752,7 +695,7 @@
 used as regular variables, just like the incoming parameters.
 When named, they are initialized to the zero for their type when
 the function begins; if the function executes a <code>return</code> statement
-with no arguments, the current values of the result parameters are 
+with no arguments, the current values of the result parameters are
 used as the returned values.
 </p>
 
@@ -938,7 +881,7 @@
 A slice, for example, is a three-item descriptor
 containing a pointer to the data (inside an array), the length, and the
 capacity; until those items are initialized, the slice is <code>nil</code>.
-For slices, maps, and channels, 
+For slices, maps, and channels,
 <code>make</code> initializes the internal data structure and prepares
 the value for use.
 For instance,
@@ -1066,7 +1009,7 @@
 Especially in libraries, functions tend to have multiple error modes.
 Instead of returning a boolean to signal success,
 return an <code>os.Error</code> that describes the failure.
-Even if there is only one failure mode now, 
+Even if there is only one failure mode now,
 there may be more later.
 </p>
 
@@ -1255,9 +1198,9 @@
 <p>
 The <code>reflect.DeepEqual</code> function tests
 whether two complex data structures have equal values.
-If a function returns a complex data structure, 
+If a function returns a complex data structure,
 <code>reflect.DeepEqual</code> combined with table-driven testing
-makes it easy to check that the return value is 
+makes it easy to check that the return value is
 exactly as expected.
 </p>
 
@@ -1337,7 +1280,3 @@
 </p>
 
 -->
-
-</div>
-</body>
-</html>
diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html
index 14ed149..055242f 100644
--- a/doc/go_for_cpp_programmers.html
+++ b/doc/go_for_cpp_programmers.html
@@ -1,59 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-<!--
-To convert <h2>Foo</h2> into <h2 id="Foo">Foo</h2>
-and convert §Foo into §<a href="#Foo">Foo</a>:
-
-	Edit ,s/<(h.)>(.*)(<\/h.>)/<\1 id="\2">\2\3/g
-	Edit ,x g/id="/ x/id="[^"]+"/ s/ /_/g
-	Edit ,s/§([^),.]+)/§<a href="#\1">\1<\/a>/g
-	Edit ,x/href="#[^"]+"/ s/ /_/g
--->
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>Go For C++ Programmers</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Specification">Go For C++ Programmers</h1>
+<!-- Go For C++ Programmers -->
 
 <p>
 Go is a systems programming language intended as an alternative to C++.
@@ -72,11 +17,6 @@
 <p>
 There is more <a href="./">documentation about go</a>.
 
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
-
 <h2 id="Conceptual_Differences">Conceptual Differences</h2>
 
 <ul>
@@ -666,14 +606,3 @@
   return &lt;- my_ch;
 }
 </pre>
-
-</div>
-
-<div id="footer">
-<p>Except as noted, this content is
-   licensed under <a href="http://creativecommons.org/licenses/by/3.0/">
-   Creative Commons Attribution 3.0</a>.
-</div>
-
-</body>
-</html>
diff --git a/doc/go_lang_faq.html b/doc/go_lang_faq.html
index 142a224..e40c3b0 100644
--- a/doc/go_lang_faq.html
+++ b/doc/go_lang_faq.html
@@ -1,54 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>The Go Programming Language Design FAQ</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Design_FAQ">The Go Programming Language Design FAQ</h1> 
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- The Go Programming Language Design FAQ -->
 
 <h2 id="origins">Origins</h2>
 
@@ -416,15 +366,3 @@
 
 make vs new
 </pre>
-
-
-</div>
-
-<div id="footer">
-<p>Except as noted, this content is
-   licensed under <a href="http://creativecommons.org/licenses/by/3.0/">
-   Creative Commons Attribution 3.0</a>.
-</div>
-
-</body>
-</html>
diff --git a/doc/go_mem.html b/doc/go_mem.html
index 9239e98..d2167a6 100644
--- a/doc/go_mem.html
+++ b/doc/go_mem.html
@@ -1,64 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-<!--
-To convert <h2>Foo</h2> into <h2 id="Foo">Foo</h2>
-and convert §Foo into §<a href="#Foo">Foo</a>:
-
-	Edit ,s/<(h.)>(.*)(<\/h.>)/<\1 id="\2">\2\3/g
-	Edit ,x g/id="/ x/id="[^"]+"/ s/ /_/g
-	Edit ,s/§([^),.]+)/§<a href="#\1">\1<\/a>/g
-	Edit ,x/href="#[^"]+"/ s/ /_/g
--->
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>The Go Memory Model</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Specification">The Go Memory Model</h1>
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- The Go Memory Model -->
 
 <h2>Introduction</h2>
 
diff --git a/doc/go_spec.html b/doc/go_spec.html
index d49a4a0..afb85de 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,64 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-<!--
-To convert <h2>Foo</h2> into <h2 id="Foo">Foo</h2>
-and convert §Foo into §<a href="#Foo">Foo</a>:
-
-        Edit ,s/<(h.)>(.*)(<\/h.>)/<\1 id="\2">\2\3/g
-        Edit ,x g/id="/ x/id="[^"]+"/ s/ /_/g
-        Edit ,s/§([^),.]+)/§<a href="#\1">\1<\/a>/g
-        Edit ,x/href="#[^"]+"/ s/ /_/g
--->
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>The Go Programming Language Specification</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList" style="clear:both">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Specification">The Go Programming Language Specification</h1>
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- The Go Programming Language Specification -->
 
 <!--
 Todo
@@ -4613,14 +4553,3 @@
 	<li><font color=red>Gccgo does not implement the blank identifier.</font></li>
 	<li><font color=red>Method expressions are not implemented.</font></li>
 </ul>
-
-</div>
-
-<div id="footer">
-<p>Except as noted, this content is
-   licensed under <a href="http://creativecommons.org/licenses/by/3.0/">
-   Creative Commons Attribution 3.0</a>.
-</div>
-
-</body>
-</html>
diff --git a/doc/go_tutorial.head b/doc/go_tutorial.head
index c6977bd..a15e536 100644
--- a/doc/go_tutorial.head
+++ b/doc/go_tutorial.head
@@ -1,8 +1,3 @@
-<div id="content">
-<h1 id="Lets_Go">Let's Go</h1> 
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- Let's Go -->
 
 <h2>Introduction</h2>
diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index 1029d74..755e43d 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -1,8 +1,4 @@
-<h1 id="Lets_Go">Let's Go</h1> 
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- Let's Go -->
 
 <h2>Introduction</h2>
 <p>
@@ -602,7 +598,7 @@
     % helloworld3
     hello, world
     can't open file; err=No such file or directory
-    % 
+    %
 
 </pre>
 <h2>Rotting cats</h2>
@@ -770,7 +766,7 @@
     abcdefghijklmnopqrstuvwxyz
     % echo abcdefghijklmnopqrstuvwxyz | ./cat --rot13
     nopqrstuvwxyzabcdefghijklm
-    % 
+    %
 </pre>
 <p>
 Fans of dependency injection may take cheer from how easily interfaces
@@ -1354,5 +1350,3 @@
 There's a lot more to Go programming and concurrent programming in general but this
 quick tour should give you some of the basics.
 </table>
-</body>
-</html>
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 1b57722..b703b2e 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -4,14 +4,8 @@
 	license that can be found in the LICENSE file.
 -->
 
-{.section Dirs}
-	<h2>Subdirectories</h2>
-	{.repeated section @}
-		<a href="{Name|html}">{Name|html}</a><br />
-	{.end}
-{.end}
 {.section PDoc}
-	<h1>package {PackageName|html}</h1>
+	<!-- PackageName is printed as title by the top-level template -->
 	<p><code>import "{ImportPath|html}"</code></p>
 	{Doc|html-comment}
 	{.section Filenames}
@@ -77,3 +71,9 @@
 		{.end}
 	{.end}
 {.end}
+{.section Dirs}
+	<h2>Subdirectories</h2>
+	{.repeated section @}
+		<a href="{Name|html}">{Name|html}</a><br />
+	{.end}
+{.end}
diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt
index 8d836cc..d8c3c31 100644
--- a/lib/godoc/package.txt
+++ b/lib/godoc/package.txt
@@ -1,10 +1,3 @@
-{.section Dirs}
-SUBDIRECTORIES
-{.repeated section @}
-	{Name}
-{.end}
-
-{.end}
 {.section PDoc}
 PACKAGE
 
@@ -75,3 +68,11 @@
 {.end}
 {.end}
 {.end}
+{.section Dirs}
+
+SUBDIRECTORIES
+
+{.repeated section @}
+	{Name}
+{.end}
+{.end}
diff --git a/lib/godoc/parseerror.html b/lib/godoc/parseerror.html
index 35d9562..361cffe 100644
--- a/lib/godoc/parseerror.html
+++ b/lib/godoc/parseerror.html
@@ -4,7 +4,7 @@
 	license that can be found in the LICENSE file.
 -->
 
-<h1>Parse errors in {filename}</h1>
 <pre>
 {.repeated section list}
-{src}{.section msg}<b><font color=red>«{msg|html}»</font></b>{.end}{.end}</pre>
+{src}{.section msg}<b><font color=red>«{msg|html}»</font></b>{.end}{.end}
+</pre>
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 5164c39..1de4765 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -50,10 +50,7 @@
 )
 
 
-const (
-	Pkg = "/pkg/";	// name for auto-generated package documentation tree
-	Spec = "/doc/go_spec.html";
-)
+const Pkg = "/pkg/";	// name for auto-generated package documentation tree
 
 
 type delayTime struct {
@@ -186,7 +183,7 @@
 func parse(path string, mode uint) (*ast.File, *parseErrors) {
 	src, err := io.ReadFile(path);
 	if err != nil {
-		log.Stderrf("ReadFile %s: %v", path, err);
+		log.Stderrf("%v", err);
 		errs := []parseError{parseError{nil, 0, err.String()}};
 		return nil, &parseErrors{path, errs, nil};
 	}
@@ -349,16 +346,16 @@
 func servePage(c *http.Conn, title, content interface{}) {
 	type Data struct {
 		title interface{};
-		header interface{};
 		timestamp string;
 		content interface{};
 	}
 
-	var d Data;
-	d.title = title;
-	d.header = title;
-	d.timestamp = time.SecondsToLocalTime(syncTime.get()).String();
-	d.content = content;
+	d := Data{
+		title: title,
+		timestamp: time.SecondsToLocalTime(syncTime.get()).String(),
+		content: content,
+	};
+
 	if err := godocHtml.Execute(&d, c); err != nil {
 		log.Stderrf("godocHtml.Execute: %s", err);
 	}
@@ -374,18 +371,57 @@
 // ----------------------------------------------------------------------------
 // Files
 
+var (
+	tagBegin = strings.Bytes("<!--");
+	tagEnd = strings.Bytes("-->");
+)
+
+// commentText returns the text of the first HTML comment in src.
+func commentText(src []byte) (text string) {
+	i := bytes.Index(src, tagBegin);
+	j := bytes.Index(src, tagEnd);
+	if i >= 0 && j >= i+len(tagBegin) {
+		text = string(bytes.TrimSpace(src[i+len(tagBegin) : j]));
+	}
+	return;
+}
+
+
+func serveHtmlDoc(c *http.Conn, r *http.Request, filename string) {
+	// get HTML body contents
+	path := pathutil.Join(goroot, filename);
+	src, err := io.ReadFile(path);
+	if err != nil {
+		log.Stderrf("%v", err);
+		http.NotFound(c, r);
+		return;
+	}
+
+	// if it's the language spec, add tags to EBNF productions
+	if strings.HasSuffix(path, "go_spec.html") {
+		var buf bytes.Buffer;
+		linkify(&buf, src);
+		src = buf.Bytes();
+	}
+
+	title := commentText(src);
+	servePage(c, title, src);
+}
+
+
 func serveParseErrors(c *http.Conn, errors *parseErrors) {
 	// format errors
 	var buf bytes.Buffer;
 	if err := parseerrorHtml.Execute(errors, &buf); err != nil {
 		log.Stderrf("parseerrorHtml.Execute: %s", err);
 	}
-	servePage(c, errors.filename + " - Parse Errors", buf.Bytes());
+	servePage(c, "Parse errors in source file " + errors.filename, buf.Bytes());
 }
 
 
-func serveGoSource(c *http.Conn, name string) {
-	prog, errors := parse(name, parser.ParseComments);
+func serveGoSource(c *http.Conn, filename string) {
+	path := pathutil.Join(goroot, filename);
+	prog, errors := parse(path, parser.ParseComments);
 	if errors != nil {
 		serveParseErrors(c, errors);
 		return;
@@ -396,43 +432,35 @@
 	writeNode(&buf, prog, true);
 	fmt.Fprintln(&buf, "</pre>");
 
-	servePage(c, name + " - Go source", buf.Bytes());
-}
-
-
-func serveGoSpec(c *http.Conn, r *http.Request) {
-	src, err := io.ReadFile(pathutil.Join(goroot, Spec));
-	if err != nil {
-		http.NotFound(c, r);
-		return;
-	}
-	linkify(c, src);
+	servePage(c, "Source file " + filename, buf.Bytes());
 }
 
 
 var fileServer = http.FileServer(".", "");
 
-func serveFile(c *http.Conn, req *http.Request) {
+func serveFile(c *http.Conn, r *http.Request) {
+	path := r.Url.Path;
+
 	// pick off special cases and hand the rest to the standard file server
-	switch {
-	case req.Url.Path == "/":
-		// serve landing page.
-		// TODO: hide page from ordinary file serving.
-		// writing doc/index.html will take care of that.
-		http.ServeFile(c, req, "doc/root.html");
+	switch ext := pathutil.Ext(path); {
+	case path == "/":
+		serveHtmlDoc(c, r, "doc/root.html");
 
-	case req.Url.Path == "/doc/root.html":
+	case r.Url.Path == "/doc/root.html":
 		// hide landing page from its real name
-		// TODO why - there is no reason for this (remove eventually)
-		http.NotFound(c, req);
+		http.NotFound(c, r);
 
-	case pathutil.Ext(req.Url.Path) == ".go":
-		serveGoSource(c, req.Url.Path[1 : len(req.Url.Path)]);  // strip leading '/' from name
+	case ext == ".html":
+		serveHtmlDoc(c, r, path);
+
+	case ext == ".go":
+		serveGoSource(c, path);
 
 	default:
-		// TODO not good enough - don't want to download files
-		// want to see them
-		fileServer.ServeHTTP(c, req);
+		// TODO:
+		// - need to decide what to serve and what not to serve
+		// - don't want to download files, want to see them
+		fileServer.ServeHTTP(c, r);
 	}
 }
 
@@ -496,6 +524,7 @@
 	// get package AST
 	pkg, err := parser.ParsePackage(dirname, filter, parser.ParseComments);
 	if err != nil {
+		// TODO: parse errors should be shown instead of an empty directory
 		log.Stderr(err);
 	}
 
@@ -548,7 +577,12 @@
 	if path == "" {
 		path = ".";  // don't display an empty path
 	}
-	servePage(c, path + " - Go package documentation", buf.Bytes());
+	title := "Directory " + path;
+	if info.PDoc != nil {
+		title = "Package " + info.PDoc.PackageName;
+	}
+
+	servePage(c, title, buf.Bytes());
 }
 
 
@@ -665,7 +699,6 @@
 			handler = loggingHandler(handler);
 		}
 
-		http.Handle(Spec, http.HandlerFunc(serveGoSpec));
 		http.Handle(Pkg, http.HandlerFunc(servePkg));
 		if *syncCmd != "" {
 			http.Handle("/debug/sync", http.HandlerFunc(dosync));