faces.js: SVG cartoon faces with React and CLI output
A JavaScript library for generating vector-based cartoon faces
At a glance
- What is it?
- faces.js generates reproducible vector cartoon faces as small JavaScript objects, then renders them to the DOM, SVG strings, React components, or command-line output. It fits games, editors, and applications that need editable avatars without storing bitmap images.
- Who is it for?
- Adopt faces.js when an application needs compact, editable, vector-based cartoon identities with random or controlled facial features. Do not choose it for photographic avatars or illustrations that require free-form vector authoring.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why faces.js generates faces as data
faces.js addresses a narrow but common need: an application needs many cartoon identities without designing every portrait by hand. Its output resembles the simplified faces used in games and can serve players, fictional characters, community members, avatars, or game records. The library was originally created for Basketball GM and other ZenGM games, according to the README, and is now described as being used in other projects.
The important design choice is the representation. A face is drawn as SVG, but the generated face is also a small JavaScript object. That separation makes the face data suitable for storage, later retrieval, modification, and redrawing. The same object can therefore represent both the instructions used to construct the face and a reproducible rendering target. This is more useful than generating an image file when an application needs to change one feature, apply an override, or render at the browser's current dimensions.
The intended users are front-end and TypeScript developers who want a deterministic face model rather than a collection of static images. It may also fit Node.js workflows that need an SVG string. It does not cover realistic portraits, hand-drawn artwork, or arbitrary image uploads. The documented feature vocabulary is centered on heads, hair, bodies, eyes, noses, mouths, and related facial assets arranged as SVG components.
How generation, overrides, and relatives shape a face
The central generation function is `generate`. Without arguments, it returns a randomly assembled face object. Its optional first argument overrides values in that generated result, while its optional second argument controls player-creation parameters. The README documents `gender` values of `male` and `female`, with male as the default, and `race` values of `white`, `black`, `asian`, and `brown`, with random selection as the default.
Overrides use the same nested feature structure as the face. This means generation and rendering can share constraints such as `{ body: { color: "blue" } }`. A generated face can have blue skin applied immediately, while an existing face can have the same override applied only when displayed or converted. That separation matters when stored face data should remain canonical while a particular context imposes a temporary presentation rule.
The `relative` parameter adds a similarity mechanism. The library starts from an existing face and randomizes only some features, producing a face intended to resemble an immediate family member. Based on the documented description, generation combines selected assets and properties into a face configuration, and `display` later interprets that configuration as SVG. The README also states that the generated object exposes its available options, allowing a caller to inspect or manually construct a non-random face. The repository includes source, SVG assets, build tooling, and TypeScript declarations, although the README excerpt does not specify the exact complete schema of every feature.
Installing faces.js and rendering the first face
The README gives the following npm installation command:
npm install --save facesjsThe package is an ES module, and the documented browser-side import exposes `display` and `generate`:
import { display, generate } from "facesjs";After creating an HTML element with the id `my-div-id`, generate a face and pass either that id or the element itself to `display`:
const face = generate();
display("my-div-id", face);The documentation states that `display` inserts or renders the vector face into the selected `div`. For CommonJS callers, it also shows an equivalent import style:
const { display, generate } = require("facesjs");The first useful customization can be added without learning the complete face schema. This override always gives a generated face blue skin:
const face = generate({ body: { color: "blue" } });A real application will usually store the returned face object rather than the rendered SVG. It can later pass that object to `display`, apply another override, or use the documented editor as a design reference. The README does not document rollback behavior or a schema migration process for stored face objects.
React rendering adds visibility deferral and error control
For React applications, faces.js exports a `Face` component from `facesjs/react`. The component accepts a generated face or a `FaceConfig`, optional overrides, a wrapper `className`, and a `style` object. The README's example uses `lazy`, which delays override application and rendering until the component becomes visible according to an intersection observer.
This example imports the generator and React component separately:
import { generate } from "facesjs";
import { Face } from "facesjs/react";
import { useEffect } from "react";
export const MyFace = ({ face }) => {
return <Face face={face} lazy style={{ width: 100 }} />;
};The `lazy` property is useful when many avatars may be present but only some are within the user's visible area. It changes when work begins, not what face is produced. The `ignoreDisplayErrors` property has a narrower purpose. When set to `true`, errors raised while `display` runs are suppressed. The README positions this for user-defined faces where malformed input should not fill application error logs.
That suppression is also a design boundary. A developer choosing `ignoreDisplayErrors` trades visibility into rendering failures for quieter logs. The README does not define the exact error categories caught, so applications should not treat this prop as a validation mechanism.
SVG export and the faces.js CLI
Server-side or Node.js workflows can use `faceToSvgString` instead of manipulating the DOM. The function accepts a face and returns an SVG string:
import { faceToSvgString, generate } from "facesjs";
const face = generate();
const svg = faceToSvgString(face);Overrides are supported by this function too:
const svg = faceToSvgString(face, { body: { color: "blue" } });The README says that `faceToSvgString` is intended for Node.js and recommends rendering to the DOM first for client-side conversion, which implies that this path is not positioned as the preferred browser workflow.
The CLI exposes generation and output through `npx facesjs`. With no arguments it writes a random face to standard output:
npx facesjsTo save a male white face as `test.svg`, use the documented `-r` and `-o` options:
npx facesjs -r white -o test.svgThe command creates the file named by the example, `test.svg`. A JSON override can also be combined with gender selection:
npx facesjs -j '{"body":{"color":"blue"}}' -g femaleThe CLI also accepts `-f` for an input file and `-h` for help. Input JSON may contain either a complete face or a partial face, with unspecified features generated randomly.
Adding SVG features creates asset-placement constraints
The repository layout includes an `svgs` directory, while the build process runs `node tools/process-svgs.js`. The README states that each face is assembled from multiple SVGs and that adding an SVG in the appropriate folder should make it available to the library.
The feature authoring process has an important canvas constraint. Contributors are told to assume a 400x600 canvas. Most features can be drawn anywhere within that canvas because the library identifies and positions them automatically. Heads and hair are different. Their placement matters because the system uses those positions as references when placing other facial features. A newly authored head or hair SVG must follow the placement used by the existing assets.
This asset model is simpler than a complete vector editor and more restricted at the same time. It works well when adding a compatible eye, mouth, nose, or other modular asset. It does not provide documented support for arbitrary drawing layers, masks, or custom geometry outside the expected folder structure. The editor can be used to design faces, but the README excerpt does not describe an API for importing an artist's complete SVG illustration.
A conventional alternative is to author a complete SVG or use a static avatar asset library. Those approaches allow more control over composition, but the caller must manage all geometry and state. faces.js instead provides generation, feature selection, overrides, relational variation, and rendering around its bundled asset set. Projects needing unrestricted artwork are outside its documented scope.
Maintenance, releases, and the Apache-2.0 boundary
The repository is not archived. Its last push was on 2026-04-14, and the documented recent releases are v5.0.3 on 2026-04-16, v5.0.2 on 2025-09-09, and v5.0.1 on 2025-05-06. Those records list the releases, but the README does not provide a support policy for older major versions.
The package is primarily TypeScript and exposes a browser API, a React entry point, a Node.js-oriented SVG conversion function, and a CLI. The build includes SVG processing, Babel compilation, TypeScript declaration generation, linting, and Vitest tests. For contributors, the documented development command starts Vite, watches source and SVG changes, and updates the editor UI:
pnpm run devThe package metadata identifies the license as `Apache-2.0`. That license governs the library and its distribution, but the repository excerpt does not state whether bundled SVG assets have separate licensing or attribution requirements. Teams distributing generated or modified artwork should review the repository's `LICENSE` and asset provenance. Upgrade compatibility between stored face schemas remains undocumented.
Editorial conclusion
Adopt faces.js when an application needs compact, editable, vector-based cartoon identities with random or controlled facial features. Do not choose it for photographic avatars or illustrations that require free-form vector authoring. Before adoption, verify that the bundled facial features and documented race, gender, and color controls match the intended application and that the Apache-2.0 licensing is acceptable.
Frequently asked questions
How do I install faces.js?
The README documents `npm install --save facesjs`. The package can then be imported with ES modules or CommonJS.
Can faces.js render a face in React?
Yes. The package provides a `Face` component from `facesjs/react` that accepts a face, optional overrides, wrapper styling, and lazy rendering.
Can faces.js create SVG files from the command line?
Yes. `npx facesjs` writes a generated face to standard output, and options such as `-o` and `-r` can select an output filename and race. The CLI also supports gender, JSON, and input-file options.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zengm-games-facesjs)Was this useful?