---
title: "v1.5.0"
description: "The new global `systhema` CLI, a `[[...segments]]` catch-all with configurable sitemaps, capability-based access control, captcha verification and the Systhema Figma plugin."
requested_language: cs
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/cs/changelog/v1.5.0
version: changelog
docs_index: https://docs.systhema.app/cs/llms.txt
---
> This page isn't translated yet. Showing English.


## 🆕 New Global CLI

This release introduces `@systhemaui/cli`, the new global Systhema CLI. Install it once and use `systhema create`, `systhema upgrade`, `systhema codemod`, `systhema info`, `systhema self-update` from anywhere:

```bash
pnpm add -g @systhemaui/cli
systhema --help
```

The global CLI also proxies the project-local helpers (`sync`, `init`, `payload <sub>`, etc.), so you no longer need `pnpm exec` for most things. See [the CLI guide](../cli/index.md) for the full command list.

**Bin rename:** the project-local `systhema` bin (provided by `@systhemaui/core`) was renamed to `systhema-core` so the `systhema` name belongs to the new global CLI. `systhema upgrade` runs a codemod (`rename-systhema-bin`) that rewrites `package.json` scripts automatically — manual action only needed if you have custom invocations elsewhere.

---

## ⚠️ Must Be Adapted

These changes will break your project if not addressed. Apply them before upgrading.

### 1. Migrate to `[[...segments]]` Catch-All & New Sitemaps (#28)

The `(systhema)` route group has been consolidated from 6 consumer files down to 3. The old `[...path]` structure is no longer supported — you must migrate to the new `[[...segments]]` catch-all.

#### Before (6 files)

```text
(systhema)/
├── page.tsx                              ← homepage
├── [...path]/page.tsx                    ← CMS pages
├── components/[id]/page.tsx              ← component previews
├── (sitemaps)/
│   ├── sitemap.xml/route.ts              ← sitemap index
│   └── pages-sitemap.xml/route.ts        ← pages sitemap
└── sys/[route]/route.ts                  ← API routes
```

#### After (3 files)

```text
(systhema)/
├── [[...segments]]/page.tsx              ← all pages, components, future modules
├── (sitemaps)/sitemap.xml/route.ts       ← single sitemap.xml
└── sys/[route]/route.ts                  ← API routes + grouped sitemap sub-routes
```

#### How to migrate

The fastest path — regenerate all files automatically:

```bash
# Delete old page files
rm src/app/(site)/(systhema)/page.tsx
rm -r src/app/(site)/(systhema)/\[...path\]
rm -r src/app/(site)/(systhema)/components

# Delete old sitemap files
rm -r src/app/(site)/(systhema)/\(sitemaps\)/pages-sitemap.xml
# If you had a manually created sitemap index, remove it too:
# rm src/app/(site)/(systhema)/(sitemaps)/sitemap.xml/route.ts

# Regenerate everything
systhema payload create-app-files --override   # global CLI (proxies to project-local)
# or, equivalently:
pnpm exec systhema-core payload create-app-files --override
```

Or see the template project for the exact file contents if you prefer to migrate manually.

#### Sitemaps must also be migrated

The old manually-maintained sitemap route files (`pages-sitemap.xml/route.ts`, etc.) are replaced by a single `sitemap.xml/route.ts` that delegates to the library. If your project had custom sitemaps (e.g., for blog posts or projects), migrate them to the config-based approach:

**Before (manual route files):**

```text
(sitemaps)/
├── sitemap.xml/route.ts              ← manually lists sub-sitemaps
├── pages-sitemap.xml/route.ts        ← manually queries pages
└── projects-sitemap.xml/route.ts     ← manually queries projects
```

**After (config-based, single file):**

```text
(sitemaps)/
└── sitemap.xml/route.ts              ← one file, delegates to library
```

Custom entries are now defined in the plugin config — see [Configurable Sitemaps](#configurable-sitemaps-28) under New Features for full examples.

#### What you get

- **SSG by default** — all pages pre-rendered at build time with ISR revalidation (~1 month). Admin bar auth moved to client-side, removing the dynamic API calls that previously prevented static generation.
- **Draft page protection** — `queryPageByPath` now explicitly filters `_status: 'published'` for public visitors. Draft pages were previously accessible.
- **Configurable sitemaps** — add custom entries or grouped sub-sitemaps via plugin config instead of manual route files.
- **Future-proof** — when Systhema Modules land, your page files won't need any changes.

### 2. `withSysthema()` Plugin Options Overhaul (#23)

Several features that were previously enabled by default now require explicit opt-in:

| Feature      | Before              | After        | How to enable                                 |
| ------------ | ------------------- | ------------ | --------------------------------------------- |
| `components` | enabled             | **disabled** | `components: true`                            |
| `googleMaps` | `true` / `false`    | **`false`**  | `googleMaps: { apiKey: '...' }`               |
| `embed`      | enabled             | **disabled** | `embed: true`                                 |
| `forms`      | enabled             | **disabled** | `forms: true` or `forms: { fields: { ... } }` |
| `redirect`   | enabled             | **disabled** | `redirect: true`                              |
| `emails`     | auto (with adapter) | **`false`**  | `emails: { defaultFromAddress: '...' }`       |

**`googleMaps` no longer accepts `true`** — the API key is now part of the config:

```ts
// Before
googleMaps: true
// After
googleMaps: { apiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY }
```

**`emails` no longer accepts `true`** — env vars are no longer read internally:

```ts
// Before
emails: true  // read from SYSTHEMA_EMAIL_* env vars
// After
emails: {
  defaultFromAddress: process.env.SYSTHEMA_EMAIL_FROM!,
  defaultReplyTo: process.env.SYSTHEMA_EMAIL_REPLY_TO,
  adminAddress: process.env.SYSTHEMA_EMAIL_ADMIN_ADDRESS,
}
```

**`APP_ENVIRONMENT` env var removed** — use the `environment` plugin option:

```ts
environment: (process.env.APP_ENVIRONMENT as 'production' | 'staging' | 'development') || 'production',
```

**`VERCEL_PROJECT_PRODUCTION_URL` removed** — `NEXT_PUBLIC_SERVER_URL` is the only URL source.

#### Full migration example

```ts
// Before (v1.4.x) — everything enabled by default, env vars read internally
withSysthema(config, {})

// After (v1.5.0)
withSysthema(config, {
  environment: (process.env.APP_ENVIRONMENT as 'production' | 'staging' | 'development') || 'production',
  components: true,
  embed: true,
  redirect: true,
  googleMaps: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
    ? { apiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY }
    : false,
  emails: process.env.SYSTHEMA_EMAIL_FROM
    ? {
        defaultFromAddress: process.env.SYSTHEMA_EMAIL_FROM,
        defaultReplyTo: process.env.SYSTHEMA_EMAIL_REPLY_TO,
        adminAddress: process.env.SYSTHEMA_EMAIL_ADMIN_ADDRESS,
      }
    : false,
  forms: true,
})
```

### 3. Minimum Dependency Versions

| Package         | Old minimum | New minimum                                                           |
| --------------- | ----------- | --------------------------------------------------------------------- |
| `tailwindcss`   | `^4.1`      | **`^4.2`** (#15)    |
| `@payloadcms/*` | `^3.79.1`   | **`^3.80.0`** (#16) |

### 4. Payload 3.80: `imageURL` → `admin.images.icon` (#17)

Payload deprecated `imageURL` in 3.79.0. All 41 usages across Systhema have been migrated. If you have custom blocks using `imageURL`, update them:

```diff
  const MyBlock: Block = {
    slug: 'myBlock',
-   imageURL: '/icons/my-block.svg',
+   admin: { images: { icon: '/icons/my-block.svg' } },
    fields: [/* ... */],
  }
```

### 5. `next lint` Removed in Next.js 16 (#29)

```diff
- "lint": "next lint",
+ "lint": "eslint .",
```

---

## 📣 Heavily Recommended

Not immediately breaking, but you should do these now. Skipping them will cause problems in a future release.

### Migrate Legacy Token Format (#12)

The old community plugin ("Design Tokens Manager") token format is now **deprecated** and will be removed in a future major release. If your project still uses old-format token files, migrate now — either by re-exporting from Figma using the new `@systhemaui/figma` plugin, or by running:

```bash
systhema migrate-tokens
```

Both formats currently produce identical CSS output, so migration is safe. But legacy support **will be dropped** — don't wait.

### Add Systhema Gateway (#27)

The gateway is an extensible request middleware that will gain features (i18n locale detection, maintenance mode) without requiring consumer changes. Setting it up now means you're ready when those features land.

**`src/proxy.ts`** (or `src/middleware.ts` for Next.js <16):

```ts
import { systhemaGateway } from '@systhemaui/payload/gateway'

export const proxy = systhemaGateway()
```

If you already use a custom admin domain, pass the config:

```ts
export const proxy = systhemaGateway({
  customAdminURL: process.env.ADMIN_URL,
})

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}
```

### Next.js Config Improvements (#29)

**Rename `next.config.mjs` → `next.config.ts`** with proper TypeScript typing and the new `devBundleServerPackages: false` option from the official Payload template:

```ts
import { withPayload } from '@payloadcms/next/withPayload'
import type { NextConfig } from 'next'

const nextConfig: NextConfig = { /* ... */ }

export default withPayload(nextConfig, { devBundleServerPackages: false })
```

**Remove `exprContextCritical` workaround** if your `next.config` has it — this was a temporary fix for noisy webpack warnings from Payload's job queue and is no longer needed:

```diff
- config.module.exprContextCritical = false
```

### Install `@payloadcms/typescript-plugin` (#18)

Now a peer dependency. Provides IDE support for Payload component paths. Add to your `tsconfig.json`:

```json
{
  "compilerOptions": {
    "plugins": [{ "name": "@payloadcms/typescript-plugin" }]
  }
}
```

---

## ✨ New Features

If your website already has a custom solution for any of these, consider migrating to the built-in version.

### Capability-Based Access Control (#7)

Replaces the hardcoded `admin`/`editor` role checks with a flexible, fine-grained permission system. **If you've built custom role logic**, this replaces it entirely.

#### Capability String Format

Capabilities use dot-notation to express resource-level, field-level, and global-level permissions:

```text
{collection}.{operation}           → pages.create, uploads.delete
{collection}.{field}.{operation}   → pages.seo.update, users.roles.read
global.{global}.{operation}        → global.header.update, global.seo.read
```

Wildcards are supported: `*` (all capabilities), `pages.*` (all pages capabilities including field-level), `global.*` (all global capabilities).

#### Built-in Roles

| Role            | Slug         | Description                                                                               |
| --------------- | ------------ | ----------------------------------------------------------------------------------------- |
| **Developer**   | `dev`        | Full access (`*`). Invisible to non-dev users. Assigned via `pnpx payload seed-dev` only. |
| **Admin**       | `admin`      | All built-in Systhema features. Custom collections are NOT included by default.           |
| **Editor**      | `editor`     | Read + update content as drafts. Full uploads. Read-only globals.                         |
| **SEO Manager** | `seoManager` | Read pages with editable SEO fields only. Full global SEO access.                         |

Since admin is scoped to built-in features only, **custom collections are dev-only by default**. Use `overrideRoles` to grant admin (or editor) access to project-specific collections:

```ts
withSysthema(config, {
  roles: {
    // Register custom capabilities
    customCapabilities: [
      'projects.create', 'projects.read', 'projects.update', 'projects.delete',
    ],
    // Create custom roles
    customRoles: [
      { name: 'contentReviewer', label: 'Content Reviewer', capabilities: ['pages.read', 'components.read'] },
    ],
    // Extend built-in roles
    overrideRoles: (defaults) => ({
      ...defaults,
      admin: {
        ...defaults.admin,
        capabilities: [...defaults.admin.capabilities, 'projects.*', 'tickets.*'],
      },
      editor: {
        ...defaults.editor,
        capabilities: [...defaults.editor.capabilities, 'pages.create', 'pages.delete', 'pages.publish'],
      },
    }),
  },
})
```

To restore the old behavior where admin sees everything (including all custom collections):

```ts
overrideRoles: (defaults) => ({
  ...defaults,
  admin: { ...defaults.admin, capabilities: ['*'] },
})
```

#### Scoped Field-Level Updates

Sub-capabilities like `pages.seo.update` allow editing specific field groups while keeping everything else read-only. A user with only `pages.seo.update` can see pages, save pages, but only edit the SEO tab — all other fields appear read-only in the admin UI.

For consumer collections, apply the same pattern:

```ts
import { requireUpdateOrScoped, addScopedFieldAccess, requireCapabilityField } from '@systhemaui/payload'

const Articles: CollectionConfig = {
  slug: 'articles',
  access: { update: requireUpdateOrScoped('articles') },
  fields: addScopedFieldAccess([
    { name: 'title', type: 'text' },
    { name: 'content', type: 'richText' },
    {
      name: 'metadata',
      type: 'group',
      // Users with articles.metadata.update can edit this without full articles.update
      access: { update: requireCapabilityField('articles.metadata.update') },
      fields: [/* ... */],
    },
  ], 'articles.update'),
}
```

#### Per-User Capabilities

A `capabilities` multi-select field on Users allows assigning individual capabilities per-user — extend a role, start blank with specific capabilities, or use wildcards. Capabilities covered by roles are auto-removed on save. Escalation prevention ensures users can only assign capabilities they possess.

#### New Public API Exports

**Access function generators**: `requireCapability()`, `requireCapabilityField()`, `requireAnyCapability()`, `requireUpdateOrScoped()`, `publicOrCapability()`, `capabilityOrPublished()`, `capabilityOrSelf()`, `addScopedFieldAccess()`

**Capability utilities**: `hasCapability()`, `hasAnyCapability()`, `getUserCapabilities()`, `isDev()`, `getRoleCapabilities()`, `getAllRoleDefinitions()`, `getRoleOptions()`, `getCapabilityOptions()`

**Legacy access functions**: `admin`, `editor`, `authenticated`, `adminOrSelf`, `adminsOrPublished`, `authenticatedOrPublished`, `anyone`, `nobody`, `checkRole` — all still work.

#### Backwards Compatibility

No data migration needed — `admin`/`editor` role strings are preserved. `checkRole()` and `user.roles?.includes('admin')` patterns still work. Without the `roles` config option, behavior is identical to before.

---

### Systhema Figma Plugin & Dual Token Format (#12)

**If you're still using the abandoned "Design Tokens Manager" plugin**, this replaces it with a first-party `@systhemaui/figma` plugin. Full round-trip token sync between Figma and code.

- **Export**: Single-click export of all Figma variables and styles as W3C DTCG-compliant token files
- **Import**: Full round-trip sync with granular conflict resolution — dry-run analysis, mode mapping, per-variable Replace/Keep/Add/Skip actions, three-pass alias resolution
- **Core Dual Format**: New format is primary. Old format works via deprecated legacy adapter. Both produce identical CSS output.

```bash
# Migrate old tokens in-place
systhema migrate-tokens
```

---

### Custom Admin URL & AdminBar Extensibility (#27)

**If you've set up a custom admin domain or extended the AdminBar yourself**, Systhema now handles this natively.

```ts
withSysthema(config, {
  customAdminURL: process.env.ADMIN_URL,
  customLivePreviewURL: process.env.LIVE_PREVIEW_URL,
  whitelabel: {
    enabled: true,
    graphics: {
      Logo: '@/components/MyLogo',
      Icon: '@/components/MyIcon', // shared between admin panel and frontend AdminBar
    },
  },
  customCollections: [CaseStudies, PressReleases], // labels auto-extracted for AdminBar
})
```

Auto-configures routes, CSRF, cross-domain cookies, and live preview URL pinning. Zero overhead for logged-out visitors. The [Systhema Gateway](#add-systhema-gateway-27) handles admin domain routing.

> **Note:** Cross-domain admin does not work with `localhost` subdomains. Use a real domain alias for local development.

---

### Configurable Sitemaps (#28)

**If you have custom sitemap route files**, replace them with config-based sitemaps. With no config, `/sitemap.xml` auto-includes all published CMS pages.

#### Default mode (single flat sitemap)

```ts
withSysthema(baseConfig, {
  sitemaps: {
    additional: [
      // Static entry
      { url: '/login' },
      // Dynamic resolver from a collection
      async (payload) => {
        const posts = await payload.find({ collection: 'projects', limit: 1000 })
        return posts.docs.map(p => ({ url: `/projects/${p.slug}`, lastModified: p.updatedAt }))
      },
    ],
  },
})
```

#### Grouped mode (sitemap index + sub-sitemaps)

When `grouped: true`, generates a sitemap index at `/sitemap.xml` with sub-sitemaps served via `/sys/`:

```ts
withSysthema(baseConfig, {
  sitemaps: {
    grouped: true,
    additional: [
      { url: '/login' },                                // → /sys/pages-sitemap.xml
      { url: '/register' },                              // → /sys/pages-sitemap.xml
      { group: 'projects', entries: async (payload) => { // → /sys/projects-sitemap.xml
        const posts = await payload.find({ collection: 'projects', limit: 1000 })
        return posts.docs.map(p => ({ url: `/projects/${p.slug}` }))
      }},
    ],
  },
})
```

Entries use the full Next.js `MetadataRoute.Sitemap` shape (url, lastModified, changeFrequency, priority, alternates, images, videos). All sitemap responses include `Cache-Control: public, s-maxage=3600, stale-while-revalidate=600`.

#### New exports

| Export                                                                        | Package                       |
| ----------------------------------------------------------------------------- | ----------------------------- |
| `systhemaSitemapRoute`                                                        | `@systhemaui/payload/next`    |
| `systhemaSitemapGroupRoute`                                                   | `@systhemaui/payload/next`    |
| `SitemapEntry`, `SitemapResolver`, `SitemapAdditionalEntry`, `SitemapsConfig` | `@systhemaui/payload` (types) |

---

### Captcha Verification — reCAPTCHA & Turnstile (#20)

**If you've integrated captcha manually into your forms**, Systhema now supports Google reCAPTCHA v2 and Cloudflare Turnstile out of the box. Both can be configured simultaneously.

```ts
withSysthema(config, {
  forms: {
    fields: {
      recaptcha: {
        siteKey: process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY!,
        secretKey: process.env.RECAPTCHA_SECRET_KEY!,
      },
      turnstile: {
        siteKey: process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!,
        secretKey: process.env.TURNSTILE_SECRET_KEY!,
      },
    },
  },
})
```

Captcha blocks appear as form field types in the admin. Frontend widget loads on demand with skeleton loading, blocks submission until completed. Server-side verification happens automatically.

---

### User Avatar, Upload Ownership & FileGuard (#31)

**If you've added custom upload ownership or file validation**, Systhema now provides these built-in.

**User Avatar** — optional upload field on Users for profile pictures, rendered in the Payload admin top bar. Enabled by default (`users: { avatar: false }` to disable).

**Upload Ownership** — every upload tracks who created it. Users without full upload capabilities can still manage their own files:

| Capability        | Read     | Create | Update   | Delete   |
| ----------------- | -------- | ------ | -------- | -------- |
| None (basic user) | Own only | Yes    | Own only | Own only |
| `uploads.read`    | All      | Yes    | Own only | Own only |
| `uploads.update`  | All      | Yes    | All      | Own only |
| `uploads.delete`  | All      | Yes    | All      | All      |

**FileGuard** (renamed from FileSizeGuard) — validates both file size AND MIME type client-side:

```ts
withSysthema(config, {
  uploads: {
    maxFileSize: 50 * 1024 * 1024,
    allowedMimeTypes: ['image', 'application/pdf'],
  },
})
```

---

### Custom Error Messages & Checkbox Required Modes (#21)

Form fields now support custom error messages via Advanced Settings. Checkbox groups have a configurable required mode: **Each option** (all must be checked) or **At least one**.

---

### `strictDraftTypes` (#19)

The default config now enables `strictDraftTypes: true`, generating stricter TypeScript types that distinguish between draft and published document shapes.

---

### Emails Toggle (#11)

**If you manage emails independently** (custom templates, different env vars), disable Systhema's email features:

```ts
withSysthema(config, { emails: false })
```

---

### New TailwindCSS Color Tokens (#14)

Added **mauve**, **olive**, **mist**, and **taupe** color tokens matching TailwindCSS v4.2. Available in Figma designs and project variable resolution.

---

## 🐛 Fixes & Internal Improvements

### Bug Fixes

- **Disabled buttons** now correctly show the default color variant instead of hover colors (#13)
- **Form relationships inside Lexical blocks** are now properly populated — forms were only rendering in preview mode before (#25)
- **Server-only modules** no longer leak into client bundles when running in workspace mode — fixes 500 errors caused by `sharp`, `revalidatePath`, and `@payloadcms/richtext-lexical` internals (#24)
- **Draft pages** are no longer visible to public visitors — explicit `_status: 'published'` filter added (#28)
- **Live preview hydration mismatch** fixed by initializing `isLivePreview` from search params (#28)
- **Token asterisks** in the new Figma plugin format are now stripped from token names and references — fixes CSS build errors like `var(--color-bunker-950*)` (#32)
- **Uploads public read access** restored — uploads were incorrectly restricted to authenticated users only (#33)
- **AdminBar capability checks** — Edit and New links are now hidden for users without the required capabilities (#34)
- **Email capabilities** no longer registered when the Emails global is disabled — prevents phantom capabilities from appearing in role configuration (#35)
- **Payload template** — replaced `middleware.ts` with `proxy.ts` for Next.js 16 and fixed `Invalid URL` error from missing `NEXT_PUBLIC_SERVER_URL` (#36)
- **seed-dev script** now uses Payload's bin script API instead of importing `@payload-config` directly — fixes build errors in consumer projects (#37)
- **AdminBar collection override** — new `collection` prop allows explicitly setting the collection slug, useful when auto-detection fails on custom page types (#38)
- **"Block not found" during HMR** — Lexical editor block resolution now uses a stable lookup map instead of fragile array indexing, fixing crashes during hot module replacement (#39)
- **Plugin stores survive HMR** — custom blocks, text states, and plugin options stores now persist on `globalThis` to prevent state loss during hot module replacement; reverts editor changes from #39 in favor of this approach (#40)
- **Block `_sanitized` flag cleared on HMR** — sanitized blocks no longer skip re-initialization after hot module replacement, fixing stale block configuration (#41)
- **Source maps no longer published** — `react`, `next`, and `payload` packages were shipping `.js.map` and `.d.ts.map` files, exposing original TypeScript source. Source map emission is now disabled in both `tsup` and `tsc` configs (#42)
- **ESLint warnings** resolved across the payload package — unstable `useMemo` deps, missing `useEffect` dep, unused import (#26)
- **API URL** hidden from all collections and globals in the admin panel
- **Type generation** now uses `tsx watch` in dev mode for faster iteration

### Internal / Monorepo

- **Workspace simplification** (#29) — templates are now proper workspace members, `pnpm use:workspace` / `pnpm use:published` scripts removed
- **Template cleanup** (#23) — example code moved to `examples/` directories
- **CI** — GitHub Actions cleaned up, duplicate build eliminated, Node 22, concurrency controls
- **Design tokens** re-exported and updated across all templates (#30)
- **Registry cleanup** — all `1.0.0`–`1.4.1` stable versions on GitHub Packages were re-published without source maps, and all leftover beta/canary/internal versions outside the `1.5.0` line have been deleted from the registry. Production sites using `--frozen-lockfile` against an affected version will need to refresh their lockfile, since tarball shasums changed.

---

## List of all changes

### 🚀 Features

#### core

- feat(figma,core): Systhema Figma plugin and dual token format support (c473ee2) (#12)

#### payload

- feat(payload): capability-based access control system (8f0e4f1) (#7)
- feat(payload): add @payloadcms/typescript-plugin as peer dependency (b226a29) (#18)
- feat(payload): enable strictDraftTypes in default config (9ba0c69) (#19)
- feat(payload): Google reCAPTCHA and Cloudflare Turnstile captcha form fields (6b25808) (#20)
- feat(payload): custom error messages, checkbox required modes, and form fixes (1d9b458) (#21)
- feat(payload): add custom admin URL, live preview URL, and AdminBar extensibility (ad87ccc) (#27)
- feat(payload): add user avatar, uploadedBy tracking, FileGuard, and admin component consolidation (0bd0855) (#31)
- feat(payload): add collection prop to AdminBar for explicit override (297220d) (#38)

#### general

- feat: support manual internal publish from any branch, use canary tag for main (0a91fee)

### ♻️ Refactors

#### payload

- refactor(payload): migrate imageURL to admin.images.icon for Payload 3.80 (0fd8f9d) (#17)
- refactor(payload): consolidate (systhema) pages into unified [[...segments]] catch-all (940b33b) (#28)

### 🐛 Bug fixes

#### core

- fix(core): enforce default color variant on disabled buttons (c6d9a75) (#13)
- fix(core): prevent doubled !important in animation disable utilities (fc21dd2) (#22)
- fix(core): strip asterisks from token names in new format pipeline (b13e973) (#32)

#### payload

- fix(payload): add emails toggle to decouple Emails global from email adapter (a24492d) (#11)
- fix(payload): prevent server-only modules from leaking into client bundles (ebdc3d0) (#24)
- fix(payload): populate form relationships inside Lexical blocks (85747db) (#25)
- fix(payload): resolve all ESLint warnings (ef85f18) (#26)
- fix(payload): resolve lint warnings — useMemo for allowedMimeTypes, prefix unused importMap (2847264)
- fix(payload): use tsx watch for type generation in dev mode (453054c)
- fix(payload): hide API URL from all collections and globals (49e45ce)
- fix(payload): allow public read access for uploads (b3f76b6) (#33)
- fix(payload): hide AdminBar Edit/New links for users without capabilities (acbbfc7) (#34)
- fix(payload): don't register email capabilities when Emails global is disabled (bcf86a5) (#35)
- fix(payload): use Payload bin script API for seed-dev instead of @payload-config import (c3680cc) (#37)
- fix(payload): resolve "Block not found" error during HMR (15d258c) (#39)
- fix(payload): persist stores on globalThis to survive HMR, revert editor changes (0ccf54e) (#40)
- fix(payload): clear \_sanitized flag on blocks to fix HMR re-initialization (d6c69d8) (#41)

#### templates/payload

- fix(templates/payload): set postcss base to project root for CSS resolution (e4fddd8)
- fix: replace middleware.ts with proxy.ts and fix Invalid URL in payload template (580d5fd) (#36)

#### general

- fix: use internal tag for all pre-release builds, reserve canary for release cycles (e8d4b0c)
- fix(\*): disable source maps in published packages to prevent source code disclosure (50b2a1e) (#42)

### 💄 Style

#### general

- style: format (451d657)
- style: format payload package with prettier (d89140c)

### 📚 Docs

#### general

- docs: add gateway example with simple, admin domain, and extended usage (2ab7809)
- docs: add v1.4.1 release notes (03656fe)

### ⏪ Reverts

#### core

- revert(core): move animation disable classes back to addUtilities (8e470bc)

### 🧹 Chores

#### core

- chore: add new tailwindcss color tokens (717e13b) (#14)
- chore(core): bump tailwindcss peer dependency to ^4.2 (63a8e64) (#15)

#### payload

- !chore(payload): revise default plugin options and replace hardcoded env vars (f24d0f2) (#23) (breaking)
- chore(payload): bump payload peer dependencies to ^3.80.0 (ebfdae8) (#16)
- chore(payload): add lint and format scripts (465c525)
- chore: update design tokens across all templates and core (656c909) (#30)
- chore: update payload template with importMap, whitelabel icon, and gateway (baaa793)

#### general

- chore: simplify workspace setup, migrate next.config to TypeScript (e68529f) (#29)
- chore: rename publish workflow to release (1899ca4)
- chore: clean up GitHub Actions — concise syntax, concurrency, Node 22 (771d3a6)
- chore: eliminate duplicate build in CI by merging internal publish into build workflow (9b833f3)
- chore: switch to published packages and fix dependencies (a974927)
