diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Changelog
-
-## 0.1.0.0
-
-First release.
-
-- `build`: builds a cabal project into an npm package (JS bindings,
-  TypeScript declarations, `.wasm`, runtime and `package.json`).
-- `generate`: writes the Haskell and JS bindings for plain source files.
-- Standard types: numbers (including `Integer`/`Natural` as `bigint`), `Bool`,
-  `Char`, `String`, `Text`, `Day`, `UTCTime`, `Maybe`, `Either`, tuples, lists,
-  `Vector`, `NonEmpty`, `Set`/`HashSet`/`IntSet` and `Map`/`HashMap`/`IntMap`.
-- User data types: records, positional constructors and enums.
-- Arguments are validated before reaching Haskell; Haskell exceptions become
-  `HaskellError` without breaking the module.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # ghc-wasm-bindgen
 
-Generates JavaScript/TypeScript bindings for a pure Haskell module compiled
+Generate JavaScript/TypeScript bindings for a pure Haskell module compiled
 with GHC's WASM backend.
 
 ```haskell
@@ -48,17 +48,8 @@
 | positional                | `{ $tag: "C"; contents: … }` |
 | all without fields (enum) | `"A" \| "B"`                 |
 
-Constructors are exported as functions: `Rect({ width: 3, height: 4 })` for
-records, `Node(left, 3, right)` for positional ones, and constants like `Leaf`
-for nullary ones. Names that are not valid in JS get a trailing `_`
-(`delete` → `delete_`).
-
 Notes:
 
-- `Int` and `Word` are 32 bits on wasm32.
-- Map keys can be strings, numbers, `Bool`, `Char`, dates or your own types.
-  `Map` and `Set` compare keys by reference.
-- `UTCTime` keeps millisecond precision.
 - Every type the API uses must be exported with all its constructors.
 - Not supported yet: `IO`, polymorphic functions, functions as arguments,
   operators, types with parameters and GADTs.
@@ -70,8 +61,6 @@
   before reaching Haskell.
 - An exception in Haskell throws a `HaskellError`.
 
-Either way, the module keeps working.
-
 ## Usage
 
 ### `build`: cabal projects
@@ -79,14 +68,32 @@
 From the cabal project that contains the module:
 
 ```sh
-ghc-wasm-bindgen build src/ShapeWasm.hs --name shape --out pkg
+ghc-wasm-bindgen build src/ShapeWasm.hs --name shape --out pkg/src
 ```
 
 The module must be exposed by a library, in the same package as the code it
-wraps or in one that depends on it. This writes the npm package `pkg/`
-(`shape.js`, `shape.d.ts`, `shape.wasm`, the runtime and `package.json`).
-Depend on it like any other package and import `shape`, `shape/runtime`
-(`init`, `HaskellError`) and `shape/shape.wasm`.
+wraps or in one that depends on it. This writes `shape.js`, `shape.d.ts`,
+`shape.wasm` and the JS runtime to `pkg/src/`, and nothing else, so the
+directory around it can be maintained by hand, even in another repository.
+
+To publish it as an npm package, write its `package.json` yourself, for
+example:
+
+```json
+{
+    "name": "shape",
+    "version": "0.1.0",
+    "type": "module",
+    "exports": {
+        ".": { "types": "./src/shape.d.ts", "default": "./src/shape.js" },
+        "./runtime": { "types": "./src/ghc_wasm_bindgen_runtime.d.ts", "default": "./src/ghc_wasm_bindgen_runtime.js" },
+        "./shape.wasm": "./src/shape.wasm"
+    }
+}
+```
+
+Then import `shape`, `shape/runtime` (`init`, `HaskellError`) and
+`shape/shape.wasm`.
 
 ### `generate`: plain source files
 
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -15,8 +15,8 @@
     , "  ghc-wasm-bindgen build MODULE.hs --name NAME --out DIR"
     , "  ghc-wasm-bindgen generate MODULE.hs --name NAME --hs-out DIR --js-out DIR [-i DIR]..."
     , ""
-    , "build     From the cabal project that contains MODULE.hs, builds an npm package:"
-    , "          NAME.js, NAME.d.ts, NAME.wasm, the runtime and a package.json."
+    , "build     From the cabal project that contains MODULE.hs, writes NAME.js,"
+    , "          NAME.d.ts, NAME.wasm and the JS runtime to --out."
     , "          Needs cabal, and wasm32-wasi-cabal, wasm32-wasi-ghc and wasm-opt"
     , "          (ghc-wasm-meta) on PATH."
     , "generate  For plain source files: writes NameWasmBindings.hs and the Haskell"
@@ -25,7 +25,7 @@
     , ""
     , "  MODULE.hs      module whose export list is the API (e.g. src/ShapeWasm.hs)"
     , "  --name NAME    package and file name (e.g. shape)"
-    , "  --out DIR      output directory of the package (e.g. pkg)"
+    , "  --out DIR      output directory (e.g. pkg/src)"
     , "  -i DIR         import directory for the modules MODULE.hs imports"
     , "                 (MODULE.hs's own source root is added)"
     ]
diff --git a/ghc-wasm-bindgen.cabal b/ghc-wasm-bindgen.cabal
--- a/ghc-wasm-bindgen.cabal
+++ b/ghc-wasm-bindgen.cabal
@@ -1,17 +1,12 @@
 cabal-version:      3.0
 name:               ghc-wasm-bindgen
-version:            0.1.0.0
+version:            0.2.0.0
 synopsis:           JavaScript/TypeScript bindings for GHC's WASM backend
 description:
-    Generates JavaScript and TypeScript bindings for a pure Haskell module
-    compiled with GHC's WebAssembly backend. The module's export list is the
-    API: functions become typed JS functions, and data types become
-    TypeScript types with constructors.
-
-    @ghc-wasm-bindgen build@ builds a cabal project into an npm package (JS
-    bindings, TypeScript declarations, the .wasm and a small runtime).
-    @ghc-wasm-bindgen generate@ only writes the bindings, for plain source
-    files compiled by hand.
+    Generate JavaScript and TypeScript bindings for a pure Haskell module
+    compiled with GHC's WebAssembly backend. Exported functions are exposed
+    as typed JavaScript functions, and exported data types as TypeScript
+    types with constructor functions.
 
     See the README for supported types and usage.
 category:           Web, WebAssembly, JavaScript, Development
@@ -26,7 +21,6 @@
 tested-with:        GHC == 9.10.3
 extra-doc-files:
     README.md
-    CHANGELOG.md
 extra-source-files:
     runtime-js/ghc_wasm_bindgen_runtime.js
     runtime-js/ghc_wasm_bindgen_runtime.d.ts
diff --git a/src/GhcWasmBindgen.hs b/src/GhcWasmBindgen.hs
--- a/src/GhcWasmBindgen.hs
+++ b/src/GhcWasmBindgen.hs
@@ -2,7 +2,7 @@
 
 -- | Bindings for a Haskell API module, in two modes:
 --
--- * 'build' (cabal projects): builds an npm package (JS bindings + .wasm).
+-- * 'build' (cabal projects): builds the JS bindings and the .wasm.
 --   The package that contains the module is built natively, so the module can
 --   be inspected with its real dependencies; then the Haskell bindings are
 --   generated, together with the Haskell runtime module, as a package under
@@ -25,8 +25,8 @@
 import qualified Data.ByteString.Char8 as BC
 import Data.Char (isSpace, toLower, toUpper)
 import Data.FileEmbed (embedFile)
-import Data.List (intercalate, isSuffixOf, stripPrefix)
-import Data.Maybe (fromMaybe, mapMaybe)
+import Data.List (isSuffixOf, stripPrefix)
+import Data.Maybe (mapMaybe)
 import qualified Data.Text.Encoding as TE
 import System.Directory
 import System.Exit (ExitCode (..))
@@ -46,7 +46,7 @@
   , optName :: String
     -- ^ Base name of the outputs: NAME.js, NAME.d.ts, NAME.wasm.
   , optOut :: FilePath
-    -- ^ Directory of the npm package to write.
+    -- ^ Directory to write the JS bindings, runtime and .wasm to.
   }
 
 newtype BuildError = BuildError String
@@ -143,8 +143,7 @@
   run "wasm-opt" ["-Oz", wasm, "-o", optOut o </> name <.> "wasm"]
 
   -- JS side.
-  mapM_ (\(file, contents) -> writeIfChanged (optOut o </> file) contents) $
-    ("package.json", packageJson name (pkgVersion pkg)) : jsFiles name api
+  mapM_ (\(file, contents) -> writeIfChanged (optOut o </> file) contents) (jsFiles name api)
   pure (optOut o)
 
 -- | The JS bindings and runtime, by file name.
@@ -167,7 +166,7 @@
 
 -- Cabal --------------------------------------------------------------------
 
-data Package = Package {pkgName :: String, pkgVersion :: String}
+newtype Package = Package {pkgName :: String}
 
 -- | The cabal package that contains the API module: the nearest .cabal file
 -- above it.
@@ -180,7 +179,7 @@
         f : _ -> do
           fields <- mapMaybe field . lines . BC.unpack <$> BS.readFile (dir </> f)
           case lookup "name" fields of
-            Just n -> pure (Package n (fromMaybe "0" (lookup "version" fields)))
+            Just n -> pure (Package n)
             Nothing -> throwIO (BuildError (dir </> f ++ " has no name field"))
         [] | takeDirectory dir == dir -> throwIO (BuildError ("no .cabal file found above " ++ file))
            | otherwise -> go (takeDirectory dir)
@@ -229,33 +228,6 @@
 -- | Cabal package and component names allow letters, digits and @-@.
 cabalName :: String -> String
 cabalName = map (\c -> if c == '_' then '-' else c)
-
--- npm ----------------------------------------------------------------------
-
-packageJson :: String -> String -> ByteString
-packageJson name version =
-  BC.pack . unlines $
-    [ "{"
-    , "    \"name\": " ++ show (map toLower name) ++ ","
-    , "    \"version\": " ++ show (semver version) ++ ","
-    , "    \"type\": \"module\","
-    , "    \"main\": " ++ show ("./" ++ name ++ ".js") ++ ","
-    , "    \"types\": " ++ show ("./" ++ name ++ ".d.ts") ++ ","
-    , "    \"exports\": {"
-    , "        \".\": { \"types\": " ++ show ("./" ++ name ++ ".d.ts") ++ ", \"default\": " ++ show ("./" ++ name ++ ".js") ++ " },"
-    , "        \"./runtime\": { \"types\": \"./ghc_wasm_bindgen_runtime.d.ts\", \"default\": \"./ghc_wasm_bindgen_runtime.js\" },"
-    , "        " ++ show ("./" ++ name ++ ".wasm") ++ ": " ++ show ("./" ++ name ++ ".wasm")
-    , "    }"
-    , "}"
-    ]
-
--- | Cabal versions have any number of components; npm wants exactly three.
-semver :: String -> String
-semver v = intercalate "." (take 3 (splitOn '.' v ++ repeat "0"))
-  where
-    splitOn c s = case break (== c) s of
-      (a, []) -> [a]
-      (a, _ : rest) -> a : splitOn c rest
 
 -- Files and processes ------------------------------------------------------
 
