@featherk/icons 0.15.8 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +25 -13
  2. package/dist/docs-manifest.d.ts +1 -0
  3. package/dist/docs-manifest.js +7 -5
  4. package/dist/fontawesome/build.cjs +1 -2
  5. package/dist/fontawesome/build.d.ts +1 -1
  6. package/dist/fontawesome/build.mjs +2 -3
  7. package/dist/fontawesome/catalog.cjs +0 -13
  8. package/dist/fontawesome/catalog.d.ts +0 -8
  9. package/dist/fontawesome/catalog.mjs +0 -13
  10. package/dist/fontawesome/chunks/{generate-BBurrhLv.cjs → generate-B_FxftR7.cjs} +12 -1
  11. package/dist/fontawesome/chunks/{generate-Zq9q2YZD.mjs → generate-DF9R65sV.mjs} +13 -2
  12. package/dist/fontawesome/chunks/manifest-CF473fsM.mjs +61 -0
  13. package/dist/fontawesome/chunks/manifest-DEhGKvmi.cjs +60 -0
  14. package/dist/fontawesome/cli.cjs +23 -26
  15. package/dist/fontawesome/cli.mjs +23 -26
  16. package/dist/fontawesome/generate.d.ts +7 -0
  17. package/dist/fontawesome/manifest.d.ts +35 -0
  18. package/dist/fontawesome/setup.cjs +147 -179
  19. package/dist/fontawesome/setup.d.ts +2 -2
  20. package/dist/fontawesome/setup.mjs +149 -181
  21. package/dist/fontawesome/vite.cjs +64 -28
  22. package/dist/fontawesome/vite.d.ts +25 -5
  23. package/dist/fontawesome/vite.mjs +65 -29
  24. package/docs/ADDING-ICONS.md +4 -3
  25. package/docs/COMING-SOON.md +24 -14
  26. package/docs/ICONS.md +1 -1
  27. package/docs/fontawesome/CreateFontAwesomeManifest.md +12 -12
  28. package/docs/fontawesome/FontAwesome.md +47 -48
  29. package/docs/fontawesome/FontAwesomeCLI.md +14 -19
  30. package/docs/fontawesome/FontAwesomeDeveloperSetup.md +134 -0
  31. package/docs/fontawesome/LICENSING.md +61 -82
  32. package/package.json +1 -1
  33. package/dist/fontawesome/chunks/manifest-BB3q10t1.mjs +0 -20
  34. package/dist/fontawesome/chunks/manifest-C15Xa22L.cjs +0 -19
@@ -0,0 +1,134 @@
1
+ # FeatherK FontAwesome Developer Setup
2
+
3
+ This is the step-by-step setup for a developer adding Font Awesome icons to an application with `@featherk/icons`, on a local machine and in CI. It covers the default layout every team uses: Free packages in the application, Pro packages in a private `fontawesome-pro-sources/` project. For background, see [Font Awesome Build Integration](FontAwesome.md). For licensing, token handling, and the `--free-only` exception, see [Font Awesome Pro Licensing and Setup](LICENSING.md).
4
+
5
+ ## Before You Start
6
+
7
+ - Confirm package access, release coverage, and Creator seats with the license owner. A package token enables downloads; it grants no license seats, and neither does `@featherk/icons`.
8
+ - Get a Pro Package Token from the [Font Awesome Tokens page](https://fontawesome.com/account/tokens). Never put the token in a file, a command, or shell history. The setup command reads it from `FONTAWESOME_PACKAGE_TOKEN` or asks for it at a hidden prompt.
9
+ - Get the catalog keys for the icons you need from UX; see [Choose Font Awesome Icons and Create a Manifest](CreateFontAwesomeManifest.md).
10
+ - Install `@featherk/icons` and the application's Vite major (7 or 8) as development dependencies, as described in [Install the Vite Integration](FontAwesome.md#install-the-vite-integration).
11
+
12
+ ## Local Machine
13
+
14
+ 1. **Create `fontawesome.keys.json`** at the application root. It is the only list of selected icons: the setup command installs exactly what it lists, and the Vite plugin generates exactly what it lists. Pro keys go under `pro`.
15
+
16
+ ```json
17
+ {
18
+ "free": ["user"],
19
+ "pro": ["pro-house-light"]
20
+ }
21
+ ```
22
+
23
+ 2. **Install the source packages** from the application root. Enter the token at the hidden prompt when asked:
24
+
25
+ ```sh
26
+ npx featherk-fontawesome-setup --manifest fontawesome.keys.json
27
+ ```
28
+
29
+ The command looks up each key's exact package and version in the published catalog, then:
30
+ - installs the Free packages into the application's `devDependencies` from public npm, without the token;
31
+ - writes the Pro pins into `fontawesome-pro-sources/` (a `package.json`, a `.gitignore`, and an `.npmrc` with only a token placeholder), then installs that project with the token.
32
+
33
+ You never install a Font Awesome package by hand.
34
+
35
+ 3. **Commit** `fontawesome.keys.json`, `package.json`, `package-lock.json`, and `fontawesome-pro-sources/`, including its `package-lock.json`. Its `node_modules` stays ignored. Never put a real token in any `.npmrc`.
36
+
37
+ 4. **Add the plugin** to `vite.config.ts`:
38
+
39
+ ```ts
40
+ import { featherkFontAwesome } from "@featherk/icons/fontawesome/vite";
41
+
42
+ export default defineConfig({
43
+ plugins: [
44
+ vue(),
45
+ featherkFontAwesome({ manifest: "fontawesome.keys.json" }),
46
+ ],
47
+ });
48
+ ```
49
+
50
+ 5. **Run the application's normal scripts**, such as `npm run dev` and `npm run build`, without the token. Because `fontawesome-pro-sources/` is installed, they include the Pro icons. At the end of each build, Vite lists the source packages the icons came from; the list is informational only.
51
+
52
+ 6. **Render icons** from the virtual module; see [Render the Selected Key](FontAwesome.md#render-the-selected-key).
53
+
54
+ ```ts
55
+ import { getFaIcon } from "virtual:featherk/fontawesome";
56
+
57
+ const houseIcon = getFaIcon("pro-house-light");
58
+ ```
59
+
60
+ If a type check such as `vue-tsc` runs before Vite, generate the declarations first with the same manifest:
61
+
62
+ ```sh
63
+ npx featherk-fontawesome --manifest fontawesome.keys.json --virtual-types src/featherk-fontawesome.d.ts
64
+ ```
65
+
66
+ ### Fresh Clone
67
+
68
+ After the application's normal `npm ci`, install the committed Pro sources from their lockfile with the token:
69
+
70
+ ```sh
71
+ npx featherk-fontawesome-setup
72
+ ```
73
+
74
+ Without this step, the application still installs and builds, with the Free icons only. Code that uses a Pro key then fails type checking, which shows that the step was skipped.
75
+
76
+ ### Changing Icons
77
+
78
+ Edit `fontawesome.keys.json`, rerun `npx featherk-fontawesome-setup --manifest fontawesome.keys.json`, and commit the result. The command updates both sets of pins; when the Pro pins change, it regenerates `fontawesome-pro-sources/package-lock.json`. Restart Vite after installing.
79
+
80
+ ## CI
81
+
82
+ A build that includes Pro icons has three steps. Only the middle one has the token:
83
+
84
+ 1. The application's normal `npm ci`, without the token.
85
+ 2. `npx featherk-fontawesome-setup`, with `FONTAWESOME_PACKAGE_TOKEN`. In CI it installs `fontawesome-pro-sources/` only from the committed lockfile and refuses `--manifest` setup.
86
+ 3. The application's normal build, test, and deploy steps, without the token.
87
+
88
+ A build that skips step 2 is Free-only. Never expose the token to untrusted pull-request builds.
89
+
90
+ ### TeamCity
91
+
92
+ 1. Add a build parameter named `fontawesome.package.token` with type **Password**. Do not use an `env.` prefix; TeamCity would export it to every step.
93
+ 2. Leave the existing `npm ci` step unchanged, and add a Command Line step after it that sets the token for one command:
94
+
95
+ ```sh
96
+ # Linux agent
97
+ FONTAWESOME_PACKAGE_TOKEN='%fontawesome.package.token%' npx featherk-fontawesome-setup
98
+ ```
99
+
100
+ ```bat
101
+ rem Windows agent
102
+ set "FONTAWESOME_PACKAGE_TOKEN=%fontawesome.package.token%"
103
+ npx featherk-fontawesome-setup
104
+ ```
105
+
106
+ 3. Leave the build and the authorized deploy steps unchanged. They never reference the parameter.
107
+
108
+ Build agents must be able to reach `npm.fontawesome.com`. For GitHub Actions and the full token-scoping rules, see [CI and Deployment](LICENSING.md#ci-and-deployment).
109
+
110
+ ### Build Caches
111
+
112
+ A build cache keyed on tracked files, such as Turborepo's, must also key on whether `fontawesome-pro-sources/` is installed, or it can replay a Free build where Pro is expected. Add the install marker to the build's inputs:
113
+
114
+ ```json
115
+ "inputs": ["$TURBO_DEFAULT$", "fontawesome-pro-sources/node_modules/.package-lock.json"]
116
+ ```
117
+
118
+ Keep builds that include Pro icons out of shared or remote caches.
119
+
120
+ ## Distribution
121
+
122
+ > [!WARNING]
123
+ > A Pro build contains Font Awesome SVG path data. Publish it only where access controls, license coverage, and the required seats are confirmed, and preserve `featherk-fontawesome.licenses.txt` in every application distribution.
124
+
125
+ ## Checklist
126
+
127
+ - [ ] License owner confirmed package access, release coverage, and seats
128
+ - [ ] `fontawesome.keys.json` lists UX-provided keys, with Pro keys under `pro`
129
+ - [ ] `npx featherk-fontawesome-setup --manifest fontawesome.keys.json` ran locally
130
+ - [ ] `fontawesome-pro-sources/` and both lockfiles are committed; no token is in any file
131
+ - [ ] `vite.config.ts` uses `featherkFontAwesome({ manifest: "fontawesome.keys.json" })`
132
+ - [ ] CI runs `npx featherk-fontawesome-setup` with the token, between `npm ci` and the build
133
+ - [ ] Any build cache keys on the `fontawesome-pro-sources` install marker
134
+ - [ ] `featherk-fontawesome.licenses.txt` ships with the application
@@ -20,15 +20,15 @@ The steps below are for Dev after UX/Design has selected the desired Pro variant
20
20
 
21
21
  1. Confirm entitlement, Creator coverage, and approved releases with the license owner.
22
22
  2. Dev obtains an authorized **Pro Package Token** from the Font Awesome account and supplies it privately as `FONTAWESOME_PACKAGE_TOKEN`.
23
- 3. Dev installs the npm packages named by the manifest's `package` fields at their exact `version`s into the dedicated private project through its environment-referenced npm configuration.
24
- 4. Dev enables the Pro profile and prepares declarations before type checking/building the application.
23
+ 3. Dev runs `featherk-fontawesome-setup --manifest fontawesome.keys.json`, which pins Free packages into the application and Pro packages into the private `fontawesome-pro-sources/` project at their exact catalog versions. See [Consuming Applications](#consuming-applications).
24
+ 4. Dev builds with the application's normal scripts; wherever `fontawesome-pro-sources/` is installed, the builds include the Pro icons.
25
25
  5. Dev preserves upstream notices and verifies publication/deployment boundaries before distribution.
26
26
 
27
27
  A package token is not a Kit code, account password, or Kendo license key. Never paste it into chat, screenshots, source files, command arguments, or logs. Follow the organization's approved token issuance/rotation process; do not share account passwords.
28
28
 
29
29
  ## This FeatherK Repository
30
30
 
31
- Normal root installation/build, Free demos, tests, and public package publishing require no Pro token. `demos/pro` is a separate private source project, not a root workspace. It requests exact `@fortawesome/pro-regular-svg-icons@7.0.0` and `@fortawesome/pro-light-svg-icons@7.0.0` packages; no paid dependency is added to the normal demo workspace or public icons package.
31
+ Normal root installation/build, Free demos, tests, and public package publishing require no Pro token. `demos/fontawesome-pro-sources` is a separate private source project, not a root workspace; it is the same [default layout](#default-isolated-pro-sources) every consuming application uses. It requests exact `@fortawesome/pro-regular-svg-icons@7.0.0` and `@fortawesome/pro-light-svg-icons@7.0.0` packages; no paid dependency is added to the normal demo workspace or public icons package.
32
32
 
33
33
  The committed source-project npm configuration contains only a placeholder:
34
34
 
@@ -44,21 +44,21 @@ From the repository root, after confirming Steps 1-2:
44
44
  ```sh
45
45
  # The Font Awesome commands run from the built package; build it first.
46
46
  npm run build --workspace=@featherk/icons
47
- # Step 3: Authenticated installation runs only inside demos/pro.
47
+ # Step 3: Authenticated installation runs only inside demos/fontawesome-pro-sources.
48
48
  npm run setup:fontawesome:pro --workspace=@featherk/demos
49
- # Step 4: Start the explicitly licensed local profile.
50
- npm run dev:pro --workspace=@featherk/demos
49
+ # Step 4: Start the demo; with the sources installed, the Pro page renders.
50
+ npm run dev --workspace=@featherk/demos
51
51
  # Step 5: Build the application and preserve emitted notices.
52
- npm run build:pro --workspace=@featherk/demos
52
+ npm run build --workspace=@featherk/demos
53
53
  ```
54
54
 
55
- FeatherK's demos use the [isolated source project](#optional-pro-isolated-source-project) layout: `setup:fontawesome:pro` runs `featherk-fontawesome-setup --source-root pro`. The installer checks for the token without printing it. Initial installation creates an isolated lockfile; later runs use `npm ci` when it exists. Review and commit dependency/integrity metadata for reproducible CI, ensuring it contains no credentials. Source `node_modules` and application artifacts remain ignored. No paid installation has been performed as part of implementing this setup.
55
+ `setup:fontawesome:pro` runs `featherk-fontawesome-setup` without arguments, which installs `demos/fontawesome-pro-sources` from its committed lockfile with `npm ci`. The installer checks for the token without printing it. Review and commit dependency/integrity metadata for reproducible CI, ensuring it contains no credentials. Source `node_modules` and application artifacts remain ignored.
56
56
 
57
- The UX-approved Pro manifest requests Regular Rocket, Light Feather, and Light Heart. These pins are requested examples, not verified downloads. If entitlement, releases, or exports are unavailable, Dev must stop installation/generation and return to UX/Design for approval before changing the manifest or dependencies; never substitute silently.
57
+ The UX-approved Pro manifest requests Regular Rocket, Light Feather, Light Heart, and Light House (`pro-rocket-regular`, `pro-feather-light`, `pro-heart-light`, `pro-house-light`). An authorized installation of these pins succeeded on October 15, 2026 (see [Validation Boundary](#validation-boundary)). If entitlement, releases, or exports later become unavailable, Dev must stop installation/generation and return to UX/Design for approval before changing the manifest or dependencies; never substitute silently.
58
58
 
59
- The profile wrappers enable the non-secret `FEATHERK_FONTAWESOME_PRO=1` build flag and remove the package token from child build environments. They invoke the demo's own commands, not the root Turborepo cached build. Do not put paid outputs into shared/untrusted caches.
59
+ The demo has no separate Pro scripts: its normal `dev` and `build` include the Pro icons once `demos/fontawesome-pro-sources` is installed, and only the Free icons otherwise. `demos/turbo.json` adds `fontawesome-pro-sources/node_modules/.package-lock.json`, which npm writes on install, to the build's cache inputs, so the root Turborepo build never replays a Free build where Pro sources are installed, or the reverse. Do not put paid outputs into shared or remote caches.
60
60
 
61
- `sourceRoot: "pro"` resolves installed licensed packages while output guards remain relative to the demo project. Node resolution also finds already installed Free packages in parent workspace directories. The next normal preparation restores the Free-only generated key union.
61
+ The demo's plugin options are `{ manifest: "fontawesome.keys.json" }`. With the sources installed, the plugin resolves licensed packages from `fontawesome-pro-sources/` while output guards remain relative to the demo project; Node resolution also finds already installed Free packages in parent workspace directories. Without them, it does not read that directory.
62
62
 
63
63
  Routes are `/icons/fontawesome/free` and `/icons/fontawesome/pro`; `/icons/fontawesome` redirects to Free. The Pro page shows an unavailable state without a licensed profile, never fabricated artwork. Enabling the profile with missing/invalid sources fails the build rather than hiding an error.
64
64
 
@@ -77,7 +77,7 @@ setup_status=$?
77
77
  unset fa_token
78
78
  # Step 4: Start only after successful installation.
79
79
  if [[ $setup_status -eq 0 ]]; then
80
- npm run dev:pro --workspace=@featherk/demos
80
+ npm run dev --workspace=@featherk/demos
81
81
  fi
82
82
  ```
83
83
 
@@ -96,7 +96,7 @@ try {
96
96
  Remove-Item Env:FONTAWESOME_PACKAGE_TOKEN -ErrorAction SilentlyContinue
97
97
  }
98
98
  # Step 4: Start only after successful installation.
99
- npm run dev:pro --workspace=@featherk/demos
99
+ npm run dev --workspace=@featherk/demos
100
100
  ```
101
101
 
102
102
  Do not continue after an install error. `401`/`403` can indicate invalid/revoked credentials or insufficient entitlement. Inspect status codes without printing token/config contents. Missing releases/exports need a source/approval review, not an unpinned upgrade.
@@ -105,11 +105,11 @@ Do not continue after an install error. `401`/`403` can indicate invalid/revoked
105
105
 
106
106
  Consumers need their own covered access or an enterprise agreement that actually covers them. The public FeatherK package grants no Pro rights.
107
107
 
108
- `@featherk/icons` provides `featherk-fontawesome-setup` for consumer setup. Run it through `npx` or an npm script from the application root, once per application, on a developer machine. It reads the UX-provided keys-only manifest (or `--keys a,b`) and pins each package to the exact catalog version. The manifest is the same file the Vite plugin and CLI use: a `free` array of catalog keys plus an optional `pro` array.
108
+ `@featherk/icons` provides `featherk-fontawesome-setup` for consumer setup. Run it through `npx` or an npm script from the application root, on a developer machine. It reads the UX-provided keys-only manifest, the same file the Vite plugin and CLI use (a `free` array of catalog keys plus an optional `pro` array), and pins each package to the exact catalog version.
109
109
 
110
- ### Standard: Free and Pro Together
110
+ ### Default: Isolated Pro Sources
111
111
 
112
- Most applications use both tiers, so the standard setup installs Free and Pro packages together as ordinary `devDependencies`:
112
+ Every application uses this layout unless it has a specific reason not to:
113
113
 
114
114
  ```sh
115
115
  npx featherk-fontawesome-setup --manifest fontawesome.keys.json
@@ -117,63 +117,54 @@ npx featherk-fontawesome-setup --manifest fontawesome.keys.json
117
117
 
118
118
  The command:
119
119
 
120
- 1. Adds these lines to the application's `.npmrc`, creating it if needed. Existing settings are kept, and the lines are not duplicated on later runs:
120
+ 1. Installs the exact Free pins into the application's `devDependencies` from public npm. This step needs no token.
121
+ 2. Writes the exact Pro pins into `fontawesome-pro-sources/`, a private source project next to the application's `package.json`, then installs it with the token from `FONTAWESOME_PACKAGE_TOKEN` or a hidden prompt. The project contains a `package.json`, a `.gitignore` for its `node_modules`, and an `.npmrc` with only the token placeholder:
121
122
 
122
123
  ```ini
123
124
  @fortawesome:registry=https://npm.fontawesome.com/
124
125
  //npm.fontawesome.com/:_authToken=${FONTAWESOME_PACKAGE_TOKEN}
125
126
  ```
126
127
 
127
- 2. Installs the exact Free and Pro pins with `npm install --save-dev --save-exact`, using the token from `FONTAWESOME_PACKAGE_TOKEN` or a hidden prompt.
128
+ Commit `package.json`, `package-lock.json`, and `fontawesome-pro-sources/`, including its `package-lock.json`. Configure the Vite plugin with `featherkFontAwesome({ manifest: "fontawesome.keys.json" })`.
128
129
 
129
- Commit `.npmrc`, `package.json`, and `package-lock.json`. Then configure the Vite plugin with `allowPro: true` and the manifest's Free and Pro keys, without `sourceRoot` or separate Pro scripts.
130
+ The directory name `fontawesome-pro-sources` is fixed, so every team's setup looks the same. The plugin and CLI find the directory themselves, and installing it is what turns Pro icons on. The application's normal `dev` and `build` scripts need no changes:
130
131
 
131
- The scope line routes **all** `@fortawesome` packages, Free included, to the Font Awesome registry. Every install therefore needs `FONTAWESOME_PACKAGE_TOKEN`, and everyone who installs the application needs an applicable seat.
132
+ - **Where `fontawesome-pro-sources/` is installed** (its `node_modules` exists), builds generate the `free` and `pro` keys, resolving Pro packages from it.
133
+ - **Where it is not installed**, builds generate the `free` keys alone and never read it. If a job should have installed it and didn't, code that uses a Pro key fails type checking, because the generated key union then contains only Free keys.
132
134
 
133
- #### Token-Scoped Installs
135
+ The application's own `npm ci` never needs the token, so developers and CI jobs without Pro access can still install it and build Free-only. Only installing `fontawesome-pro-sources/` needs Pro access, and everyone who does, or who builds where it is installed, needs an applicable seat.
134
136
 
135
- `npm ci` runs lifecycle scripts from the application and every dependency, and later build tools run arbitrary Node code. Any of them can read a token in their environment. Log masking and Vite's `VITE_` client-variable filter do not prevent this. Do not export the token persistently or for a whole CI build. Give it only to an install that skips scripts, then run anything that needs scripts without it:
137
+ A build cache keyed on tracked files, such as Turborepo's, must also key on whether the sources are installed, or it can replay a Free build where Pro is expected. Add the install marker that npm writes to the build's inputs, for example in Turborepo:
136
138
 
137
- 1. With the token: `npm ci --ignore-scripts`.
138
- 2. Without the token, run any install scripts the application needs:
139
- - `npm rebuild` runs the dependency install scripts that step 1 skipped. On npm 12 and later, dependency scripts run only when approved in the application's `allowScripts` (`npm install-scripts approve <pkg>`), and `npm rebuild` follows the same approvals. Older npm versions run all of them.
140
- - `npm rebuild` does not run the application's own lifecycle scripts. Run those explicitly, for example `npm run prepare --if-present`.
141
- 3. Without the token: `npm run dev`, `npm run build`, tests, and deployment. npm runs normally when the `.npmrc` placeholder is unset; only `@fortawesome` registry requests need it.
139
+ ```json
140
+ "inputs": ["$TURBO_DEFAULT$", "fontawesome-pro-sources/node_modules/.package-lock.json"]
141
+ ```
142
142
 
143
- Git Bash:
143
+ Keep builds that include Pro icons out of shared or remote caches.
144
144
 
145
- ```bash
146
- read -r -s -p "Font Awesome package token: " fa_token; echo
147
- FONTAWESOME_PACKAGE_TOKEN="$fa_token" npm ci --ignore-scripts
148
- install_status=$?
149
- unset fa_token
150
- [[ $install_status -eq 0 ]] && npm rebuild
151
- ```
145
+ After changing the manifest, rerun the same command. It updates both sets of pins; when the Pro pins change, it removes the stale `fontawesome-pro-sources/package-lock.json` and the install regenerates it. Review and commit the result.
152
146
 
153
- PowerShell:
147
+ On a fresh clone and in CI, run the application's normal `npm ci`, then install the source project from its committed lockfile:
154
148
 
155
- ```powershell
156
- $env:FONTAWESOME_PACKAGE_TOKEN = [System.Net.NetworkCredential]::new(
157
- "", (Read-Host "Font Awesome package token" -AsSecureString)
158
- ).Password
159
- try {
160
- npm ci --ignore-scripts
161
- if ($LASTEXITCODE -ne 0) { throw "Font Awesome package installation failed." }
162
- } finally {
163
- Remove-Item Env:FONTAWESOME_PACKAGE_TOKEN -ErrorAction SilentlyContinue
164
- }
165
- npm rebuild
149
+ ```sh
150
+ npx featherk-fontawesome-setup
166
151
  ```
167
152
 
168
- The setup command follows the same rule. It installs with `--ignore-scripts` and passes the token only to that npm process. For CI, see [TeamCity](#teamcity).
153
+ Without arguments, the command runs `npm ci` in `fontawesome-pro-sources/` with the token, skipping lifecycle scripts and ignoring npm workspace settings. In CI it requires the committed lockfile. See [CI and Deployment](#ci-and-deployment).
169
154
 
170
- Before supplying the token, the command checks `.npmrc`. It refuses any of the following:
155
+ ### Setup Safety Checks
156
+
157
+ Before supplying the token, the command checks `fontawesome-pro-sources/.npmrc`. It refuses any of the following:
171
158
 
172
159
  - a `@fortawesome` registry other than `https://npm.fontawesome.com/`
173
160
  - any reference to `FONTAWESOME_PACKAGE_TOKEN` outside `//npm.fontawesome.com/:_authToken`
174
161
  - any other `npm.fontawesome.com` credential, including a literal token
175
162
 
176
- It also pins the Font Awesome registry on the npm command line, which overrides other npm configuration. The token therefore can only be sent to Font Awesome. The command refuses to run in CI, because it changes `package.json`. It installs with `--ignore-scripts`, so lifecycle scripts never run while the token is present, and it never prints the token. The isolated source-project install applies the same checks, and also requires both Font Awesome lines.
163
+ It also pins the Font Awesome registry on the npm command line, which overrides other npm configuration, so the token can only be sent to Font Awesome. It installs with `--ignore-scripts`, so lifecycle scripts never run while the token is present, passes the token only to that npm process, and never prints it. Setup with `--manifest` changes `package.json`, so it refuses to run in CI.
164
+
165
+ `npm ci` lifecycle scripts and build tools run arbitrary Node code that can read any token in their environment, and log masking does not prevent that. Give the token only to `featherk-fontawesome-setup`, never to the application's `npm ci`, its build, or a whole CI job, and do not export it persistently.
166
+
167
+ The application's own `.npmrc` must not route `@fortawesome` to a registry: Free packages come from public npm, and Pro packages only from `fontawesome-pro-sources/`. Setup refuses an application whose `.npmrc` does. That includes an application set up with the `--pro-in-app` option, which shipped in 0.16.0 and was then removed; remove the Font Awesome lines from its `.npmrc` and any `@fortawesome/pro-*` packages from its `devDependencies`, then rerun setup with `--manifest`.
177
168
 
178
169
  ### Exception: Free Only
179
170
 
@@ -183,31 +174,20 @@ For an application that will use only Free icons:
183
174
  npx featherk-fontawesome-setup --manifest fontawesome.keys.json --free-only
184
175
  ```
185
176
 
186
- Free packages come from public npm. The command writes no `.npmrc` lines and needs no token or CI configuration. It fails if the manifest contains Pro keys, or if `.npmrc` already routes `@fortawesome` to a registry. Leave `allowPro` unset.
177
+ Free packages come from public npm. The command needs no token or CI configuration and creates no source project. The default command behaves the same way for a manifest without Pro keys; `--free-only` also guarantees it, failing if the manifest contains Pro keys, if `fontawesome-pro-sources/` exists, or if `.npmrc` routes `@fortawesome` to a registry. Configure the Vite plugin with `{ manifest: "fontawesome.keys.json" }`. To add Pro later, add the keys to the manifest and rerun without `--free-only`.
187
178
 
188
- Free-only is a per-application choice, not a per-developer one. In a Free and Pro application, the lockfile resolves Free packages through the Font Awesome registry, so a developer without the token cannot install that application. To move a Free-only application to Pro later, add the Pro keys to the manifest and rerun the command without `--free-only`, then add the CI token parameter.
179
+ ### Generation and Licensing Boundaries
189
180
 
190
- ### Optional Pro: Isolated Source Project
181
+ Keep Pro keys in the manifest's `pro` group. Public or uncredentialed builds must not include paid inputs: run them where `fontawesome-pro-sources/` is not installed.
191
182
 
192
- Some projects must keep Pro optional so normal installs never need a token. FeatherK's own demos work this way. They install Pro packages into a separate private project and pass `sourceRoot` to the Vite plugin only in an authorized profile, for example `featherkFontAwesome({ keys, allowPro: true, sourceRoot: "pro" })`. The same command supports this layout:
193
-
194
- ```sh
195
- # Scaffold .npmrc (token placeholder only), package.json with exact Pro pins, and .gitignore.
196
- npx featherk-fontawesome-setup --source-root fontawesome-pro-sources --init --manifest fontawesome.keys.json
197
- # Install with the token; this creates fontawesome-pro-sources/package-lock.json.
198
- npx featherk-fontawesome-setup --source-root fontawesome-pro-sources
199
- ```
200
-
201
- Commit the scaffolded files and the lockfile. `--init` pins only Pro keys, because Free packages belong in the application's own `devDependencies`. It refuses to overwrite existing files unless you pass `--force`, and it needs no token. When `--init --force` changes the dependencies, for example by adding a Pro package, it removes the now-stale `package-lock.json`. The next install then regenerates it with `npm install`; review and commit the new lockfile. After editing the source project's `package.json` by hand, run the install with `--refresh-lock` to update the lockfile. Later runs use `npm ci` in the source project and remove npm workspace settings, so `--workspace` invocations target only that project. In CI, `--init` and `--refresh-lock` are refused and the lockfile is required. The application's own `npm ci` needs no token. CI adds a separate token-scoped install step for the source project before the Pro build.
202
-
203
- Keep Pro keys in the manifest's `pro` group and include them only in the authorized profile. Optional profiles must not silently include paid inputs in public/uncredentialed builds. The `dev:pro`/`build:pro` profile scripts above are repository demo helpers.
204
-
205
- For non-Vite applications or declaration generation before a standalone type check, follow [CLI and non-Vite setup](FontAwesomeCLI.md). Registry authentication still belongs to the authorized package installation environment; the generator and browser never receive the token. The `allowPro` option prevents accidental selection; it does not verify license entitlement. Follow the [generated-output ignore guidance](FontAwesome.md#generated-output-and-source-checks): exclude generated files from ESLint/Prettier/Git while retaining TypeScript checks.
183
+ For non-Vite applications or declaration generation before a standalone type check, follow [CLI and non-Vite setup](FontAwesomeCLI.md). Registry authentication still belongs to the authorized package installation environment; the generator and browser never receive the token. Listing a key under `pro`, and installing `fontawesome-pro-sources/` only where Pro is wanted, prevent accidental selection; they do not verify license entitlement. Follow the [generated-output ignore guidance](FontAwesome.md#generated-output-and-source-checks): exclude generated files from ESLint/Prettier/Git while retaining TypeScript checks.
206
184
 
207
185
  ## CI and Deployment
208
186
 
209
187
  FeatherK and `feather-k-<demo-name>` repositories use GitHub Actions. TeamCity applies only to enterprise apps using that platform.
210
188
 
189
+ A build that includes Pro icons has three steps: the application's normal `npm ci` without the token, a token-scoped `npx featherk-fontawesome-setup` that installs `fontawesome-pro-sources/` from its lockfile, and the application's normal build without the token. Builds that don't need Pro icons skip the middle step and come out Free-only.
190
+
211
191
  Use a dedicated trusted Actions job with a protected Environment and approval/branch rules. Supply the token only to source installation, not public publishing or client compilation. After checkout and Node/root dependency setup:
212
192
 
213
193
  ```yaml
@@ -217,39 +197,38 @@ Use a dedicated trusted Actions job with a protected Environment and approval/br
217
197
  NPM_CONFIG_CACHE: ${{ runner.temp }}/fontawesome-pro-cache
218
198
  run: npm run setup:fontawesome:pro --workspace=@featherk/demos
219
199
  - name: Build licensed demo application
220
- run: npm run build:pro --workspace=@featherk/demos
200
+ run: npm run build --workspace=@featherk/demos
221
201
  ```
222
202
 
223
- In CI, detected from `CI`, `TEAMCITY_VERSION`, or `GITHUB_ACTIONS`, the setup command refuses app-root setup and `--init`, and an isolated install requires the committed `package-lock.json`. Unattended jobs therefore only run a locked `npm ci` and never resolve new versions. In every layout, supply the token only to the install step that skips lifecycle scripts, never to the whole job. See [Token-Scoped Installs](#token-scoped-installs). With no token and no interactive terminal, the command fails instead of prompting.
203
+ In CI, detected from `CI`, `TEAMCITY_VERSION`, or `GITHUB_ACTIONS`, the setup command refuses `--manifest` setup, and the source-project install requires the committed `package-lock.json`. Unattended jobs therefore only run a locked `npm ci` and never resolve new versions. Supply the token only to the `featherk-fontawesome-setup` step, never to the whole job. With no token and no interactive terminal, the command fails instead of prompting.
224
204
 
225
205
  Configure the protected Environment separately; this fragment grants no license rights. Restrict paid caches/archives/artifacts, and never execute untrusted PR code with the token, including via `pull_request_target`. Normal public FeatherK publishing must not receive Pro credentials or use the licensed profile.
226
206
 
227
207
  ### TeamCity
228
208
 
229
- Do not define the token as an `env.` parameter. TeamCity passes `env.` parameters to every step in the build, so build tools and lifecycle scripts could read the token. Instead, scope it to the install step:
209
+ Do not define the token as an `env.` parameter. TeamCity passes `env.` parameters to every step in the build, so build tools and lifecycle scripts could read the token. Instead, scope it to one install step:
230
210
 
231
211
  1. In the build configuration, add a parameter named `fontawesome.package.token` with type **Password**. Use no `env.` prefix, so TeamCity does not export it to the steps' environment.
232
- 2. Change the existing install step to a Command Line step that sets the variable for the install command only. Each Command Line step runs in its own process, so the variable does not carry into later steps.
212
+ 2. Add a Command Line step that sets the variable for one command only. Each Command Line step runs in its own process, so the variable does not carry into later steps.
233
213
 
234
- Linux agent:
214
+ Leave the application's existing `npm ci` step unchanged and add this step after it:
235
215
 
236
216
  ```sh
237
- FONTAWESOME_PACKAGE_TOKEN='%fontawesome.package.token%' npm ci --ignore-scripts
217
+ # Linux agent
218
+ FONTAWESOME_PACKAGE_TOKEN='%fontawesome.package.token%' npx featherk-fontawesome-setup
238
219
  ```
239
220
 
240
- Windows agent:
241
-
242
221
  ```bat
222
+ rem Windows agent
243
223
  set "FONTAWESOME_PACKAGE_TOKEN=%fontawesome.package.token%"
244
- npm ci --ignore-scripts
224
+ npx featherk-fontawesome-setup
245
225
  ```
246
226
 
247
- 3. If the application or its dependencies need install scripts, add a step without the token. Use `npm rebuild` for dependency scripts, which follows `allowScripts` approvals on npm 12 and later. Run the application's own scripts explicitly, for example `npm run prepare --if-present`, because `npm rebuild` does not run them. See [Token-Scoped Installs](#token-scoped-installs).
248
- 4. Leave the build, test, and deploy steps unchanged. They never reference the parameter.
227
+ Leave the build step unchanged: with the sources installed, the normal build includes the Pro icons.
249
228
 
250
- Password parameters are masked in build logs, but masking does not stop code running in a step from reading the value. TeamCity also writes the step script, with the substituted value, to a temporary file on the agent. Limit the parameter to trusted build configurations and agents, and never run untrusted pull-request code in a build that defines it. Build agents must be able to reach `npm.fontawesome.com`.
229
+ 3. Leave the build, test, and deploy steps free of the parameter. They never reference it.
251
230
 
252
- This applies to the [standard Free and Pro setup](#standard-free-and-pro-together). For the [isolated source project](#optional-pro-isolated-source-project), the app's normal install needs no token. Add a separate token-scoped step that runs the source install script, for example `npm run fontawesome:install:pro`, before the Pro build. [Free-only](#exception-free-only) applications need no TeamCity configuration.
231
+ Password parameters are masked in build logs, but masking does not stop code running in a step from reading the value. TeamCity also writes the step script, with the substituted value, to a temporary file on the agent. Limit the parameter to trusted build configurations and agents, and never run untrusted pull-request code in a build that defines it. Build agents must be able to reach `npm.fontawesome.com`. [Free-only](#exception-free-only) applications need no TeamCity configuration.
253
232
 
254
233
  Tokens do not expand Creator seats.
255
234
 
@@ -259,6 +238,6 @@ Enterprise Pages must enforce authentication on deployed URLs/static assets; rep
259
238
 
260
239
  Public `@featherk/icons` artifacts contain tooling and owned icons only: no paid dependencies/artwork, source caches, credentials, or generated paid-icon collections. Private distribution alone does not establish entitlement.
261
240
 
262
- Isolated-source resolution uses synthetic tests. Free generation and Pro-unavailable UI can be checked without secrets. Real paid exports, license notices, and enabled Pro rendering remain unverified until an authorized installation succeeds. Pro+ collections requiring Kits remain outside this no-Kit implementation.
241
+ Automated tests use synthetic packages, so public CI needs no secrets. On October 15, 2026, an authorized installation of `demos/fontawesome-pro-sources` was checked locally: `npm run verify:fontawesome --workspace=@featherk/demos` verified all 14 demo selections, including the four Pro exports, against the installed packages (path data, viewBox, version, and style), and the build emitted both the Free and Pro license notices. Rendering of the Pro page in a browser was not part of that check. Re-run the verification after changing pins. Pro+ collections requiring Kits remain outside this no-Kit implementation.
263
242
 
264
- References: [package authentication](https://docs.fontawesome.com/web/setup/packages), [Pro license](https://fontawesome.com/license), and [Font Awesome account](https://fontawesome.com/account).
243
+ References: [package authentication](https://docs.fontawesome.com/web/setup/packages), [Pro license](https://fontawesome.com/license), and [Font Awesome account](https://fontawesome.com/account).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featherk/icons",
3
- "version": "0.15.8",
3
+ "version": "0.16.1",
4
4
  "main": "dist/featherk-icons.umd.js",
5
5
  "module": "dist/featherk-icons.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,20 +0,0 @@
1
- import { readFile } from "node:fs/promises";
2
- const isKeyList = (value) => Array.isArray(value) && value.every((key) => typeof key === "string");
3
- function parseFontAwesomeManifest(manifest) {
4
- if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
5
- throw new Error("Font Awesome manifest must be a JSON object");
6
- }
7
- const { free, pro } = manifest;
8
- if (!isKeyList(free) || pro !== void 0 && !isKeyList(pro)) {
9
- throw new Error(
10
- 'Font Awesome manifest must contain "free" and optional "pro" key arrays'
11
- );
12
- }
13
- return { free, pro: pro ?? [] };
14
- }
15
- async function readFontAwesomeManifest(path) {
16
- return parseFontAwesomeManifest(JSON.parse(await readFile(path, "utf8")));
17
- }
18
- export {
19
- readFontAwesomeManifest as r
20
- };
@@ -1,19 +0,0 @@
1
- "use strict";
2
- const promises = require("node:fs/promises");
3
- const isKeyList = (value) => Array.isArray(value) && value.every((key) => typeof key === "string");
4
- function parseFontAwesomeManifest(manifest) {
5
- if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
6
- throw new Error("Font Awesome manifest must be a JSON object");
7
- }
8
- const { free, pro } = manifest;
9
- if (!isKeyList(free) || pro !== void 0 && !isKeyList(pro)) {
10
- throw new Error(
11
- 'Font Awesome manifest must contain "free" and optional "pro" key arrays'
12
- );
13
- }
14
- return { free, pro: pro ?? [] };
15
- }
16
- async function readFontAwesomeManifest(path) {
17
- return parseFontAwesomeManifest(JSON.parse(await promises.readFile(path, "utf8")));
18
- }
19
- exports.readFontAwesomeManifest = readFontAwesomeManifest;