diff --git a/hoppy-docs.cabal b/hoppy-docs.cabal
--- a/hoppy-docs.cabal
+++ b/hoppy-docs.cabal
@@ -1,5 +1,5 @@
 name: hoppy-docs
-version: 0.3.1
+version: 0.3.2
 synopsis: C++ FFI generator - Documentation
 homepage: http://khumba.net/projects/hoppy
 license: AGPL-3
diff --git a/src/Foreign/Hoppy/Documentation/UsersGuide.hs b/src/Foreign/Hoppy/Documentation/UsersGuide.hs
--- a/src/Foreign/Hoppy/Documentation/UsersGuide.hs
+++ b/src/Foreign/Hoppy/Documentation/UsersGuide.hs
@@ -132,16 +132,16 @@
 code generators, some runtime support for Haskell bindings, and interface
 definitions for the C++ standard library.
 
-Bindings using Hoppy have three parts:
+Bindings using Hoppy have three Cabal packages:
 
-- A Haskell generator program (in @\/generator@) that knows the interface
-definition and generates code for the next two parts.
+- A Haskell generator program (in @\/myproject-generator@) that knows the
+interface definition and generates code for the next two parts.
 
-- A C++ library (in @\/cpp@) that gets compiled into a shared object containing
+- A C++ library (in @\/myproject-cpp@) that gets compiled into a shared object containing
 the C++ half of the bindings.
 
-- A Haskell library (in @\/hs@) that links against the C++ library and exposes
-the bindings.
+- A Haskell library (in @\/myproject@) that links against the C++ library and
+exposes the bindings.
 
 The path names are suggested subdirectories of a project, and are used in this
 document, but are not required.  Only the latter two items need to be packaged
@@ -156,36 +156,30 @@
 -}
 {- $getting-started-project-setup
 
-To bind to a C++ library, first the binding author writes a generator program
-(@\/generator@) in Haskell.  This program should define the complete C++
-interface that is to be exposed.  The binding author also writes a @Main.hs@
-file for invoking the generator (usually deferring to 'defaultMain').  If
-necessary, she should also write wrappers for C++ things that she doesn't want
-to expose directly (in @\/cpp@).
-
-Then, her build process should perform the following steps:
-
-1. Compile the generator (@\/generator@).
-
-2. Run the generator to create the C++ and Haskell sides of the bindings in
-@\/cpp@ and @\/hs\/src@ respectively.  See the documentation for 'run' for how
-to invoke a generator.
-
-3. Compile the C++ side of the bindings into a shared object.  Make sure to
-compile with the version of the C++ standard that matches what the generator was
-run with (see 'activeCppVersion').
-
-4. Compile the Haskell side of the bindings, linking with the C++ library.
+To set up a new Hoppy project, it's recommended to start with the project in the
+@example\/@ directory as a base.  It is a minimal project that defines a C++
+function to reverse a @std::string@, exposes that to Haskell via a library, and
+provides a demo program that uses the library.  The @example\/install.sh@ script
+simply compiles and installs the generator, C++, and Haskell packages in turn.
 
-For this last step, the @.cabal@ file in @\/hs@ should have
+The generator package specifies the C++ interface to be exposed, using the
+functions and data types described in the rest of this section.
 
-> extra-libraries: foo
+The C++ package is a mostly empty, primarily containing a @Setup.hs@ file that
+invokes Hoppy build hooks, and the C++ code we're binding to.  When building
+this package, Hoppy generates some C++ code and then relies on a Makefile we
+provide for linking it together with any code we provided (see
+@example\/example-cpp\/cpp\/Makefile@).  If you are relying on a system library,
+you can link to it in the Makefile.
 
-to link against a shared object @libfoo.so@.  If this library is not on the
-system's library search path, then she will need to specify
-@--extra-lib-dirs=...\/cpp@ to the @cabal configure@ for @\/hs@.
+The Haskell package is even more empty than the C++ one.  It contains a similar
+@Setup.hs@ to invoke Hoppy.  Nothing else is included in the package's library,
+although you are free to add your own Haskell modules.  The executable ties
+everything together by calling the C++ code.  It reverses the characters of each
+input line it sees.
 
-The unit tests provide some simple examples of this setup.
+To publish this project, one would upload all three packages to Hackage.  (But
+make sure to rename it first!)
 
 -}
 {- $getting-started-a-first-binding
@@ -431,6 +425,7 @@
 define a module to export the class, and an interface to collect our modules.
 
 @
+import "Foreign.Hoppy.Generator.Main"
 import "Foreign.Hoppy.Generator.Spec"
 
 main :: IO ()
@@ -678,19 +673,27 @@
 Haskell memory to the object.
 
 This is tracked internally by handles.  Handles can either be unmanaged (as they
-are initially) or managed (by the collector).  A managed handle can be created
-from an unmanaged handle by calling 'toGc'.  This assigns the object to be
-tracked by the collector, and 'delete' will be called on the object once no more
-handles are left pointing to it.  'toGc' returns a __new__ handle, and existing
-unmanaged handles for the object should no longer be used, since they will be
-dangling pointers once the object is destroyed.  There are some points of
-caution around using this function that are worth knowing about; see the
-function documentation for more info.
+are initially) or managed (by the collector).  For simplicity, this is not
+reflected in a handle's type.  A managed handle can be created from an unmanaged
+handle by calling 'toGc'.  This assigns the object to be tracked by the
+collector, and 'delete' will be called on the object once no more handles are
+left pointing to it.  'toGc' returns a __new__ handle, and existing unmanaged
+handles for the object should no longer be used, since they will be dangling
+pointers once the object is destroyed.  There are some points of caution around
+using this function that are worth knowing about; see the function documentation
+for more info.
 
 If you want to pass an object to the collector immediately upon creation, chain
 its constructor call with @('toGc' '=<<')@.  This is not done by default because
 we don't support revoking the collector's watch over an object, and there are
 times when you want to work with manually managed objects.
+
+'toGcT' may be used when defining a function to make an object being passed into
+Haskell be managed by the garbage collector explicitly.  But rather than using
+'toGcT' with value objects, it's better to use 'classSetConversionToGc'.  There
+is also a lesser-used 'objToHeapT' for copying a temporary onto the heap for
+Haskell code to manage without giving it to the garbage collector (and a
+corresponding 'classSetConversionToHeap').
 
 -}
 {- $getting-started-objects-conversions
