The package.json file enters most developers' lifes as something to struggle with on build errors when libraries dont't want to work with each other in this or that version, but knowing it and how to use it for your own purposes gives you more than just calming your build tool.
Modern frontend development consists mainly in
npm installor
yarn installor
pnpm installwhere npm / yarn / pnpm read a package.json file to know which packages of JavaScript files to download and store it in which way, with special attention to avoid conflicts with other packages or versions of packages. They are not concerned with using a package after it is installed, or if it is has any usable content at all.
An installed package may contain a fetch_helper whose code is defined in the file all_helpers.js of the package super-helpers that resides in the directory node_modules (since npm was invented to provide packages as "modules" for Node). Syntactically correct you would make the fetch_helper available in your script by
// js code
import { fetch_helper } from "./node_modules/super-helpers/all_helpers.js"but, starting with Node.js, JavaScript runtimes and IDEs want to make your life easier by just requiring e.g.
// js code
import { fetch_helper } from "super-helpers`"To allow this, e.g. Node.js reads a package.json file in the directory super-helpers in node_modules to find the path to fetch_helper on its own, e.g. by the package.json entry
// package.json
"main": "all_helpers.js"Node.js could do this without a package.json or a main entry if you rename all_helpers.js to index.js, but with main and / or some other specific entries in a package.json package developers are not forced to shoehorn everything in a single index.js file.
In practice, the only formal restriction for a package.json is that it must be a valid JSON file, usage restrictions boil down to adhere to currently documented keys of npm and Node.js, making the original specification (see References) rather theoretical. Anything not conflicting with this can be added to a package.json for deeper purposes of the package itself, e.g. automated processes reflecting being run on different platforms like Linux vs. Windows, configuration options, or meta information to be used for different purposes like user information or orchestrating different parts of the package.
A very prominent special purpose usage of a package.json is that by Microsoft for VS Code extensions.
Of course the JSON Schema Store has a formal description for NPM package.json files, but the clear and simple concept of a package.json and its widespread acceptance as a quasi-standard makes it a schema for providing information as a JSON file that only needs the name "package.json" to know how to read it, for humans as well as for automated processes.
In this way also packages that have nothing to offer that could be used for an import in a JavaScript file can and do utilize a package.json to describe themselves and their proper usage. A significant example are themes for Ghost CMS, e.g. for the default theme "Caspar".
The most prominent use of a package.json without installing or using JavaScript code of course is the npm registry where it is used to make a package findable and to describe it.