v1.8.0
Payload 3.93 security fixes, a five-minute login lock, authors limited to their own posts, components without stock Tailwind classes, motion and stacking tokens, and Systhema Docs with an MCP server for agents.
On this page
✨ HighlightsLink to this section
1.8.0 starts with security. It requires Payload 3.93.0, Payload's November 2026 security release, and fixes two weaknesses in Systhema itself: a locked account unlocked after 0.3 seconds instead of five minutes, and the Posts Author role could edit every post. Every Payload project should upgrade.
The rest of the release makes Systhema a cleaner base under Tailwind. Components no longer ship stock Tailwind classes, so a class you pass in className always wins. Every component takes classNames for its inner parts. Typography colours get text-heading, text-copy and text-meta. Motion and stacking come from design tokens. None of this changes how a page looks: each change was compared element by element against 1.7.6 on real consumer sites, at desktop and mobile widths. The documentation moves to Systhema Docs, versioned per release, and coding agents can read it through an MCP server.
Security: Payload 3.93.0Link to this section
Payload marks 3.93.0 as "vital security updates":
- Read access on child blocks is now enforced in queries.
- A block field accepts only its configured block types.
pasteURLrestrictions apply to remote URL uploads.- The XML response policy covers XSL.
- The Open Graph endpoint clamps its description.
- The Lexical HTML converters escape stored values.
These fixes have no GHSA ids yet. Every @payloadcms/* peer of @systhemaui/payload is now ^3.93.0. Both bundled Payload patches are regenerated as @payloadcms__ui@3.93.0.patch and @payloadcms__richtext-lexical@3.93.0.patch, with every hunk kept. systhema upgrade and systhema doctor install them.
Payload 3.92 raised its Node.js floor to ^22.23.4 || >=24.22.1, so Payload projects need one of those. The Payload template's engines.node follows. Projects without Payload stay on Node 20.9 or later, and the CLI on Node 22 (#290).
New projects also get new and raised pnpm.overrides floors:
| Override | Fixes |
|---|---|
dompurify@>=3.0.0 <3.4.17 → ^3.4.17 | 19 advisories on the copy monaco-editor pins, through @payloadcms/ui |
@babel/core@>=7.0.0 <7.29.6 → ^7.29.6 | GHSA-4x5r-pxfx-6jf8, through next > styled-jsx |
fast-uri@>=3.0.0 <3.1.9 → ^3.1.9 | four advisories |
nodemailer@>=10.0.0 <10.1.4 → ^10.1.4 | SMTP and SendGrid projects |
undici@>=6.0.0 <6.29.1 → ^6.29.1, undici@>=7.0.0 <7.30.1 → ^7.30.1, undici@>=8.0.0 <8.12.2 → ^8.12.2 | the October and November undici CVEs |
Locked accounts stay locked for five minutesLink to this section
After five failed logins, an account now stays locked for five minutes. Before, it stayed locked for 0.3 seconds, so a password-guessing script was barely slowed down.
The cause was a unit mismatch. The users.auth.lockTime option is documented in seconds (default 300), but it reached Payload unchanged, and Payload reads lockTime in milliseconds. Systhema now converts it, and a booted-Payload test pins the lock (#284).
Authors edit only their own postsLink to this section
The Posts module's built-in Author role now edits only posts where it is the author. Before, an author could edit any post, including other authors' drafts and the SEO fields of published posts. An author also always becomes the author of the posts they create and save, so they cannot publish under someone else's name or hand a post over. Authors still read every post. Publishers, admins and custom roles with posts.update are unchanged.
The role trades posts.update for a new posts.updateOwn capability. The new exported helper requireUpdateOwnOrScoped(collectionSlug, ownerField = 'author') gives your own collections the same rule (#285).
A Tailwind class in className always winsLink to this section
Systhema components no longer put stock Tailwind classes in their markup. Before, <Stack direction="col"> rendered class="stack flex flex-col". A md:flex-row you passed sat in the same layer, so Tailwind's internal sort order decided which one won. Now every prop maps to a Systhema class that sits below Tailwind's utilities:
| Where | Before | Now |
|---|---|---|
<Stack> | flex, flex-col, justify-between, max-md:flex-row … | .stack is a flex box itself; stack-col, stack-justify-between, max-md:stack-row … |
| Stack divider | self-stretch / w-full plus an inline style | stack-divider-vertical / stack-divider-horizontal, restyled with classNames.divider |
| Payload Stack block items | flex-1, grow, self-* | stack-item-flex-1, stack-item-grow, stack-item-self-* |
<Image> / <Video> objectFit, objectPosition | object-cover, object-left-top | media-fit-cover, media-position-top-left |
Media blocks' align field | mr-auto, mx-auto, ml-auto | figure-align-left, figure-align-center, figure-align-right |
| PostCard, HighlightCard, PostMeta, ShareButtons | flex flex-col gap-4, absolute inset-0 … p-7 … | the .post-* rules in core's posts CSS |
Two stock utilities stay on purpose: aspect-*, now without brackets (aspect-4/3), and sr-only!. The layer order is documented in Cascade layers (#286, #287).
classNames for a component's inner partsLink to this section
className styles a component's root. The new classNames prop reaches the inner elements the component renders itself. Each value is added after that part's default classes:
<Section classNames={{ container: 'max-w-none', content: 'gap-xl' }}>…</Section>
<Carousel classNames={{ thumbs: 'gap-sm', nextButton: 'rounded-full' }}>…</Carousel>It covers Section, the three heroes, Carousel, Gallery, SearchField, Stack, AccordionContent, the Header and Footer wrappers and icons, and the Posts components, in react and in the Next twins. Each component page has a "Styling the parts" table (#286).
text-heading, text-copy and text-metaLink to this section
Typography colours get text-* classes that pair with type styles the way Tailwind's text-red-500 text-2xl do: text-heading text-h1, text-copy text-body. The colour roles behind them are renamed to match: typography.body is now typography.copy, and typography.label is now typography.meta.
Everything old keeps working in 1.x: color-heading, color-body, color-label, --color-typography-body, {typography.body} references, and customTokens overrides under either name. systhema upgrade renames the roles in your token files.
cn() also stopped dropping Systhema classes. It treated every text-<word> as a colour, so cn('text-h1 text-heading') returned text-heading alone, and a PostCard title lost text-h4 when you passed text-white (#286, #292).
Motion and stacking from tokensLink to this section
Component durations, easing curves and page-level z-index values now come from tokens. Every value falls back to what it was before:
transitioncollection. It drives the header menu and its overlay, sub-menus, chevrons and toggle, the checkbox and radio marks, the video play overlay and its hover zoom, the share pills and the cookie banner. For example,header.menu.transitionDurationbecomes--transition-header-menu-transition-duration.zIndexcollection (new). It sets--z-index-header(40),headerMenu(50),headerMenuOverlay(45),postShare(40),cookieConsent(100) andskipLink(9999).- Durations.
easingsgainsfast(150ms),normal(300ms) andslow(500ms).
Core ships all of these at the values components already used, and the upgrade adds them to your project, so you can tune motion in Figma. With reduced motion on, the mobile menu, its sub-menus, chevrons and toggle, and the media hover zoom now snap to their end state instead of animating (#289, #292). See Motion tokens and Token collections.
The cookie banner without !importantLink to this section
The banner now loads vanilla-cookieconsent's stylesheet inside @layer components. Unlayered, it beat every layer, so Systhema's banner theme needed !important on almost every declaration. 136 of the theme's 143 !important declarations are gone, and your own CSS in @layer app now overrides the banner without !important.
The banner's category switches also read their own cookieConsent.toggle.* tokens. By default they alias the form switch tokens, so the banner looks the same. Detach one in Figma to style the banner's switch on its own (#286, #292).
Systhema Docs and an MCP server for agentsLink to this section
The documentation now lives at docs.systhema.app, with a page for every component, utility family and Payload block, and live demos. The site keeps a copy of the docs for each minor version. The Editor guide for site owners, the home page and the release notes are public. The developer docs need the GitHub token you already use to install Systhema, or an issued access key.
Coding agents get the docs for the project's installed version through a systhema-docs MCP server:
systhema mcp add docs --agent claude,codex,cursor --scope project
systhema mcp listsysthema mcp writes the entry for Claude Code, Codex, Cursor, VS Code, Gemini CLI and OpenCode. The entry runs systhema mcp serve docs, which sends the key the CLI already uses for the registry, so no key ends up in an MCP config. A new docs-access doctor check warns when that key is missing or no longer opens the docs.
The consumer skills shrink from about 95,000 to 18,000 words. They keep the field-tested guardrails and look everything else up in the docs. Runtime messages that cite a page now link https://docs.systhema.app/v/<installed version>/… instead of a repository path (#264). See MCP server and systhema mcp.
Smaller stylesheet, missing post CSS restoredLink to this section
Projects now scan a class list that each package build writes (dist/systhema-classes.txt) instead of Systhema's compiled JavaScript:
- Doc comments and JavaScript negations no longer generate CSS. A consumer-style compile drops from 543.8 KB to 401.8 KB raw (25.8 KB brotli).
- Post pages get the CSS for
post-byline-meta,post-meta-author-roleandpost-related-titleback. Payload's frontend templates were never scanned. - The header menu toggle's hover icon colour now applies. A selector typo had stopped it from matching.
(#286, #287)
⬆️ UpgradeLink to this section
pnpm add -g @systhemaui/cli@latest
cd <your-project>
systhema upgrade --dry-run
systhema upgrade --yesThe upgrade moves Payload projects to Payload 3.93.0 and installs both bundled patches. It runs no codemods and no database hooks. Its token step offers one batch that changes nothing on the page:
- It renames
typography.bodytocopyandtypography.labeltometaincolorSystem. Thebodytype size inresponsiveSizingis left alone. Core's three{typography.body}references are rewritten only when they still hold the stock value; other references resolve through the alias. - It adds
fast,normalandslowtoeasings. - It writes the
transitionandzIndexcollections and their manifest entries. - It points the cookie banner's
cookieConsent.toggle.*tokens at the form switch tokens. The banner always rendered the form switch, so nothing visible changes.
footer.social.iconSize is not added to existing projects. On a 1.7 project the footer's social icons size from their own glyph aspect, and the token would square them at 24px. That visible change waits for 2.0. New projects get the token from core.
Check Node.js on Payload projects. You need ^22.23.4 or >=24.22.1. Update .nvmrc, .node-version, Docker base images and your host's Node setting.
Check users.auth.lockTime. If you set it in milliseconds to work around the bug (for example 300000), set it in seconds now (300). Otherwise the lock lasts 1,000 times longer.
Give authors posts.update if they must edit each other's posts, through a custom role, overrideRoles or per-user capabilities. Posts without an author can no longer be edited by authors; a publisher can assign one.
Copy the new override floors into existing projects. systhema upgrade does not write pnpm.overrides. Add the floors from the table above to your pnpm.overrides, then run pnpm install.
Connect your agents to the docs with systhema mcp add docs --agent <agents>.
⚠️ Breaking & Behavioral ChangesLink to this section
1. Payload projects need Payload 3.93 and Node.js 22.23.4 or 24.22.1Link to this section
The payload and @payloadcms/* peers of @systhemaui/payload are ^3.93.0. Payload 3.92 raised Payload's own Node floor to ^22.23.4 || >=24.22.1. The vendored AI SDK moves to version 7. Its deprecated names (system, totalUsage, toTextStreamResponse) are replaced inside the package, and the AI module's behaviour and stored usage are unchanged (#290).
2. users.auth.lockTime reaches Payload in millisecondsLink to this section
The option stays in seconds and is now multiplied by 1,000. A project that already passed milliseconds gets a lock 1,000 times longer (#284).
3. The Author role edits only its own postsLink to this section
Authors lose posts.update and get posts.updateOwn. Their author field is always set to themselves on create and save (#285).
4. Components render Systhema classes instead of stock Tailwind classesLink to this section
Computed styles are unchanged. Markup changes in three ways:
- CSS, tests or scripts that select Systhema components by
.flex,.flex-col,.object-coveror.mx-autono longer match. Select by the Systhema class instead. - Default aspect classes lose their brackets:
aspect-[4/3]is nowaspect-4/3. - Thirteen rules that only comments or plain code in Systhema's packages ever triggered are no longer generated from them:
.grid,.contents,.object-cover,.fixed,.border,.transform,.resize,.ordinal,.visible,.grow,.shrink,.line-clamp-5and.line-clamp-none. A project that uses them in its own markup still gets them from its own scan.
(#287)
5. GalleryWrapper's className goes to its rootLink to this section
It used to go to every slide. Use classNames.slide for the slides (#286).
6. Deprecated: color-* classes and the body and label colour rolesLink to this section
color-heading, color-body, color-label, typography.body, typography.label and --color-typography-body/--color-typography-label keep working in 1.x and will be removed in 2.0. Use text-heading, text-copy, text-meta, typography.copy, typography.meta and --color-typography-copy/--color-typography-meta.
A project colour role whose text- name clashes with one of its own text styles keeps only its color-<role> class, with a build warning (#286, #292).
7. Reduced motion stops more parts from movingLink to this section
With prefers-reduced-motion: reduce, the mobile menu panel, its overlay, sub-menus, chevrons and toggle lines, and the media overlay image zoom now get transition-duration: 0s. Colour fades keep their timing (#289).
8. The cookie banner's library CSS sits in @layer componentsLink to this section
Your own overrides with !important still win. Unlayered project CSS now beats the library's rules too. The library moves to vanilla-cookieconsent 3.3.0, which appends the modal to <body> and reads navigator.languages (#286, #290).
9. Runtime messages link docs.systhema.appLink to this section
Messages that printed a repository path or a GitHub URL now link the public docs page for the installed version. Developer pages need the registry token or an access key (#264).
🐛 Fixes & Internal ImprovementsLink to this section
Bug FixesLink to this section
spacing-resetworks on Tailwind 4.3.4 and later. A roottheme('spacing')started returning the whole spacing scale, so the class emitted a broken rule instead of--spacing: 4px(#290)- A repeated swapped spacing variable is wrapped once.
var(--x) var(--x)became a double-wrapped--spacing()in the header menu toggle'smask-size(#286) - The Next and HTML starters ship the cookie consent tokens. 48
--cookie-consent-*variables were unresolved in new projects (#286) - The columns spacer drops its nine
!importants, so a project can size or show it (#286) - The Figma plugin reads Figma's current composed colours. Since November 2026, Figma hands an alias with an opacity over as
{ color, opacity }. The plugin exported five foundation colours as raw objects that core could not read. It now exports and re-imports them correctly. The plugin is renamed Systhema Design Tokens Manager and shows its version in the window (#291) - The doctor's
missing-tokenscheck no longer reports an addition into a collection that a migration introduces; the missing collection is the one finding (#292)
Internal / MonorepoLink to this section
- Node 24.22.3 for the monorepo, CI and the demo and design images, after the October and November Node security releases (#279, #288)
- Every other dependency bump that passes: ESLint 10, Next 16.4.6, Tailwind 4.3.5, Vite 8.3.8 and Vitest 5.1 among them. The undici CVEs are patched across the workspace (#280, #290)
- The demo installs its security overrides and keeps them when its Docker build pins the Payload family (#281, #282, #283)
- A token
renametakes an optionaltargetcollection.typography.bodyis also a type size inresponsiveSizing, so the role rename would otherwise have renamed both (#292) docs/is restructured into the Systhema Docs tree, withpnpm docs:generate,docs:check,docs:snapshotanddocs:keys, regenerable screenshots and Editor guide translations (#264)
List of all changesLink to this section
🚀 FeaturesLink to this section
apps/docsLink to this section
- feat(apps/docs): add Systhema Docs, versioned docs with an MCP server for agents (#264) (b43089b7)
coreLink to this section
- feat(core): read component motion and stacking from tokens (#289) (20d8cdd1)
- feat(core): follow the refreshed Figma starter tokens (#292) (6b45bf54)
figmaLink to this section
- feat(figma): rename the plugin and read figma's new composed colours (#291) (008f9d71)
🐛 Bug fixesLink to this section
apps/demoLink to this section
- fix(apps/demo): update published systhema pins to 1.7.6 (#281) (07c8caa7)
- fix(apps/demo): apply the template security overrides to the demo install (#282) (edbb9cb0)
- fix(apps/demo): keep the security overrides when pinning the payload family (#283) (0821f308)
core, react, nextLink to this section
- fix(core,react,next): restore missing css, order the cascade and expose component parts (#286) (99ef88b0)
core, react, next, payloadLink to this section
- fix(core,react,next,payload): ship systhema classes only and scan a class manifest (#287) (621d7ab0)
depsLink to this section
- fix(deps): patch undici CVEs (#280) (149b035f)
payloadLink to this section
- fix(payload): lock an account for five minutes, not 0.3 seconds, after failed logins (#284) (8b80ca19)
- fix(payload): limit the author role to editing their own posts (#285) (5b24fdfa)
generalLink to this section
- fix: pin Node 22.23.4 (October 2026 security release) (db3d5268)
- fix: pin Node 24.22.3 (November 2026 security release) (#288) (1762dfda)
🧹 ChoresLink to this section
apps/demo, apps/designLink to this section
- chore(apps/demo,apps/design): use node 24 for apps and ci (#279) (be7311cc)
depsLink to this section
- chore(deps): refresh dependencies for 1.8.0 (#290) (e487324e)