Styling
TYPO3 Astryx uses StyleX for component recipes and design variables, with
skom/ resolving compiled classes in native Fluid templates. This guide
defines the source layout, naming rules, theme model and build steps for the extension and its
consuming sitepackage.
StyleX and upstream Astryx document APIs and design principles; neither mandates a particular folder hierarchy for this TYPO3 project. The conventions below are the project's source contract. For the CSS exception policy and the exact frontend, RTE and backend-preview import graph, see StyleX and CSS integration.
Architecture and source layout
Keep authored sources under the package that owns them. The reusable extension owns shared UI, semantic token families and built-in themes. A Content Block owns a recipe or supporting rule that is used only by that block. The consuming sitepackage owns its brand styles and assets.
packages/
typo3_astryx/
Resources/Private/JavaScript/
frontend.entry.js
rte-editor.entry.js
backend-preview.entry.js
StyleX/
components/ # reusable native Fluid and page recipes
tokens/ # defineVars modules grouped by semantic family
components/ # component-specific public token families
themes/ # one lowercase theme module per theme identity
ContentBlocks/ContentElements/<block-name>/
src/ # styles owned by this block only
Resources/Private/CSS/
main.css # import aggregator; no component rules
rte.entry.css # reset, fonts, themes and prose foundations
preview.entry.css # imports the shared RTE foundation
themes.css # GENERATED complete CSS token bridge
layers.css # cascade-layer order
prose.css # CKEditor and arbitrary prose markup
navigation-backdrop.css # native dialog ::backdrop exception
astryx_sitepackage/
Resources/Private/JavaScript/
site.entry.js
StyleX/components/ # sitepackage-owned recipes, when needed
Resources/Private/CSS/
main.css # declaration-free Vite layer anchor
Use lowercase kebab-case for StyleX source folders and filenames. Give every .stylex.
file a unique basename within its package manifest because the connector also creates basename
aliases from those names. Fluid component filenames and the public Fluid recipe names remain
PascalCase; their manifest keys use the lowercase recipe module basename, for example Button
resolves to button..
Use the source folder for authored files and the Resources/ folders for generated
assets. Never edit the generated StyleX manifests, compiled CSS or JavaScript, checksums,
Build/ or Resources/ by hand.
Token groups and StyleX recipes
Token sources use stylex. and one named export per file. The family is both a
discovery boundary and a variable group that themes may override. Build/
lists every family and theme source; the bridge and ownership verifier use this explicit contract.
| Family | Source location | Example public names |
|---|---|---|
| Color roles | Style | --, -- |
| Category and code colors | Style and code- | --, -- |
| Typography, spacing, layout, shape, shadow and motion | Style | --, -- |
| Component tokens | Style | -- |
Name public CSS variables with the stable namespace -- followed by lowercase
kebab-case semantic segments. Use a predictable order:
--
Not every token needs every segment. Examples include --,
--, --,
-- and --.
Choose names by intended role, not by a current hex value, theme, mode or a component's incidental
CSS declaration. Add a component segment only for a deliberate themeable component contract.
Keep mode and theme identity out of token names. A semantic token such as
-- resolves in Neutral, Stone and Ocean and may use paired
light- values. This keeps recipes independent of a selected theme.
In StyleX recipes, import the define export and reference the token directly. Avoid
spelling public var references in recipe declarations:
import * as stylex from '@stylexjs/stylex';
import {colorTokens} from '../tokens/color-tokens.stylex.js';
export const styles = stylex.create({
root: {
color: colorTokens['--astryx-color-text-primary'],
backgroundColor: colorTokens['--astryx-color-background-surface'],
},
});
Use CSS custom properties in supporting CSS where CSS must consume a public token. A recipe-local
custom property is an implementation detail: keep it in its owning recipe or block stylesheet and
do not add it to the public token families. Site-specific overrides belong in the final
product cascade layer.
Theme strategy
Theme identity and color mode are independent axes. Neutral, Stone and Ocean are
theme identities; system, light and dark are modes. The selected theme maps stable
semantic roles to values, while mode-aware color values use light- and the element's
color-. Do not create separate Ocean Light/Ocean Dark theme identities.
Each theme lives in a lowercase kebab-case file under Style and uses
stylex. to override the relevant variable groups. Keep theme inputs sparse when a
token should inherit its default. Themes share the same public token schema; the bridge resolves
all defaults and overrides into a complete set for each theme. This complete output is required
for nested theme boundaries and for TYPO3 editor/preview CSS.
When adding a theme:
- Create a file such as
themes/. Import only the token groups it overrides and export a namedforest- theme. stylex. js createvalue for each changed group.Theme - Add its lowercase name and source path to
Build/.design- tokens. json - Import the theme module from
Resources/so StyleX compiles it into the frontend manifest.Private/ Java Script/ frontend. entry. js - Run
Build/. It validates the static source contract and generates the fully resolved theme map and scoped CSS bridge.generate- theme- bridge. mjs - Add the theme to
Classes/and to the page-theme choices inConfiguration/ Theme Resolver. php Configuration/. Add or update the matching label inTCA/ Overrides/ pages. php Resources/and the available-theme list in Configuration.Private/ Language/ locallang. xlf - Record upstream attribution and local changes in
Build/,upstream- versions. json Build/andadaptations. json THIRD_when the theme is adapted from another design system.PARTY_ NOTICES. md - Build and verify frontend, RTE and backend preview output. Check the new theme in light and dark modes and at nested theme boundaries.
Theme variables are scoped to [data-. The Neutral values also provide
the default scope for .ck- and .astryx-. Keep editor and preview styling
scoped so theme values do not leak into unrelated TYPO3 backend chrome. The page theme and mode
fields, system settings and optional visitor preference are resolved by the extension; preserve
that runtime contract when changing the theme catalogue.
The palettes should map to semantic roles such as text, surface, border, accent, status, code and category colors. Review foreground/background pairings together for contrast. Treat generated palette values as candidates: map them to roles and review the resulting pairings before adding them to a theme. Record upstream sources, licenses and local adaptations in the existing provenance files.
Sitepackage overrides
For product branding, prefer a site-owned StyleX recipe for site-specific component styling and the
extension's semantic theme/token contracts for shared appearance. Do not copy extension token
modules into the sitepackage. Place reusable site-only recipes under
astryx_ and import them from that
package's site.. Keep its Resources/ declaration-free; it is a
Vite layer anchor, not the product styling surface. Use product-layer CSS only for a specific
browser or integration surface that cannot be represented through the StyleX build path, and
document that reason beside the exception. Never target generated atomic class names.
Recipe ownership and naming
Use these ownership rules:
- Keep reusable native Fluid component recipes such as
button.andstylex. js heading.instylex. js Resources/.Private/ Java Script/ Style X/ components/ - Keep page chrome recipes centrally when they are consumed by page templates.
- Keep recipes used only by one Content Block in
Content. Name the module after its component or styling responsibility. A generic name does not make a one-block recipe shared.Blocks/ Content Elements/<block- name>/ src/<recipe- name>. stylex. js - Keep block-owned CSS and preview CSS in the same block's
src/directory. - Import every frontend recipe from
frontend.. RTE and preview entrypoints import the token index and their scoped CSS entrypoint.entry. js - Use finite static recipe keys. Keep the Fluid
ax:allowlist, module exports andrecipe Build/synchronized; never hard-code generated atomic class names.recipes. json
Tokens define reusable themeable values; recipes apply values to elements and express layout, states and variants. A one-off display or layout declaration belongs in its recipe rather than in a new public token. Avoid hand-authored CSS for controlled Content Block markup; the exception policy and file-by-file CSS wiring are documented in StyleX and CSS integration.
The connector exposes aliases based on the lowercase module basename, for example
button., notice. and carousel-. Public Fluid
components can retain PascalCase names such as Button for template readability.
The public CSS variable rename in this refactor is breaking for custom CSS, templates and themes that used the former token names. There are no compatibility aliases. Update those consumers using the [token migration table](TokenMigration.rst).
Build and verification
Run commands from the consuming TYPO3 project root, using DDEV for the project's pinned runtime:
# Regenerate complete theme CSS from source tokens and sparse theme overrides.
ddev exec node packages/typo3_astryx/Build/generate-theme-bridge.mjs
# Full Vite and extension asset build, finalization and verification.
ddev exec npm run build
# Run the StyleX source ownership and generated artifact audits directly.
ddev exec node packages/typo3_astryx/Build/verify-style-ownership.mjs
ddev exec node packages/typo3_astryx/Build/verify-artifacts.mjs
The build updates the consuming site's and extension's Vite assets and StyleX manifests. Deploy the resulting CSS, JavaScript, fonts, lazy chunks and manifests together. If a recipe basename or source path changes, rebuild both manifests and flush TYPO3 caches so Fluid resolves the new aliases.
For the CSS import and output map, see StyleX and CSS integration. For site theme settings, see Configuration.