Generating licenses from your package.json
Creating a JSON-file from your dependencies listed in the package file is really simple. I’m using a library called license-report, which reduces this task to a single command call. I just have to install the package as a development dependency for my project and added the following NPM-script.
{
"dep:gen": "license-report --only=prod --output=json > licenses.json"
}
With every Next.js build
As this is a repetitive task that has to be done before every deployment to ensure a current output, I simply added it to NPM’s build-command. This command is also used by Next.js, which means whenever you deploy a new version (and therefore create a new build), the licenses from your dependencies get generated before the actual build.
{
"build": "npm run dep:gen && npx next build",
}
A practical implementation
Finally, I’m simply consuming the json in my Next.js page and pass it as a property to my view. Note that the page itself is purely static. The following code example is used exactly like this in this progressive web app. They are available on the license-page.
import React from "react";
import { NpmDependency } from "../../models/license/model.license";
import RiExternalLink from "remixicon-react/ExternalLinkLineIcon";
type Props = {
licenses: NpmDependency[];
};
export function Licenses(props: Props) {
const { licenses } = props;
return (
<>
<div className="flex flex-col items-center mb-10 space-y-2 mt-28">
<h1 className="text-5xl">Licenses</h1>
<h2 className="text-xl">All licenses used for flaming.codes</h2>
</div>
<div className="grid max-w-3xl grid-cols-12 gap-10 mx-auto">
{licenses.map((l) => (
<a
key={l.link}
className="flex-col space-y-1 overflow-hidden col-span-full group"
href={l.link.replace("git+", "").replace("ssh://", "")}
target="_blank"
rel="noopener noreferrer"
aria-label={`Open Github repo for ${l.name}`}>
<div className="inline-flex items-end">
<div className="space-x-2 duration-300 ease-in group-hover:translate-x-6 group-hover:opacity-0">
<span className="text-2xl">{l.name}</span>
<span className="opacity-50">{l.installedVersion}</span>
</div>
<div className="absolute mb-1 text-blue-600 duration-300 ease-in -translate-x-4 opacity-0 group-hover:translate-x-0 group-hover:opacity-100">
<RiExternalLink />
</div>
</div>
<div className="text-gray-400">
{[l.licenseType, l.author].filter(Boolean).join(", ")}
</div>
</a>
))}
</div>
</>
);
}