@integr8-media/config 1.1.0 → 1.2.0

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.
package/README.md CHANGED
@@ -291,6 +291,157 @@ git push origin v1.0.1
291
291
  A package without Trusted Publishing can still pass `secrets: { NPM_TOKEN: ... }` to
292
292
  `publish.yml`.
293
293
 
294
+ ## Registry site
295
+
296
+ Feature packages that ship a shadcn registry also publish a static site on GitHub Pages: a landing
297
+ page, one docs page per item, the registry JSON (`r/`) and a Ladle playground that the pages embed
298
+ for live previews. The generator lives here, so a new package gets the site without copying files.
299
+ It needs `typescript` installed (it reads the TSDoc comments with the TypeScript parser).
300
+
301
+ What a package repo adds:
302
+
303
+ ```js
304
+ // registry/site.config.mjs
305
+ import { defineRegistrySite } from '@integr8-media/config/registry-site';
306
+
307
+ export default defineRegistrySite({
308
+ brand: { name: 'Integr8 Window Manager', slug: 'window-manager' },
309
+ categories: [
310
+ ['shell', 'Shell'],
311
+ ['window', 'Windows'],
312
+ ],
313
+ stories: { window: ['--window-'], taskbar: ['--taskbar-'] },
314
+ ui: { registryUrl: 'https://minalouisleon.github.io/integr8-ui/r' },
315
+ });
316
+ ```
317
+
318
+ ```json
319
+ // package.json
320
+ "scripts": {
321
+ "site:build": "integr8-registry-site build",
322
+ "site": "integr8-registry-site dev"
323
+ }
324
+ ```
325
+
326
+ ```yaml
327
+ # .github/workflows/registry.yml
328
+ name: Registry
329
+ on:
330
+ push:
331
+ branches: [main]
332
+ workflow_dispatch:
333
+ permissions: # the reusable workflow cannot grant itself more than this
334
+ contents: read
335
+ pages: write
336
+ id-token: write
337
+ jobs:
338
+ site:
339
+ uses: <owner>/integr8-config/.github/workflows/registry-site.yml@v1
340
+ ```
341
+
342
+ The repo still owns `scripts/buildRegistry.mjs` (it turns the source into `dist/registry/`). The
343
+ site generator only reads its output.
344
+
345
+ ### Commands
346
+
347
+ | Command | What it does |
348
+ | --- | --- |
349
+ | `integr8-registry-site build` | Runs `commands.assets` (if set), builds the Ladle playground, runs `commands.registry`, writes `site/` |
350
+ | `integr8-registry-site dev` | `build` for `http://localhost:4173/`, then serves `site/` (`PORT=5000` to change) |
351
+ | `integr8-registry-site serve` | Serves an existing `site/` |
352
+ | `integr8-registry-site enabled` | Prints `true` or `false` (the on/off switch) |
353
+ | `integr8-registry-site size [exports…]` | Bundle-size breakdown (needs `bundleSizes` in the config) |
354
+
355
+ Options: `--config <file>`, `--site-base-path <path>`, `--no-playground`.
356
+
357
+ ### Turn the site off
358
+
359
+ One setting, in `package.json`:
360
+
361
+ ```json
362
+ "integr8": { "site": false }
363
+ ```
364
+
365
+ - A missing key means on. Only a JSON boolean is accepted: `"site": "false"` is an error, so a typo
366
+ never silently builds or skips the site.
367
+ - The workflow's `settings` job reads it first. When it is `false`, the `build` and `deploy` jobs
368
+ are skipped and the run still succeeds (green, with a notice).
369
+ - Every `integr8-registry-site` command prints a note and exits with code 0, so `npm run site` and
370
+ `npm run site:build` pass too.
371
+ - `pr-checks.yml` has an input `site-build` (default `false`). When a repo turns it on, it runs
372
+ `npm run site:build`, which obeys the same switch.
373
+ - A package that has no site needs only this line: no config file, no workflow call.
374
+
375
+ There is deliberately no second switch (no `enabled` input, no `SITE_ENABLED` variable): two
376
+ settings can disagree, and one committed line is easy to review. To switch the site off for a
377
+ while, commit the one line.
378
+
379
+ ### Config reference
380
+
381
+ `registry/site.config.mjs` default-exports `defineRegistrySite({...})`. Only `brand.name` is
382
+ required; every other option has a default. Bad input throws `ConfigError` (`INVALID_OPTION`)
383
+ naming the option, such as `registry-site config: "brand.name" is required and must be a non-empty string.`
384
+ Unknown options are errors too (typo guard).
385
+
386
+ | Option | Meaning | Default |
387
+ | --- | --- | --- |
388
+ | `brand.name` | Product name, in titles and labels | required |
389
+ | `brand.slug` | Shown after `integr8/` in the header | name without "Integr8", kebab-case |
390
+ | `brand.mark` | Letters in the header badge | `i8` |
391
+ | `brand.eyebrow` | Text above the hero title (`· v<version>` is added) | `Registry` |
392
+ | `brand.heroTitle`, `brand.heroAccent` | Hero title; the accent is shown in the brand gradient | name, no accent |
393
+ | `brand.lead` | Text under the hero title | `description` of `package.json` |
394
+ | `brand.title`, `brand.description` | Landing page `<title>` and meta description | name, `package.json` description |
395
+ | `brand.footer` | Footer start; `{packageName}` and `{version}` are filled in | `{packageName} · v{version}` |
396
+ | `brand.repositoryUrl` | GitHub link in the header | `$GITHUB_REPOSITORY`, else `repository` in `package.json` |
397
+ | `brand.playgroundLink` | "Playground" link in the header | `false` |
398
+ | `brand.extraStats` | Extra hero numbers, `[{ value, label }]` | none |
399
+ | `brand.heroCommand` | Command in the hero | command of the last setup step |
400
+ | `categories` | Ordered `[id, label]` pairs, matched against each item's first category; the rest go under "Other" | categories found in the registry, in order |
401
+ | `stories` | Item → parts of Ladle story ids (a story matches when its id contains a part), or a function `(item) => parts`. Items not listed have no preview | stories whose id starts with `<item>--` |
402
+ | `defaultStory` | Story shown first in the landing preview: an item name or a story id | first story |
403
+ | `ui` | `{ registryUrl, docsUrl?, packageName? }`: the ui registry the items depend on. Ui items link to the ui site, with the ui theme step. Leave out in the ui package | none |
404
+ | `fonts` | `'copy-from-ui'` (copy `dist/fonts.css` and `dist/fonts/` from the installed ui package), `'build'` (copy the ones this repo built into `dist/`), `false` (system fonts) | `'copy-from-ui'` with `ui`, else `false` |
405
+ | `setup` | "Get started": `steps` (`{ title, text?, command }`), `extras` (`{ title, text?, code, caption? }`), `namespace` (alias in `components.json`), `shortNames`, `title`, `accent`, `lead`. Text, commands and code may use `{registryUrl}`, `{uiRegistryUrl}`, `{version}`, `{packageName}`; other `{...}` stay as written | shadcn init, ui theme (with `ui`), add the first item |
406
+ | `copy` | `previewLead`, `componentsLead`: longer landing texts | generic texts |
407
+ | `previewThemes` | `[id, label]` pairs: adds a theme switcher to the previews (`&integr8Theme=<id>`) | none (no switcher) |
408
+ | `themeNote` | `{ item, skip? }`: "add the theme first" note on item pages; `false` for none | the ui theme with `ui`, else none |
409
+ | `bundleSizes` | `{ entry?, ownCodeLabel?, external? }` for `integr8-registry-site size` (esbuild comes with `@size-limit/esbuild`); `false` for off | off |
410
+ | `commands` | `assets` (for example `node scripts/buildAssets.mjs`, needed with `fonts: 'build'`) and `registry` | registry: `node scripts/buildRegistry.mjs` |
411
+ | `registryUrl` | Where `r/` is served; `{name}` and `{version}` are filled in. `REGISTRY_BASE_URL` wins | GitHub Pages URL from `repository` |
412
+ | `playground` | Build and embed the Ladle playground | `true` |
413
+
414
+ Programmatic use: `buildRegistrySite(options)` writes the site, and `renderSiteFiles(input)` returns
415
+ the pages without touching the file system (pure, for tests).
416
+
417
+ ### Move the site
418
+
419
+ Set two repository variables (Settings → Secrets and variables → Actions → Variables), or pass
420
+ the same values as workflow inputs `registry-base-url` and `site-base-path`:
421
+
422
+ - `REGISTRY_BASE_URL`: full URL of the JSON folder, such as `https://integr8-media.com/ui/r`.
423
+ - `SITE_BASE_PATH`: the path the site is served from, such as `/ui/`.
424
+
425
+ Without them the site is served at `https://<owner>.github.io/<repo>/`.
426
+
427
+ ### One-time Pages setup
428
+
429
+ In the calling repo, Settings → Pages → Source: **GitHub Actions**. Without it `configure-pages`
430
+ fails ("Get Pages site failed"). The calling workflow must also grant `pages: write` and
431
+ `id-token: write`: a reusable workflow cannot raise its own permissions, and a caller that grants
432
+ less fails at startup.
433
+
434
+ ### Local preview and the `--base` pitfall
435
+
436
+ `npm run site` builds the site and serves it on `http://localhost:4173/`.
437
+
438
+ The Ladle playground must be built with `--base <site path>playground/`. Without it, its HTML asks
439
+ for `/assets/...`, which is a 404 under `site/playground/`, so every preview iframe is blank. By
440
+ design, `integr8-registry-site` always passes the right base: `/playground/` locally,
441
+ `${SITE_BASE_PATH}playground/` in CI. If a playground built the wrong way is already in
442
+ `playground/dist`, the site build stops with `PLAYGROUND_BASE_MISMATCH` and the exact command to
443
+ fix it, instead of publishing blank previews. Do not run `ladle build` yourself for the site.
444
+
294
445
  ## API
295
446
 
296
447
  | Import | Exports |
@@ -298,6 +449,9 @@ A package without Trusted Publishing can still pass `secrets: { NPM_TOKEN: ... }
298
449
  | `@integr8-media/config/vitest` | `integr8Vitest(options?)`, `ConfigError` |
299
450
  | `@integr8-media/config/tsdown` | `integr8Tsdown(options)`, `ConfigError` |
300
451
  | `@integr8-media/config/size-limit` | `integr8SizeLimit(entries)`, `ConfigError` |
452
+ | `@integr8-media/config/registry-site` | `defineRegistrySite(config)`, `buildRegistrySite(options)`, `renderSiteFiles(input)`, `readSiteSwitch(pkg)`, `RegistrySiteError`, `ConfigError`, … (see the API reference) |
453
+
454
+ The package also has a command, `integr8-registry-site` (see [Registry site](#registry-site)).
301
455
 
302
456
  Invalid options throw `ConfigError` with `code: 'INVALID_OPTION'`. The API reference is
303
457
  generated from TSDoc with `npm run docs` (output in `docs/api/`).