---
title: "v1.6.0"
description: "The Payload admin on a diet (a 30-section page drops from 83 MB to 19.4 MB), plus a multi-pack icon picker, tier-aware blocks, cookie consent and `systhema doctor`."
requested_language: sk
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/sk/changelog/v1.6.0
version: changelog
docs_index: https://docs.systhema.app/sk/llms.txt
---
> This page isn't translated yet. Showing English.


## ✨ Highlights

This release puts the **Payload admin on a diet**. Three changes work together to cut the warm `/admin/collections/pages/[id]` response on a 30-section synthetic page from **83 MB → 19.4 MB** (−77%) and the warm TTFB from **~1.7 s → ~360 ms** (−79%):

1. A targeted `pnpm patch` against `@payloadcms/richtext-lexical` that memoizes `initLexicalFeatures` per request and runs a content-keyed dedup pass on every `featureClientSchemaMap`.
2. A lazy-mount shell for `region` / `fragment` / `slot` Lexical editors so nested editors below the fold don't pay their hydration cost until they scroll into view.
3. The public site no longer pulls the admin import map, the admin-bar CSS, or the live-preview CSS into anonymous-visitor bundles — public homepage drops from 27 → 12 chunks and 5.10 MB → 2.27 MB.

Alongside the perf work: a **multi-pack icon picker** (Font Awesome + Material Symbols + custom packs), a new `.systhema/artifacts/` directory that survives `pnpm install`, a `generate-references` CLI command that emits TOON files for agents, a top-layer `@layer app` cascade slot for project-specific overrides, and a **homepage picker** in General Settings that promotes any page to `/` with automatic link rewrites and a 308 redirect from its own slug.

The biggest structural change is **tier-aware blocks**: the old `root*`/`region*`/`fragment*`/`nested*`/`*InStack` block-slug proliferation collapses into one canonical block per concept whose fields gate themselves by editor depth — a breaking slug rename that `systhema upgrade` migrates automatically (stored Lexical content rewritten in place, no manual step). Plus a real **figure-breakout** CSS contract so `container`/`screen`-width media escapes narrow column tracks, with sub-track left/center/right alignment.

### Multi-pack Icon Picker (FA + Material Symbols + Custom)

The PayloadCMS icon picker gains **Google Material Symbols** as a first-class bundled pack alongside Font Awesome, plus an escape hatch for **custom SVG packs**. The admin editor gets a tab-based picker with smarter tokenized search, and each block type (Button, Chip) can ship a **default icon** for newly created instances.

Zero icon-pack code leaks into the frontend bundle — packs are loaded dynamically in admin only, and the public render is fully server-side.

```ts
withSysthema(baseConfig, {
  // Everything optional — defaults give you FA Solid + Brands
  // and Material Symbols Outlined 400 without writing any `icons` config.
  icons: {
    fontAwesome: { styles: ['solid', 'regular', 'brands'] },
    materialSymbols: { style: 'rounded', weight: 300, fill: true },
    custom: [
      { id: 'my-pack', label: 'Company Icons', icons: { myLogo: '<svg…></svg>' } },
    ],
  },
  button: { defaultIconAfter: 'fa-solid:faArrowRight' },
  chip:   { defaultIconBefore: 'material-symbols:tag' },
})
```

Per-instance pack overrides on `iconPickerField`:

```ts
iconPickerField({
  name: 'icon',
  packs: {
    fontAwesome: false,
    materialSymbols: { weight: 200 },
    custom: [{ id: 'company', label: 'Company', icons: { logo: '<svg…/>' } }],
  },
})
```

**Material Symbols variant swaps propagate automatically.** Picks are stored as identifier-only (`{"id":"material-symbols:arrow_forward"}`); the render path looks up the SVG on every render from the active variant's digest. Change `weight: 400 → 200` in `payload.config.ts`, redeploy, every MS icon swaps. All 7 weights × 3 styles × 2 fills (42 digests) ship in `dist/`.

> The Material Symbols **Grade** axis (`-25` / `0` / `200`) is not supported — the static SVG packages only expose style + fill. See `docs/payload/editor/icons.md` FAQ.

Full reference: [`docs/payload/editor/icons.md`](../payload/editor/icons.md).

### Cookie consent integration (#53)

A consent-scanner + Payload-controlled cookie banner ships as an opt-in feature. Marketing copy and toggles live in `generalSettings` (new Payload global section); the scanner classifies cookies into Necessary / Functional / Statistics / Marketing and respects the user's choice. The `add-cookie-consent-to-next-layout` codemod (run by `systhema upgrade`) inserts the provider into existing projects' root layout.

### Tier-aware blocks — one definition per concept, fields gated by depth (#74)

Media and rich-content blocks no longer ship a separate definition per editor depth. A single canonical block (`image`, `video`, `youtube`, `googleMap`, `embed`, `card`, `columns`, `carousel`, `form`) now carries every tier's fields, gated by a reactive `_tier` field so the admin form hides what doesn't apply at the current depth, and the JSX converters branch on `_tier` to render correctly everywhere:

| Tier     |   Width radio   | Width type/value | Sub-track alignment | Section-style (padding/theme/layoutBg) | Stack-layout |
| -------- | :-------------: | :--------------: | :-----------------: | :------------------------------------: | :----------: |
| root     |       ✅        |        ✅        |         ✅          |          ✅ (`columns` only)           |      ❌      |
| region   |       ✅        |        ✅        |         ✅          |                   ❌                   |      ❌      |
| fragment |       ❌        |        ❌        |         ❌          |                   ❌                   |      ❌      |
| stack    | media size only | ✅ (image only)  |         ❌          |                   ❌                   |      ✅      |

`_tier` is owned end-to-end by the server: an `injectTier` walker runs in the Pages collection's `afterRead` (backwards-compatible with un-migrated content) and `beforeChange` (authoritative recompute from the live tree). The walker descends both Lexical sub-editor states and Payload `type: 'blocks'` arrays (so Stack items get `_tier='stack'`).

### `systhema doctor` — unified project-health checks with auto-fix (#86)

One command to answer "is this project healthy, and can you fix it?". `systhema doctor` runs a registry of checks and reports them grouped by severity:

```bash
systhema doctor                  # grouped health report
systhema doctor --fix            # interactively resolve the fixable findings (git-safe)
systhema doctor --json | jq …    # machine-readable, read-only
```

It covers pending migrations / dependency drift, missing or outdated peer dependencies, legacy or missing token files, configuration and artifact sanity, and whether a newer CLI is available. With `--fix` it resolves the auto-fixable findings by delegating to the existing engines — `systhema upgrade`, peer-dependency bumps, `migrate-tokens`, and `sync` — never re-implementing a fixer, and following the same git-safety preflight as `upgrade`. Detection is entirely CLI-side, so it still works when the project's installed `@systhemaui/core` is broken.

The other commands (`info`, `upgrade --dry-run`, `create`, and the proxied `sync` / `copy-files` / `generate-types` / `migrate-tokens`) now emit a single throttled one-line nudge toward `systhema doctor --fix` when a project has fixable issues. The nudge only runs fast, local checks (never the network), is cached for six hours per project, and can be silenced with `SYSTHEMA_NO_DOCTOR=1`, in CI, or with `--json`.

### `systhema create` rounded out — runnable on first `pnpm dev` (#89)

`systhema create` now produces a project you can `cd` into and run with no further setup, and a fresh scaffold passes `systhema doctor` cleanly. Two changes:

- **Agent-skills install for every template.** The flow offers to install Systhema agent skills (Next.js and Payload alike), mirroring `systhema skills install` — prompts for agent target(s), defaults to the cross-agent `.agents/` location, installs before `git init` so they're in the first commit. Flags: `--skills` / `--no-skills`, `--skill-agents <list>`.
- **A complete Payload questionnaire.** Database (SQLite default / Postgres), email (Resend / SendGrid / SMTP / None), Google Maps, and form captcha (none / reCAPTCHA / Turnstile / both), with `PAYLOAD_SECRET` + `SYSTHEMA_API_SECRET` auto-generated. Only the packages you pick are installed — the db/email adapters live in `src/payload/database.ts` / `src/payload/email.ts` modules that `create` regenerates per choice and the matching `@payloadcms/*` dep is swapped in before install. A fresh `.env` is generated from the answers; template-local `.env` files are never copied into a scaffold. Every credential is settable non-interactively via flags (`--db`, `--db-url`, `--email`, `--captcha`, `--maps-key`) or env vars.

### Redesigned `systhema info` + human-only branded header (#92)

`systhema info` is rebuilt into a `doctor`-style sectioned diagnostic — **CLI** (version + install kind, registry reachability/latency, update-available hint), **Project** (root, humanized type, systhema-vs-CLI version drift, the version the tokens were generated at, Payload connections), **Skills** (how many installed + for which agents), and **Health** (an error/warning summary from the same fast offline checks `doctor` runs). The `--json` output is **extended, not restructured** (new additive fields `cli.installKind`, `project.tokens`, `project.connections`, top-level `health`), so existing consumers keep working.

The branded `SYSTHEMA` header now renders **only when stdout is a TTY** — a human at a terminal sees it; agents, CI, pipes, and `--json` don't. All header call sites (`create`, `upgrade`, `self-update`, `doctor`, `info`, top-level help) route through one gate; also silenceable with `SYSTHEMA_NO_BANNER=1`. (Note: `doctor` used to print the header unconditionally; it's now gated like everything else — intentional.)

### Admin RSC payload cut ~77% on a 30-section page (#71)

A targeted `pnpm patch` against `@payloadcms/richtext-lexical@3.84.1` ships inside `@systhemaui/payload` and a new `install-lexical-schema-dedup-patch` codemod adds it to consumers' `patches/` + `pnpm.patchedDependencies` on `systhema upgrade`. The patch does two things:

1. **Memoizes `initLexicalFeatures`** by `(sanitizedEditorConfig, clientFieldSchemaMap, schemaPath)`. Identical-shape editors at the same schema location now share one object reference, so React Flight collapses what used to be 29 × 1.83 MB into 1 × 1.83 MB + 28 × ~25 KB references.
2. **Content-keyed dedup pass** on every `featureClientSchemaMap`. The values _inside_ a single editor's map are themselves ~99% structurally identical (300-ish distinct values across 30K positions in the root editor map); a per-request `Map<hash, firstValue>` collapses them.

Measured against `templates/payload`, 30-section seeded page:

|                    |   before |    after | Δ                    |
| ------------------ | -------: | -------: | -------------------- |
| total inline RSC   | 83.36 MB | 19.37 MB | **−63.99 MB / −77%** |
| warm response      | ~1700 ms |  ~358 ms | **−79%**             |
| dominant chunk     | 27.90 MB | 27.90 MB | unchanged (root)     |
| 0-section baseline | 28.34 MB | 19.37 MB | **−32%**             |

Functionally a no-op: no UX changes, no admin behaviour changes, no Payload version bump. Cache is module-level with WeakMap roots so it follows normal GC semantics.

The patch is version-locked — when `@systhemaui/payload` bumps the bundled `@payloadcms/richtext-lexical`, the patch is regenerated and the codemod's `PATCH_TARGET_VERSION` constant moves in lockstep. Consumers on the previous Payload version see "version mismatch — skipped" and stay on the unpatched runtime until they bump too. Re-running the codemod against an already-patched project is a no-op.

### Lazy-mount nested Lexical editors (#71)

`region` / `fragment` / `slot` editor factories now wrap their `FieldComponent` in a lazy-mount shell (`@systhemaui/payload/admin/components/RscEntryLazyLexicalField`). It forwards every prop unchanged to Payload's own `RscEntryLexicalField` — server-side feature resolution and form-state build still happen — but the client component holds the rendered tree behind a placeholder until an `IntersectionObserver` fires or the user clicks/focuses it. Once mounted, the editor stays mounted; scrolling away does not unmount.

The root editor is **not** wrapped (it's always above the fold on a page edit).

Verified end-to-end against a 30-section page: 30 nested placeholders render initially, only those within ~400 px of the viewport hydrate, and once mounted the editor is fully editable. Server payload, schema map, and warm response time are unchanged — this is purely a client-hydration win — but it removes the dominant TBT bottleneck on long documents.

`withLazyMount` also wraps the editor descriptor's `generateImportMap`, so the new component path is registered in projects' `importMap.js` on the next `payload generate:importmap` (which `pnpm sync` already runs).

## ⬆️ Upgrade

If you're on **1.5.x** and want to land on 1.6.0:

```bash
# Update the global CLI first so it carries the 1.6.0 migrations.
pnpm add -g @systhemaui/cli@latest

# Then upgrade your project. Plan first; commit a clean tree before running for real.
cd <your-project>
systhema upgrade --dry-run
systhema upgrade --yes
```

The upgrade will:

1. Bump `@systhemaui/core`, `react`, `next`, `payload`, and the peer-dep ranges for Payload + Next.
2. Run ten codemods: `rename-systhema-bin`, `add-cookie-consent-to-next-layout`, `add-payload-instance-to-root-layout`, `install-lexical-schema-dedup-patch`, `remove-importmap-from-systhema-page`, `add-browserslist-to-package-json`, `rename-emails-capability-strings`, `optin-cookie-consent-tab`, `rename-figure-w-full`, `adopt-icon-picker`.
3. Apply the token migration that restructures `icon.*` into `icon.{normal,hover}.*` plus any other accumulated token additions.
4. Run `pnpm install`, `systhema-core payload create-app-files --override`, `systhema-core sync`, `payload generate:types`, `payload generate:importmap`.
5. Run post-upgrade hooks against the freshly-installed packages — currently `migrate-emails-data` (copies legacy `emails` global rows into `general-settings.emails_*`), `migrate-header-nav-dbnames` (renames the Header nav tables on Postgres to the namespaced `header_nav` / `header_sub_nav` form, from either the 1.5.x long names or the earlier canary bare names — see "Breaking & Behavioral Changes" §1), and `unify-block-slugs-data` (rewrites legacy block slugs in stored Lexical content). All are idempotent and adapter-aware.

The post-upgrade DB hooks talk to the database directly (not via `getPayload`), so they never trigger Drizzle's interactive dev schema-push — `systhema upgrade` runs start-to-finish non-interactively even on a Postgres project with pre-1.6.0 schema.

If you've moved managed Systhema files (e.g. into an `[locale]` segment for i18n), the `--override` step in `create-app-files` will recreate the defaults alongside your moved versions. Delete the duplicates after the upgrade completes.

---

## ⚠️ Breaking & Behavioral Changes

**Running `systhema upgrade` adopts almost all of these for you** — via codemods, the token migration, and three post-upgrade database hooks (including the Header global's Postgres table rename, which now runs as a hook rather than a manual SQL step). The only steps you do by hand are the ones a tool can't safely touch: the ambiguous custom Lexical converters the `adopt-icon-picker` codemod reports but won't rewrite (§2), role definitions stored outside `.ts`/`.tsx` (§7), and your _own_ code that still references a removed block slug or generated type name (§9). Each entry below marks what — if anything — is left for you.

### 1. Header global Postgres identifiers shortened (#65)

The default `Header` global's `navigation` and nested `subNavigation` arrays generated Postgres identifiers up to **75 chars**, which Postgres silently truncated to 63. Drizzle then re-issued `ADD CONSTRAINT` on every dev push and produced a recurring `42710 duplicate object`. Both arrays now carry a namespaced `dbName` (`header_nav`, `header_sub_nav`). On Payload 3.85.0 a `dbName` becomes the table name verbatim — `header_nav` / `header_sub_nav`, with versioned siblings `_header_nav_v` / `_header_sub_nav_v` — so the longest generated identifier (`_header_sub_nav_v_reference_id_pages_id_fk`, 42 chars) lands comfortably under the 63-char limit.

The table name is woven into every dependent object Drizzle generates — not just the table, but its constraints, indexes, **enum types** (`enum_nav_type`, `enum__sub_nav_v_link_type`, …) and **owned sequences** (`_nav_v_id_seq`, …). Enum types in particular are diffed by name, so a stale one is what triggers the interactive `Is enum_header_sub_nav_link_type created or renamed?` prompt. The migration renames all of them.

**You are affected if all three are true:**

1. Your project uses the bundled `Header` global from `@systhemaui/payload`.
2. You're on the Postgres adapter (`@payloadcms/db-postgres`).
3. You've already pushed the old long-named tables to a database you want to keep.

Fresh installs, dev DBs you don't mind recreating, SQLite/MongoDB users, and projects that ship a custom `Header` are unaffected.

**This is now automated** (#94, #95). `systhema upgrade` runs a `migrate-header-nav-dbnames` post-upgrade hook (Postgres-only, idempotent) that renames the affected objects in place before Payload's first schema push — so there's no manual step and no interactive "create or rename?" prompt. Because 1.6.0 was corrected while still on the canary channel, the hook recognises **every** possible pre-upgrade state and converges them on the same namespaced target:

- the **1.5.x long-named** tables (`header_navigation` / `header_navigation_sub_navigation`),
- the **earlier-canary bare-named** tables (`nav` / `sub_nav`), and
- the **half-migrated** state left by an earlier 1.6.0-canary that renamed the tables but not their enums/sequences — these are now healed on the next upgrade.

| Source table (1.5.x)                          | Source table (canary) | New table           |
| --------------------------------------------- | --------------------- | ------------------- |
| `header_navigation`                           | `nav`                 | `header_nav`        |
| `header_navigation_sub_navigation`            | `sub_nav`             | `header_sub_nav`    |
| `_header_v_version_navigation`                | `_nav_v`              | `_header_nav_v`     |
| `_header_v_version_navigation_sub_navigation` | `_sub_nav_v`          | `_header_sub_nav_v` |

plus the matching constraints, indexes, enum types, and owned sequences for each. Whichever source state a project is on, only the objects that actually exist are touched (and projects that strip enums to `varchar` via `beforeSchemaInit` simply have no enums to rename — the hook adapts).

If you'd rather migrate by hand, skip the hook with `--skip migrate-header-nav-dbnames` and either run the equivalent `ALTER TABLE … RENAME` statements yourself, or drop the source tables (`header_navigation` / `header_navigation_sub_navigation` — or the bare `nav` / `sub_nav` — and their `_v` siblings) and let Payload recreate them under the new names (you'll re-enter the nav from the admin UI).

> Custom Headers with `hasMany: true` polymorphic relationships or localized fields will also have `_rels` / `_locales` siblings on these tables — apply the same prefix rename to those if present.

### 2. Custom Lexical converters must call `resolveIconForRender` (#44)

Material Symbols picks are stored as identifier-only (`{"id":"material-symbols:arrow_forward"}` with no inline SVG) so variant swaps in `payload.config.ts` propagate instantly across the whole site. If your project has **custom** Lexical converters that read `data.iconBefore`, `data.iconAfter`, or `data.icon` straight into `dangerouslySetInnerHTML`, switch to `resolveIconForRender`:

```diff
+ import { resolveIconForRender } from '@systhemaui/payload/fields/iconPicker/resolveIconForRender'

  function MyCustomButton({ data }) {
    return (
      <button>
-       <span dangerouslySetInnerHTML={{ __html: data.iconBefore }} />
+       <span dangerouslySetInnerHTML={{ __html: resolveIconForRender(data.iconBefore).svg }} />
        {data.label}
      </button>
    )
  }
```

`resolveIconForRender` is synchronous, server-only, and handles all four storage formats (raw SVG legacy, hybrid FA/custom, MS identifier-only, empty). Built-in converters (button, chip, icon, footer-social) already call it internally — only **custom** converters need editing.

**`systhema upgrade` does most of this for you.** The bundled `adopt-icon-picker` codemod renames `faIconPickerField` → `iconPickerField` (imports and call sites, aliases preserved) and wraps the common converter pattern — `dangerouslySetInnerHTML={{ __html: <expr>.icon | .iconBefore | .iconAfter }}` — in `resolveIconForRender(<expr>).svg`, adding the import for you. It is conservative by design: anything it can't match with confidence (a bare `__html: iconBefore` variable, a computed/aliased access, or any other icon-looking value) is **reported, not rewritten**, and listed in the upgrade output so you can adapt it by hand using the diff above. The codemod is idempotent — re-running it changes nothing.

The legacy `faIconPickerField` is now `@deprecated` but still writes raw SVG strings as before. Prefer the new `iconPickerField` going forward.

### 3. `importMap` prop removed from `SysthemaPage` and `RootPage` (#72)

`<SysthemaPage importMap={importMap} />` was never read inside `@systhemaui/payload` (it was destructured as `_importMap` to silence ESLint), but importing the admin `importMap` from a public route was dragging the Lexical editor, `DocumentDrawer`, the icon-picker UI, and the rest of the admin component graph into the public Next.js bundle.

The prop is gone from the `Args` types. `systhema upgrade` ships a `remove-importmap-from-systhema-page` codemod that strips both the import line and the prop pass from the auto-generated `app/(site)/(systhema)/[[...segments]]/page.tsx`. The `payload create-app-files` scaffold has also been updated so subsequent `--override` refreshes don't undo the codemod.

If you've moved the auto-generated `page.tsx` to a non-standard path (e.g. under an `[locale]` segment for i18n), the codemod will skip it; remove the `import { importMap }` line and the `importMap={importMap}` prop manually.

### 4. `icon.*` color tokens restructured to `icon.{normal,hover}.*` (#55 and #43 follow-ups)

The flat `colorSystem.icon.*` shape was restructured into `colorSystem.icon.{normal,hover}.*` to power linkable icons (see "Linkable Icons" below). Five existing keys moved under `normal`; five new `hover` keys land on top.

`systhema upgrade` includes a token migration that handles the rename across **every** mode file (`colorSystem.default.tokens.json`, `colorSystem.dark.tokens.json`, custom modes). The same upgrade also fixed a latent runner bug where renames only applied to the first file containing the source path — relevant if you've authored custom multi-mode tokens.

### 5. Material Symbols tab appears by default in the icon picker (#44)

Projects that do nothing on upgrade will see a new **Material Symbols** tab next to Font Awesome in every icon picker. To restore the v1.5 single-pack look:

```ts
withSysthema(baseConfig, {
  icons: { materialSymbols: false },
})
```

No DB migration needed.

### 6. `systhema` is now the global CLI — project-local bin renamed to `systhema-core` (#47)

A new global CLI ships as `@systhemaui/cli`, installable as `systhema`. The previous project-local `systhema` binary (shipped by `@systhemaui/core`) has been renamed to `systhema-core`. The global CLI proxies project-context commands through to `systhema-core` so users have a single binary to remember.

**Effect on existing projects:** scripts in `package.json` that called `systhema sync` / `systhema migrate-tokens` / etc. now need to call `systhema-core <command>` (or `pnpm systhema-core <command>`). The bundled `rename-systhema-bin` codemod (run by `systhema upgrade`) rewrites `package.json` scripts conservatively.

```bash
# Install the global CLI (once, per machine)
pnpm add -g @systhemaui/cli@latest

# In a project:
systhema upgrade               # runs the upgrade pipeline
systhema-core sync             # runs only the project-local sync (artifacts)
systhema sync                  # runs `systhema-core sync` + reference generation
```

`systhema --help` lists every command; project-context commands (`sync`, `payload <sub>`, `migrate-tokens`, `create-config`, etc.) are proxied to `systhema-core`. See [`docs/cli/index.md`](../cli/index.md) for the full reference.

### 7. `global.emails.*` capabilities renamed to tab-scoped `global.general-settings.emails.*` (#73)

The `Emails` global has been folded into `general-settings` as a conditional tab (alongside the existing `cookieConsent` tab). The old capability strings (`global.emails.read`, `global.emails.update`) are gone.

`systhema upgrade` runs the `rename-emails-capability-strings` codemod against `.ts`/`.tsx` files. Roles defined in JSON / YAML / DB rows need a manual sweep — full mapping in #73.

Data is migrated automatically via the new post-upgrade hook (see Upgrade section below) — no manual SQL.

### 8. Cookie consent tab is now opt-in (#73)

Pre-1.6 the cookie consent tab was unconditional. From 1.6 it's gated by `generalSettings.cookieConsent.enabled`. `systhema upgrade` runs the `optin-cookie-consent-tab` codemod that auto-opts in any project whose `systhema.config.ts` has a top-level `cookieConsent` block. Greenfield projects opt in explicitly:

```ts
withSysthema(baseConfig, {
  generalSettings: { enabled: true, cookieConsent: { enabled: true } },
})
```

### 9. Block slugs unified — tier-segregated and `XInStack` slugs collapsed to single canonical slugs (#74)

The entire tier-segregated block surface (`rootImage` / `regionImage` / `fragmentImage` / `nestedImage`, and the video / youtube / googleMap / embed equivalents), the `formBlock` / `nestedFormBlock` pair, the `nested*` variants, and the whole `XInStack` block family are renamed to single canonical slugs. Generated `payload-types.ts` no longer contains the legacy type names (`RootImage`, `RegionVideo`, `ButtonInStack`, `NestedCard`, …), and `@systhemaui/payload` no longer exports the per-tier block defs or `inStackBlockTransform`.

| Removed / renamed                                                                                                             | Replacement                                                  |
| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| `rootImage` / `regionImage` / `fragmentImage` / `nestedImage` (+ video / youtube / googleMap / embed)                         | `image` / `video` / `youtube` / `googleMap` / `embed`        |
| `formBlock` / `nestedFormBlock`                                                                                               | `form` (interface `FormBlock` preserved)                     |
| `nestedCard` / `nestedColumns` / `nestedCarousel`                                                                             | `card` / `columns` / `carousel`                              |
| `richTextInStack` / `buttonInStack` / `chipInStack` / `iconInStack` / `avatarInStack` / `imageInStack` / `nestedImageInStack` | `richText` / `button` / `chip` / `icon` / `avatar` / `image` |
| Generated types `RootImage`, `ButtonInStack`, `NestedCard`, …                                                                 | `Image`, `Button`, `Card`, …                                 |
| CSS class `figure-w-full`                                                                                                     | `figure-w-screen` (legacy alias still safelisted + matched)  |

**Stored content migrates automatically.** `systhema upgrade` runs the new `unify-block-slugs-data` post-upgrade hook, which invokes the `migrate-unify-block-slugs` Payload bin script — rewriting every legacy slug in stored Lexical content (and injecting the new `_tier` field on every block) in place across Postgres / SQLite / Mongo, schema-independently and idempotently. No manual step, no generated `src/migrations/` file. During a staged rollout the runtime walker also recognises legacy slugs, so a frontend on the same DB keeps rendering before the migration runs.

**What you may still need to do by hand:** if your own code — custom JSX converters, block-picker config, `populateLexical*` overrides, or TypeScript referencing the generated block type names — names any removed slug or type, rename those references to the unified forms. The runtime accepts both legacy and unified slugs as a seatbelt, but type-level references to the old names won't compile.

### 10. `Icon.<tag>` proxy variants removed, use the `as` prop (#55)

`Icon` was previously a `Proxy` typed over every `keyof JSX.IntrinsicElements`, so variants such as `Icon.svg`, `Icon.div`, and `Icon.span` were part of its type-checked public API. Only `Icon.a` remains. Use the polymorphic `as` prop for every other element:

```tsx
// Before
;<Icon.svg viewBox="0 0 24 24"><path /></Icon.svg>

// After
;<Icon as="svg" viewBox="0 0 24 24"><path /></Icon>
```

`systhema upgrade` now runs the `rewrite-icon-tag-variants` codemod to make this rewrite automatically.

---

## ✨ New Features

### Linkable Icons (#55)

The inline `IconBlock` in `@systhemaui/payload` now supports links, matching the linkable Media blocks from 1.5.0. Editors set a link from a new "Link Settings" collapsible (custom URL or internal page reference, with optional `newTab`). The Lexical converter renders the polymorphic `<Icon.a>` — backed by `next/link` in `@systhemaui/next` — and the icon picks up a built-in hover affordance from the new `icon.hover.*` foundation tokens.

Drive-by improvements:

- **`Icon` is no longer a `Proxy`.** Refactored to the `Object.assign({ a })` pattern used by `Button.a` / `Chip.a` / `MediaWrapper.a`. `<Icon hasBackground>` and `<Icon.a href="…">` work unchanged; `<Icon.span>` / `<Icon.div>` etc. are removed. See Breaking & Behavioral Changes §10.
- **Smooth-scroll on Next.** `@systhemaui/next` provides its own `Icon` override so `Icon.a` routes through the package's `Link` wrapper — footer social usages and editor-authored `#section` links benefit from prefetch and hash-anchor smooth scroll.
- **Shared link resolution.** Image / Video / Icon converters now share a single `resolveLink()` helper.

### `.systhema/artifacts/` — generated files survive `pnpm install` (#46)

`systhema sync` now writes its generated artifacts (tokens, `tokenMap.{ts,js}`, `types.{ts,d.ts,js}`, `safelist.txt`) to **`<project>/.systhema/artifacts/`** instead of `node_modules/@systhemaui/core/src/tmp/`. A three-tier refresh mechanism — Tailwind plugin init, `systhema sync`, and a Node-side bootstrap inside `handleTokens.ts` — keeps `@systhemaui/core/dist/tmp/` mirrored from the authoritative `.systhema/artifacts/` source.

- `pnpm install` no longer wipes generated artifacts.
- Hot reload during monorepo development no longer clobbers generated files.
- `.systhema/` is inspectable at the project root and ready to grow.

Also new:

- **`systhema clean`** — wipes `.systhema/` at the project root and restores `@systhemaui/core/dist/tmp/` to shipped defaults.
- **`.systhema/.meta.json`** — version marker + manifest hash for stale-output detection.

**Zero consumer API changes.** All existing imports (`ColorSystem`, `LayoutBackground`, `getTokens`, `@systhemaui/core/tmp/types`, etc.) continue to work unchanged.

### TOON references for agents (#54)

The new `systhema generate-references` command emits agent-facing TOON files at `<project>/.systhema/references/tokens/*.toon`. It's automatically chained behind `systhema sync`, so the typical flow doesn't change — running `pnpm sync` regenerates both the consumer artifacts and the TOON references in one step. Direct `systhema-core sync` does NOT run reference generation; use the global `systhema sync` for the complete pipeline.

Bundled with this: a `skills install` CLI subcommand that copies Systhema's hand-edited skills into agent skill directories (`.claude/skills/`, `.agents/skills/`), and a new `systhema:understanding-tokens` skill.

### `@layer app` for project-specific overrides (#61)

The Systhema Tailwind entry now declares the top-level layer order as `theme, base, components, utilities, app` — making `app` the last (highest-priority) layer.

```css
@import '@systhemaui/core/tailwind';

@layer app {
  @media (min-width: theme('screens.md')) {
    .accordion-title {
      @apply flex-row-reverse justify-end;
    }
  }
}
```

Rules placed inside `@layer app { … }` win over Tailwind utilities and every Systhema component class. The starter templates ship their example overrides moved into the new layer.

**Backwards compatible.** Existing unlayered CSS in your global stylesheet still beats anything inside any `@layer` (per the CSS spec). Migrating overrides into `@layer app { … }` is recommended but optional.

### Form-field description support (#48)

The form-builder integration now renders an optional **description** under each field. Added at both the Payload field-schema level and the Lexical-to-JSX render side. `colorSystem.form.description` + typography tokens come with it (the token migration handles existing projects).

### `slotProps` on field components + TextField type override (#50)

Every `*Field` component in `@systhemaui/react` accepts a `slotProps` object for spreading attributes onto internal slots (`label`, `input`, `description`, `error`). `TextField` additionally accepts `type` so callers can render `email`, `number`, `tel`, `url`, etc. without dropping back to a raw `<input>`.

### Globals trigger full revalidation when changed (#66)

Header, Footer, Settings, and other globals' `afterChange` hooks now revalidate every page (`revalidatePath('/', 'layout')`) instead of revalidating individual tags. Globals are shared across the whole site, so a partial revalidate would have left some routes stale. Affects only the auto-generated `(systhema)` catch-all routes — custom routes opting into their own caching are unchanged.

### Skill ecosystem: breakpoints, foundations, layout-bg (#58)

The bundled `systhema:understanding-tokens` skill gains coverage of Systhema's responsive breakpoint system, foundation token semantics, and the `LayoutBackground` component contract, so agents apply them correctly. Installed via `systhema skills install --skill <name> --agent <agent>`.

### Emails moved into General Settings as a conditional tab (#73)

The standalone `Emails` global is gone; its four fields now live inside `general-settings` as an `Emails` tab. Both tabs (`Emails` and `Cookie Consent`) are conditionally registered — they only appear in the admin and only create DB columns when their gating option is on. If both are off, `general-settings` itself isn't registered.

The Emails tab also gains a **Send Test Email** button that routes through Systhema's email wrapper, so the saved From Name / From Address / Reply-to / branded template are all exercised end-to-end. Success and failure messages render inline with the adapter's verbatim error for debugging.

Data migration is automatic — see Upgrade section. Capability and opt-in changes are covered in Breaking & Behavioral Changes §7 and §8.

### Post-upgrade hooks in the CLI (#73)

`systhema upgrade` gains a `postUpgrade` migration shape — declarative shell hooks that run **after** `pnpm install`, so newly-bumped packages are on disk before any data-migration script runs. The new `migrate-emails-to-general-settings` script (see Emails refactor above) is the first user. `systhema upgrade --dry-run` lists hooks; `--skip <hook-name>` opts out. Failed hooks leave the rest of the upgrade intact and surface the exact command to re-run manually.

### `systhema upgrade` refreshes installed skills (#87)

Bundled skills install separately (`systhema skills install`) and used to drift out of sync with the CLI until you manually re-ran the install. `systhema upgrade` now adds a **skill-refresh** step: after the dependency install and token/type sync, it detects which skills the project already has installed — across both `project` and `user` scope and every supported agent — and re-copies the upgraded CLI's bundled-current version into exactly those locations. It only refreshes skills that are already present, so it never introduces a skill you didn't opt into, and a project with none installed is a clean no-op. The step is non-fatal (a failure warns and the upgrade continues), is honored under `--dry-run` (the plan lists which skill + scope + agent copies would be refreshed), and can be skipped entirely with `--no-skills`.

### Homepage picker in General Settings (#80)

A new always-on **Pages tab** in `general-settings` exposes a single optional `homepage` relationship field. When set, the picked page renders at `/`, its own URL (e.g. `/home`) 308-redirects to `/`, and every Page-relation link across blocks, Lexical content, sitemaps, and form-submission redirects resolves to `/` automatically — so there's no 308 round-trip on click.

| Visitor lands on       | Configured homepage                   | Outcome                                                          |
| ---------------------- | ------------------------------------- | ---------------------------------------------------------------- |
| `/`                    | none                                  | Today's behaviour: render Page where `fullPath === ''`, else 404 |
| `/`                    | set, page published                   | Render that Page                                                 |
| `/`                    | set, page unpublished/trashed/deleted | Silent fallback to `fullPath === ''`, else 404                   |
| `/<homepage.fullPath>` | set, page published, not draft mode   | 308 permanent redirect to `/`                                    |
| `/<homepage.fullPath>` | draft mode                            | Render the page directly (no redirect) so editors can preview    |

Internals: links flow through a new `pageRefToHref` helper (sync + async forms) backed by a request-scoped `homepageId` store, primed once per request at the root view. Lexical converters stay sync because `JSXConverter`'s return type can't be a Promise. Adds a `global.general-settings.pages.update` capability — admins inherit via `global.*`.

The Pages tab also fixes a duplicate `/` entry that could appear in the sitemap when both a configured homepage and a `slug=''` fallback page were present — the slug='' page is now suppressed from the sitemap whenever a homepage is configured.

### Stack items unified into the base blocks (#74)

`inStackBlockTransform` is gone. Stack and NestedStack reference the base block defs directly; the grow / shrink / flex1 / setSelfAlign / alignSelf controls move to a reusable `stackLayoutFields()` builder appended to each base block inside a drawer gated on `_tier === 'stack'`. One block definition now renders normally at root/region/fragment, with figure-width controls at root/region, and with stack-layout controls inside a Stack — invisible everywhere it doesn't apply.

### Figure breakout + sub-track-width alignment (#74)

A real breakout CSS contract: `width="container"` and `width="screen"` figures now actually escape narrower ancestor wrappers (previously they were clamped by the column track). When a figure stays at default width but its inner element is narrower than the track (an image at 50%, a 400px embed in a 1280px column), authors get left / center / right alignment via `mr-auto` / `mx-auto` / `ml-auto` (all safelisted). The alignment row only appears when it would have a visible effect. The CSS class `figure-w-full` is renamed to **`figure-w-screen`** — the `rename-figure-w-full` codemod rewrites source references on upgrade, and the legacy class stays safelisted + matched so existing markup keeps rendering. Embed and form blocks now render through the React `<Figure>` component for consistent breakout behaviour.

### `systhema migrate` — run a single data migration standalone (#74)

The post-upgrade DB hooks (`migrate-emails-data`, `migrate-header-nav-dbnames`, `unify-block-slugs-data`) are now individually runnable, mirroring how `systhema codemod` exposes a single code codemod:

```bash
systhema migrate --list                            # list available data migrations
systhema migrate unify-block-slugs-data            # run one by id
systhema migrate unify-block-slugs-data --dry-run  # report only, run nothing
```

Each migration keeps its `applicable()` guard, so a standalone run against an already-migrated project, the wrong project type, or a fresh install is a clean no-op. Each is a thin wrapper around the corresponding project-local Payload bin (e.g. `systhema migrate unify-block-slugs-data` ≡ `pnpm payload migrate-unify-block-slugs`). Useful for re-running a single migration after restoring a DB snapshot without re-running dep bumps / codemods / install.

### Public bundle drops 55% — admin code no longer in anonymous-visitor chunks (#72)

The `importMap` prop removal (see "Breaking & Behavioral Changes") plus inlining the admin-bar and live-preview CSS via React 19's hoistable `<style href="…" precedence="default">` element produces, on a real consumer homepage (production `next build`):

- **27 → 12 chunks** loaded (−15)
- **5.10 MB → 2.27 MB** total raw asset size (−55%)
- Three multi-hundred-KB JS chunks of Lexical + Payload admin code **dropped** (importMap fix)
- **5 → 1 CSS chunks**; the remaining one is the consumer's own globals.css

CSS Modules in `AdminBar` and the live-preview overlay are replaced with stable prefixed BEM-ish class names (`payload-admin-bar`, `payload-admin-bar__button`, `payload-admin-bar--hidden`) since the runtime-injected style isn't going through CSS Modules' build-time hashing anymore.

### rAF-throttled scroll listeners (#72)

`ParallaxListener`, `AosListener`, and `ScrollClassesListener` (in both `@systhemaui/react` and `@systhemaui/next`) used to run handlers synchronously on every `scroll` / `resize` / `touchmove` / `load`. For `ParallaxListener`, the per-element loop interleaved layout reads (`offsetTop`, `offsetHeight`, `scrollY`) with layout writes (`element.style.transform = …`); each write invalidated layout, so the next read forced a synchronous reflow. PageSpeed Insights flagged ~136 ms of "forced reflow" on a real consumer site.

All three listeners now coalesce events into at most one update per animation frame. `ParallaxListener.updateParallax()` is split into a read phase (collect every element's position + viewport bounds into `measurements[]`) and a separate write phase (apply transforms). No layout reads happen during the write loop. Initial updates still run synchronously so first paint is correct; only event-driven updates are scheduled. `passive: true` is added to `ScrollClassesListener` (previously missing) and preserved everywhere else.

### Modern browserslist target in templates and on upgrade (#72)

`templates/payload/package.json` and `templates/next/package.json` now ship a `browserslist` targeting Chrome / Edge / Firefox 100+ and Safari 15.4+. New projects scaffolded by `systhema create` get this automatically.

The bundled `add-browserslist-to-package-json` codemod adds the same field to existing consumers' root `package.json` on `systhema upgrade`. Idempotent — it does nothing if the consumer has any `browserslist` configuration of their own (string, array, or production/development map).

### Tab-aware General Settings revalidation (#80)

Previously, every save on the `general-settings` global flushed `/` (the layout-level ISR cache), including pure email-config edits that have no rendered-page effect. After this release, only tabs whose content actually appears on rendered pages trigger `revalidatePath('/', 'layout')`:

| Editor saves…                                 | Layout revalidates? |
| --------------------------------------------- | :-----------------: |
| Pages tab (homepage picker changed)           |         ✅          |
| Cookie Consent — any field                    |         ✅          |
| Emails — any field (From Address, logo, etc.) |         ❌          |
| Mixed (cookie consent + emails)               |         ✅          |
| Draft save (`_status !== 'published'`)        |         ❌          |

Editing the page that IS the configured homepage now also revalidates `/` (in addition to its own URL). Header / Footer / SEO globals continue to use the shared `revalidateAllPages` hook unchanged — their content is unambiguously on every page.

---

## 🐛 Fixes & Internal Improvements

### Bug Fixes

- **Frontend admin bar no longer leaks the admin URL** to anonymous visitors — the URL is off the server→client boundary; the bar fetches an authenticated `/sys/admin-bar` endpoint and renders nothing until auth is confirmed, gated on a non-sensitive marker cookie so anonymous SSG pages make zero origin requests (#90)
- **`modify` / `remove` token migrations are idempotent across every mode** — both now walk every mode file in one pass; `modify` gates on value (not existence) and can't inject `$value` into a group node, so a migration no longer re-appears on every upgrade (#91)
- **Upgrade reconciles `pnpm.overrides` for the Payload family** — `applyPeerBumps` bumps every Payload-family override (incl. transitive-only `@payloadcms/drizzle` / `@payloadcms/graphql`) to the target range, so an overrides family-pin can't silently revert the bump (#74)
- **`add-payload-instance-to-root-layout` codemod handles customized layouts** — reuses an existing resolved `payload` instance or injects the missing imports instead of blindly adding `getPayload(...)` (#74)
- **Balance-text + text-state round-trip** — kebab-case CSS keys no longer crash React rendering, and `importJSON` / `$toggleBalanceText` preserve NodeState so custom states survive load and toggle (#68)
- **`as="a"` routes through `Link`** on `Button` / `Chip` / `Card` in `@systhemaui/next`, so hash-anchor smooth-scroll and `next/link` prefetch work (previously only the `.a` subcomponents did) (#63)
- **Turbopack double-`!important` build error** worked around — `splitImportantRules()` routes `!important` block rules through `@layer base.systhema` to dodge lightningcss duplicating the bang (#59)
- **Raw icon JSON no longer leaks into the DOM** — header CTA, footer social, and form submit buttons resolve the icon-picker JSON through `resolveIconHtml()` server-side (#60)
- **`iconInStack` / `nestedImageInStack` link fields wired up** — stack icons and nested images now render `Icon.a` / `MediaWrapper.a` when a link is configured (#67)
- **TOON references: spec-conformant output + rounded numbers** — switched to the official `@toon-format/toon` encoder, kebab-cased text-style class names, dropped non-CSS metadata entries, and rounded float noise to 2 dp (#57, #62)
- **Figma asterisks no longer break Tailwind variable names** — string-reference `$value`s (e.g. `"{primitives.purple.500*}"`) now pass through `stripAsterisksDeep`, so they don't yield invalid `var(--…*)` names (#59)
- **Form blocks nested inside Lexical container blocks now render** — the JSX converter descends recursively instead of walking only the top-level block list (#75)
- **Mobile menu closes on in-menu link click** — the nav drawer closes after a descendant `<a>` is tapped (#70)
- **Template scaffolds** — fixed the first-`pnpm lint` ESLint crash and a PostCSS deprecation warning in `templates/next` / `templates/payload` (#64)
- **Pages embedding a form revalidate when the form changes** — new `afterChange` / `afterDelete` hooks on `forms` scan published pages (incl. forms nested in `Section` / `Columns`) and revalidate each match (#81)
- **`systhema upgrade` aligns every `@payloadcms/*` sibling to `payload`** — dynamic discovery bumps installed db / storage / email adapters (not peer-declared) to the resolved `payload` range, fixing the boot-time `Mismatching "payload" dependency versions` crash (#84)

### Internal / Monorepo

- **`pnpm.onlyBuiltDependencies` WARN spam removed** — the field is stripped from source template `package.json`s and re-injected at CLI bundle time, so the monorepo no longer warns while scaffolded projects still get the right array (#79)
- **Next.js / React patch bumps** — `next ^16.2.4 → ^16.2.6`, `react` / `react-dom ^19.2.5 → ^19.2.6`, matching `@next/*` + `eslint-config-next` (#45)
- **Pre-1.6.0 broad dependency refresh** — patch + minor bumps across the toolchain (`tailwindcss 4.2.2 → 4.3.0`, `swiper`, `tailwind-merge`, ESLint plugins); deliberate majors held back (#78)
- **`@toon-format/toon` 2.2 → 2.3** — decode strictness + `\uXXXX` escapes; reference output unchanged; unblocks a stale `syncWithReferences` test (#77)
- **Payload 3.84.1 → 3.85.0 + minor bumps** — `payload` and every `@payloadcms/*` to 3.85.0; peer floor raised to `^3.85.0`; the bundled richtext-lexical patch re-targets cleanly (byte-identical) (#82)

---

## List of all changes

Every commit between `v1.5.0` and `v1.6.0`, categorized. Items already covered in the prose sections above are repeated here as a flat reference.

### 🚀 Features

#### cli

- feat(cli): add generate-references command and bundled skills install (#52) (49ef3157)
- feat(cli): add `systhema doctor` — unified project-health checks with auto-fix (#86) (58bcf0b3)
- feat(cli): add icon-picker adoption codemod for the 1.6.0 upgrade (#93) (16c1d77b)
- feat(cli): refresh installed skills on systhema upgrade (#87) (39b9d07c)
- feat(cli): redesign systhema info and gate the branded header for humans (#92) (b1cef991)

#### cli,payload

- feat(cli,payload): round out the create flow and fix fresh-project setup (#89) (e17f1536)

#### cli,skills

- feat(cli,skills): teach agents breakpoints, foundations, and layout-bg (#58) (8d762dba)

#### core

- feat(core): add `app` cascade layer for project-specific overrides (#61) (ac048755)

#### docs,skills,cli

- feat(docs,skills,cli): docs refresh, ten-skill ecosystem, palette CLI (#54) (7607cefb)

#### payload

- feat(payload): add homepage picker + centralise page-href helper (#80) (a25afe8e)
- feat(payload): multi-pack icon picker — material symbols, apple emoji, font awesome, custom (#44) (9ba86c57)
- feat(payload): revalidate all pages when globals change (#66) (2060af2b)

#### react

- feat(react): add slotProps to all \*Field components and allow type override on TextField (#50) (0957b4ae)

#### general

- !feat: add global @systhemaui/cli; rename core bin to systhema-core (#47) (breaking) (9d7556d0)
- feat: add link support to image and video media blocks (#43) (4e92d1f2)
- feat(\*): add cookie consent integration with scanner and Payload controls (#53) (9b18a949)
- feat(\*): add form-field description support (#48) (56093c5c)
- feat(\*): add link support to icon blocks (#55) (15cc4d1d)

### ♻️ Refactors

#### cli,core

- refactor(cli,core): unify console output styling across commands (#85) (69800e60)

#### core

- refactor(core): relocate project artifacts to <project>/.systhema/ (#46) (21949e81)

#### payload

- refactor(payload): move emails into general-settings as a conditional tab (#73) (e88eb789)

#### general

- !refactor(\*): unified tier-aware blocks, figure breakout, sub-track alignment (#74) (breaking) (a4de522c)

### ⚡ Performance

#### payload

- perf(payload): cut admin RSC payload via lazy-mount + schemaMap dedup patch (#71) (38dffc25)

#### general

- perf(\*): cut public bundle 55% and fix scroll-listener forced reflow (#72) (58c54d73)

### 🐛 Bug fixes

#### ci

- fix(ci): make dist-tag determination flag-safe in release publish (b2160b36)

#### cli

- fix(cli): align installed @payloadcms/\* siblings to payload on upgrade (#84) (3b1e452c)
- fix(cli): emit spec-conformant TOON and align generated class names with core (#57) (26a3cbc6)
- fix(cli): make modify and remove token migrations idempotent across every mode (#91) (286c08c8)
- fix(cli): round numeric token values in generated .toon files to two decimals (#62) (4eb308d8)

#### core

- fix(core): strip Figma asterisks and dodge Turbopack double-!important (#59) (4f748337)

#### core,next,react

- fix(core,next,react): close mobile menu on in-menu link click (#70) (0c8f3b40)

#### next

- fix(next): route polymorphic as="a" through Link in Button, Chip, Card (#63) (02974134)

#### payload

- fix(payload): fix template eslint crash and postcss warning (#64) (c6e186f0)
- fix(payload): populate form blocks nested inside Lexical container blocks (#75) (569f5913)
- fix(payload): preserve text state across balance-text and normalize kebab-case CSS (#68) (b270335d)
- fix(payload): resolve icon JSON before rendering in header CTA, footer social, and form submit (#60) (c8c6a61a)
- fix(payload): revalidate embedding pages inline on form/component change (#88) (9bf1629d)
- fix(payload): revalidate pages when an embedded form changes (#81) (bff6ff17)
- fix(payload): shorten Header global's Postgres identifiers via dbName (#65) (50f6db0f)
- fix(payload): stop frontend admin bar from leaking the admin URL (#90) (3f6fc4e5)
- fix(payload): shorten cookieTableHeaders field name to stay under PostgreSQL's 63-char column limit (#56) (bc0ef9f5)
- fix(payload): wire iconInStack and nestedImageInStack link fields through to render (#67) (814e9499)

#### payload,cli

- fix(payload,cli): namespace Header nav tables under header\_ prefix (#94) (0038899d)

### 🧪 Tests

#### cli

- test(cli): accept prerelease versions in scaffolded dep specs (#76) (ac242ecd)

### 🧹 Chores

#### cli

- chore(cli): bump @toon-format/toon to 2.3.0 (#77) (de3995b0)
- chore(cli): strip pnpm.onlyBuiltDependencies from template sources (#79) (c8210c80)

#### core

- chore(core): add form-description entries to legacy tokens (#51) (56e82831)

#### deps

- chore(deps): bump next 16.2.4, react 19.2.5, payload 3.84.1 (#45) (ce9c82b1)
- chore(deps): bump patch + minor versions before 1.6.0 (#78) (90bf1a8e)
- chore(deps): bump payload 3.84.1 → 3.85.0 and other minors (#82) (4ceceb7a)

#### general

- chore: include ".systhema" folder in prettier ignore file (01fbf9e2)
- chore: remove files of docs/superpowers from repository (865cafaa)
- chore(\*): release v1.6.0-canary.1 (f3558426)
