Site275 Documents

Generated policies

Dynamic Fonts (client)

Apply this policy to every client, including panels, sites, themes, and mobile apps, and all shared client components and their source, public, and asset directories, in development and production. No font file may exist anywhere inside client repositories, source trees, public or asset directories, or packaged application bundles. Fonts downloaded at runtime may be stored in browser-managed caches or an application cache on the device; these caches must never become source assets or bundled files. Never bundle, commit, copy, generate, or embed fonts in a client, including base64 or data URLs and icon fonts. Fonts must be served dynamically over HTTPS from the statics subdomain of the current tenant, resolved through tenant runtime configuration. Do not hardcode a tenant domain or load fonts directly from third-party font services or repository URLs. Before a font is used, its files must be committed and pushed to the holizm/fonts repository in the correct directory structure: use the established language group, or common only for fonts designed to support multiple languages, and the font-family directory, with camelCase directory and file names. Reuse an existing family directory and its naming conventions; place new families under <group>/<fontFamily>/<fontVariant>.<extension>. Font definition CSS files, including every @font-face rule and its source, weight, style, and display descriptors, must also reside in holizm/fonts alongside the relevant font family and be served from tenant statics. Never define @font-face rules or keep font definition stylesheets in a panel, site, theme, app, or shared client source. Clients may declare font-family usage and load the remote definition stylesheet through shared infrastructure. Deploy those repository files to the tenant's statics service while preserving their paths. Shared client infrastructure must resolve and load the configured font families, weights, styles, and URLs; panels, sites, themes, and mobile apps only declare short font names through shared infrastructure. Keep these declarations in their existing composition files; never create separate font path configuration files in clients. Font repository paths, language groups, definition stylesheet filenames, and asset URLs must remain inside core infrastructure and must not leak into themes or sites. Qwik clients use reusable SVG icons; do not include or load icon fonts unless a future customer requirement explicitly authorizes them. Mobile client infrastructure must download fonts from the configured tenant statics URLs and register them with the native runtime before use. Reuse downloaded fonts through the device application cache and use a system-font fallback while fonts are loading or unavailable.

Correct examples

Font repository: common/roboto/regular.woff2
Font repository: persian/bYekan/bYekan.woff2
Runtime font URL: https://statics.<tenantDomain>/fonts/common/roboto/regular.woff2

Incorrect examples

src: url('./assets/regular.woff2') format('woff2');
src: url('/themes/51/assets/inter400.ttf') format('truetype');
src: url('data:font/woff2;base64,...') format('woff2');
@import url('https://fonts.googleapis.com/css2?family=Roboto');

Fix

Commit and push font files to their correct family directory in holizm/fonts, move their font definition CSS files and @font-face rules into the same repository, publish both fonts and definition stylesheets through the tenant statics service, configure the resulting runtime font references, and remove every source or bundled font file and embedded font from all clients, including panels, sites, themes, and mobile apps. Use shared runtime font loading and native registration for mobile apps.

Dynamic Images (client)

Apply this policy to every panel, site, theme, and mobile app, including shared client components and their source, public, and asset directories. No image file may exist inside these clients. Every content image must be loaded dynamically from runtime content, API data, or configuration, with its URL or media identifier supplied by that data. Never bundle, commit, copy, or generate image assets inside a client, embed static images as base64 or data URLs, or hardcode image URLs in components or styles. This includes photographs, logos, backgrounds, placeholders, and icons. When a visual element is part of the design itself, implement it as a reusable SVG component whose colors and appearance use currentColor, theme tokens, or component properties; do not store it as a static image file. Use each platform's shared image component to render dynamic content images.

Correct examples

<Image image={content.hero.image} />
<Image source={{ uri: content.hero.image.url }} />
<BrandMark color={theme.colors.brand} />

Incorrect examples

import heroImage from './assets/hero.jpg'
<Image source={require('./assets/logo.png')} />
<img src='/themes/51/assets/hero.png' />
<img src='data:image/png;base64,...' />

Fix

Store content images in the media service or external media storage, persist their URLs or media identifiers in runtime content or configuration, and render them through the shared image component. Replace bundled design visuals with reusable, themeable SVG components.

No Show Identifier (client)

In panel, site, theme, and mobile app JSX files, never use an identifier named show. Use display when it supplies rendered content or formats a value, and use visible when it controls visibility. Keep externally required show names inside non-JSX interoperability adapters.

Correct examples

<Item display={display} />
<Dialog visible={visible} />

Incorrect examples

<Item show={display} />

Fix

Replace a rendering show identifier with display, replace a visibility show identifier with visible, and update its consumers. Isolate an externally required show property in a non-JSX adapter.

Color Variables (css)

Define every CSS color as a semantic custom property in the owning bundle’s single variables.css file and reference that property wherever the color is used. This includes text, backgrounds, borders, outlines, shadows, gradients, SVG colors, interaction states, and scrollbars. Literal color values may appear only in custom-property definitions in variables.css so site and panel themes can replace colors without changing component rules.

Correct examples

:root {
    --surfaceColor: #fff;
}

.item {
    background-color: var(--surfaceColor);
}

Incorrect examples

.card { background-color: #fff; color: rgb(20 20 20); }

Fix

Move the literal color into a semantic CSS custom property in the owning variables.css file and replace its usage with var(--propertyName).

Compound Classes (css)

In CSS for sites, themes, panels, and shared client components, separate independently meaningful concepts into class tokens instead of joining them into compound names. Use class="cards bento" instead of cardsBento and class="product details" instead of productDetails. Assign each class separately to the same element so the component or domain role and its layout, section, variant, or state can be composed independently. Define shared behavior on the base class and combination-specific differences with .cards.bento or nested &.bento, and .product.details or nested &.details. A space in markup joins classes on one element; .cards .bento in CSS selects a descendant and is not an equivalent replacement. This rule applies to ordinary CSS independently of Tailwind. Keep component names, filenames, imports, and other non-class identifiers camelCase.

Philosophy

Separate classes make composition possible without copying rules or creating a new compound name for every combination. The cards class supplies the shared collection structure while bento selects its arrangement; the same cards can take another layout and the same bento concept can be reused wherever that arrangement makes sense. The product class supplies product behavior while details identifies the detailed presentation, allowing other presentations to retain the same product foundation. Assigning these concepts independently lets a component change one concern while preserving the others. Shared rules belong to their owning role, and combined selectors express only the differences that require both concepts, avoiding accidental effects on unrelated elements.

Correct examples

Assign the concepts separately on the same element: class="cards bento" and class="product details".

.cards {
    display: grid;

    &.bento {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
.product {
    display: grid;

    &.details {
        gap: 1rem;
    }
}

Incorrect examples

Avoid markup such as class="cardsBento" and class="productDetails".

.cardsBento {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.productDetails {
    display: grid;
    gap: 1rem;
}

Fix

Replace compound class names with separate semantic tokens in markup, CSS selectors, scripts, and tests. Keep the base role on each variant, reuse each token where its meaning applies, and scope combination-specific styles with combined selectors or nested & selectors.

Declaration Lines (css)

Put each @apply directive and each CSS declaration on its own line.

Correct examples

.item {
    @apply border;
    background: var(--surfaceColor);
}

Incorrect examples

.card {
    @apply border; color: var(--textColor);
}

Fix

Place every @apply and CSS property on a separate line between the selector braces.

Logical Direction (css)

Use logical start and end instead of physical left and right in CSS. This applies to properties, values, and directional utility classes, including utilities used through @apply.

Philosophy

Left and right describe fixed physical sides. Start and end follow the writing direction, so the same styles work in both LTR and RTL layouts.

Correct examples

.card {
    margin-inline-start: 1rem;
    padding-inline-end: 1rem;
    text-align: start;
}
.action {
    inset-inline-end: 0;
}

Incorrect examples

.card {
    margin-left: 1rem;
    padding-right: 1rem;
    text-align: left;
}
.action {
    right: 0;
}

Fix

Replace physical left and right with the corresponding logical inline-start and inline-end properties, values, or utilities. Verify the result in both LTR and RTL.

Nested Component Selectors (css)

Nest descendant, state, and pseudo-element rules inside their owning selectors instead of repeating flat selector paths.

Correct examples

.footer {
    .cta {
        &:hover {
            color: var(--interactionColor);
        }
    }
}

Incorrect examples

.footer .cta:hover {
    color: var(--interactionColor);
}

Fix

Move the descendant or state rule inside its owning selector and use & for states and pseudo-elements.

No Direct Utility Import (css)

Do not import or reference Tailwind directly in component, part, site, panel, or theme CSS. This includes @import and @reference directives targeting tailwindcss or its package subpaths. Load Tailwind once through the shared core global style entry; component styles may use @apply without importing or referencing Tailwind again.

Correct examples

@import './parts/media.css';
.virtualTour {
    @apply my-8 w-full;
}

Incorrect examples

@reference 'tailwindcss';
@import 'tailwindcss';
@import 'tailwindcss/utilities';

Exceptions

  • Site and panel core shared global style entry points may load Tailwind.

Fix

Remove the direct Tailwind @import or @reference and use the existing shared core global style entry.

Prefer Tailwind Utilities (css)

Try to use Tailwind utilities in CSS files instead of writing pure CSS.

Philosophy

Usually this causes lower lines of code and fewer bytes per file.

Correct examples

.links {
    @apply flex flex-wrap gap-4;
}
.icon {
    @apply size-5 fill-current;
}

Incorrect examples

.links {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.icon {
    fill: currentColor;
    height: 1.25rem;
    width: 1.25rem;
}

Exceptions

  • The enforcer checks only a conservative set of direct equivalents. It skips theme-dependent values, important declarations, ambiguous same-block overrides, blocks containing directives, and definition or keyframe contexts.

Fix

Use @apply with equivalent Tailwind utilities where practical, preserving existing behavior and semantic theme variables.

Property Order (css)

Sort CSS property declarations alphabetically within each selector. Keep @apply directives separate from the property order.

Correct examples

.item {
    @apply border;
    background: var(--surfaceColor);
    border-color: var(--lineColor);
}

Incorrect examples

.card {
    border-color: var(--lineColor);
    background: var(--surfaceColor);
}

Exceptions

  • Preserve source order when a shorthand and one of its longhands intentionally override each other.

Fix

Reorder CSS properties alphabetically without changing the order of repeated fallback values for one property.

Root Variables (css)

Define every CSS custom property in one variables.css file for each CSS bundle. Put default values at :root and theme overrides at the owning root selector in that same file. Component stylesheets must only reference those variables; they must not define variables, even in their own :root block. Keep Tailwind design tokens and permitted theme-root utility variables in variables.css too, so all values for a new theme can be found in one place.

Correct examples

variables.css:

:root {
    --surfaceColor: #fff;
}

:root.dark {
    --surfaceColor: #111;
}

Incorrect examples

components/browse.css:

:root {
    --browseTitleSurface: #fff;
}

.browse {
    .title {
        background: var(--browseTitleSurface);
    }
}

Fix

Move every custom-property definition into the owning bundle’s variables.css, group defaults and theme overrides by root selector, and leave only var(...) references in component stylesheets.

Selector Lines (css)

Put each selector in a group on its own line, with the opening brace after the last selector. Put declarations and nested selectors below the brace.

Correct examples

.item {
    @apply border;
}
.item,
.field {
    @apply border;
}

Incorrect examples

.card { @apply border; }
.card, .tile {
    @apply border;
}

Fix

Split grouped selectors at commas and move declarations and nested selectors below the opening brace.

Selector Spacing (css)

Leave one empty line between sibling CSS selectors, including nested selectors.

Correct examples

.item {
    @apply border;
}

.title {
    @apply text-xl;
}

Incorrect examples

.card {
    @apply border;
}
.title {
    @apply text-xl;
}

Fix

Insert one blank line after a selector block before the next sibling selector.

Semantic Color Variable Names (css)

In the owning bundle’s single variables.css file, choose each color variable name from its UI purpose, not its current value. Start with the narrowest meaningful element or semantic role, then add the colored property or interaction state when needed to distinguish it, such as --cardSurface, --cardBorderHover, or --footerHeadingText. If several elements use a color for the same purpose, name their shared role rather than the first element that used it; if their purposes differ, give them separate variables even when their current values match. A variable name must remain accurate at every place it is used. Avoid color words, palette shades, and numeric scales, such as green, darkBlue, or gray100, including in a one-page or one-tenant theme.

Correct examples

:root {
    --cardSurface: #fff;
    --cardBorderHover: #748f55;
    --ctaText: #fff;
}

.card {
    background-color: var(--cardSurface);

    &:hover {
        border-color: var(--cardBorderHover);
    }
}

.cta {
    color: var(--ctaText);
}
:root {
    --textOnDarkSurface: #fff;
    --footerHeadingText: #fff;
}

.hero .title,
.dialog .title {
    color: var(--textOnDarkSurface);
}

.footer .title {
    color: var(--footerHeadingText);
}

Incorrect examples

:root {
    --about-green: #748f55;
    --darkBlue: #1e3a8a;
    --gray100: #f3f4f6;
}
:root {
    --footerHeadingText: #fff;
}

.hero .title {
    color: var(--footerHeadingText);
}

Fix

Inspect every use of the variable, identify the common UI purpose or separate purposes, and name each variable accordingly. For example, replace --about-green with --aboutCardAccent, and do not use --footerHeadingText for a hero title.

Atomic Ui (jsx)

Build JSX as a recursive atomic hierarchy. Put reusable panel UI components in panel core and reusable domain site UI in part sites. Put site- or theme-specific UI and SVGs in their owning site or theme, never in site core. Compose leaf interfaces such as blog pages, course pages, lists, and forms from the appropriate components. Keep each layer focused so UI can be reused without moving visual elements into site core.

Boolean Attribute (jsx)

Pass a JSX boolean prop by its presence, such as someAttribute, instead of someAttribute={true}.

Correct examples

<Component someAttribute />

Incorrect examples

<Component someAttribute={true} />

Fix

Remove ={true} from boolean JSX attributes and keep the attribute name.

Composable Ui (jsx)

Make every JSX layer composable and reusable. Compose core atoms into larger part components, and compose part components into leaf interfaces without duplicating JSX for different sites, themes, panels, or panel themes. Use stable semantic component boundaries and canonical prop contracts so a component can be reused or replaced without replacing its parent, page, part, or bundle. Define shared compositions once and resolve configured implementations through progressively broader fallbacks when configuration is supported.

Concise Component (jsx)

When an arrow component body contains only a return statement returning JSX, return the JSX directly with a concise arrow function. Keep a block body when it contains additional statements, such as hooks, variable declarations, or conditional returns.

Correct examples

export default props => <Lookup {...props} />
export default props => <>
    <Title {...props} />
    <Content {...props} />
</>
export default props => {
    const value = useValue()
    return <Field value={value} />
}

Incorrect examples

export default props => {
    return <Lookup {...props} />
}
export default props => {
    return <>
        <Title {...props} />
        <Content {...props} />
    </>
}

Fix

Remove the block braces and return keyword, leaving the JSX directly after => without wrapping parentheses. Preserve existing comments.

Conditional Rendering Ownership (jsx)

Move conditional rendering controlled by a component-specific hasX prop into that component. Parent and intermediate components must render the child unconditionally and forward props unchanged; the controlled component must consume hasX and return null when it is false. Keep a condition in a parent only when it controls broader composition, layout, or coordination among multiple children.

Correct examples

export default props => <Items {...props} />
export default props => {
    if (!props.hasItems) return null
    return <ul />
}
export default props => <main>
    {
        props.hasDashboard && <>
            <Chart {...props} />
            <Legend {...props} />
        </>
    }
</main>

Incorrect examples

export default props => <main>
    {
        props.hasItems && <Items {...props} />
    }
</main>

Fix

Move the hasX guard into the controlled child. Conditions coordinating multiple children remain in the parent. Review ambiguous single-child layout guards manually.

Continuous Opening Tag (jsx)

Do not leave an empty line inside a multiline HTML or JSX opening tag.

Correct examples

<Component
    first={first}
    second={second}
/>

Incorrect examples

<Component
    first={first}

    second={second}
/>

Fix

Remove empty lines from the multiline opening tag.

Fragment Child Lines (jsx)

Place empty fragment tags on lines separate from their children. Put <>, every child, and </> on separate lines so fragment boundaries and sibling elements remain explicit.

Correct examples

<>
    <Title />
    <Content />
</>

Incorrect examples

<><Title /><Content /></>

Fix

Move the empty fragment opening and closing tags onto lines separate from their children while preserving the children and existing comments.

Headless Ui (jsx)

Keep the atomic JSX system headless. Components may define semantic structure, JavaScript behavior, state, and accessibility, but must not define UI appearance or look and feel. Do not put Tailwind utility classes or visual inline style declarations in JSX, including class fallbacks and class values passed through props. Expose semantic role and domain class names and implement visual decisions in the applicable site or panel styles.

Correct examples

export default props => <div className='item'>
    <Heading {...props} />
    <Content {...props} />
</div>
<Item class='video' />

Incorrect examples

export default props => <section style={{ color: 'red' }}>
    <Content {...props} />
</section>
<Item class='video w-full my-8' />

Exceptions

  • Write Tailwind sizing classes directly in Image.containerClass because the component reads them to calculate srcset.

Fix

Remove visual styling from JSX and implement it against semantic class names in theme CSS.

Jsx Attribute Formatting (jsx)

Keep an HTML or JSX opening tag with exactly one attribute on one line. When an HTML or JSX opening tag has two or more attributes, use a multiline opening tag and place every attribute on its own line. Always sort multi-lined attributes in JSX and HTML.

Correct examples

<Field value={value} />
<Field
    disabled
    value={value}
/>
<Field
    {...rest}
    disabled
    value={value}
/>

Incorrect examples

<Field disabled value={value} />
<Field
    value={value}
/>
<Field
    value={value}
    disabled
/>

Fix

Use one line for one attribute; otherwise give each attribute its own line and sort named attributes within each spread boundary. Preserve spread order because it controls overrides.

Jsx Expression Braces (jsx)

Place the opening and closing curly braces of JSX child expression containers on separate isolated lines. A single-line <td> containing only property access, including optional chaining, may keep its expression inline. For every multiline JavaScript expression inside JSX curly braces, including attribute values, place the expression on lines separate from both braces. Single-line attribute expressions may remain beside their braces.

Correct examples

export default item => <td>{item?.firstName}</td>
export default ({ title }) => <h1>
    {
        title
    }
</h1>
<Field
    disabled
    value={
        ready
            ?
            'yes'
            :
            'no'
    }
/>

Incorrect examples

export default ({ title }) => <h1>{title}</h1>
<Field
    disabled
    value={ready
        ?
        'yes'
        :
        'no'
    }
/>
<Field
    disabled
    value={
        ready
            ?
            'yes'
            :
            'no'}
/>

Exceptions

  • A single-line <td> element may keep inline braces when its only content is property access, including optional chaining. Calls, operators, additional content, and multiline cells do not qualify.

Fix

Put child-expression braces on their own lines, except in single-line <td> elements containing only property access. In multiline attribute expressions, put the opening brace after the attribute name, start the expression on the next line, and put the closing brace on a separate line after the expression.

Jsx Ternary Formatting (jsx)

Always format a ternary expression across exactly five parts on separate lines: the condition, ?, the true expression, :, and the false expression.

Correct examples

export default props => props.visible
    ?
    <Content />
    :
    null

Incorrect examples

export default props => props.visible ? <Content /> : null

Fix

Place the condition, question mark, true branch, colon, and false branch on separate lines. JSX branches may span multiple lines.

Light Qwik Component (jsx)

When a Qwik component does not require component$, convert it to a light component by removing component$ and any associated boilerplate.

Correct examples

import { component$ } from '@builder.io/qwik'
export default component$(() => {
    const count = useSignal(0)
    return <span>
        {
            count.value
        }
    </span>
})
export default props => <Content {...props} />

Incorrect examples

import { component$ } from '@builder.io/qwik'
export default component$(props => <Content {...props} />)

Fix

Remove component$ around presentation-only components. Keep boundaries using hooks, events, or Qwik slots; unknown calls are conservatively retained for review.

Nonempty File (jsx)

A JSX file must contain a meaningful minimal implementation. Empty, whitespace-only, and comment-only JSX files are not allowed.

Correct examples

export default props => <Content {...props} />

Incorrect examples


   

// Placeholder

Fix

Implement the intended component or module with the smallest useful code, or delete the unused file and its references.

One Component Per File (jsx)

Keep one primary JSX component in each file, including React and Qwik components.

Correct examples

export default props => <Content {...props} />

Incorrect examples

export const Header = props => <header {...props} />
export default props => <footer {...props} />

Fix

Move each additional JSX component into its own file.

Prop Destructuring Ownership (jsx)

Destructure props only in components that consume them. This usually means leaf components destructure props, although intermediate components may do so when they consume specific prop values themselves.

Correct examples

export default props => <Card {...props} />
export default ({ title }) => <h1>
    {
        title
    }
</h1>

Incorrect examples

export default ({ title }) => <Card title={title} />

Fix

Forward the original props object; destructure values only when consumed locally. This check detects parameter bindings used only as component attributes.

Semantic Class Names (jsx)

Name platform-owned JSX classes after the element's meaning or structural role, never its appearance, layout, or theme.

Correct examples

<footer className='footer'>
    <section className='cta' />
</footer>

Incorrect examples

<section className='blueBox' />

Fix

Replace the visual class name with one that describes the element's meaning or structural role.

Shared Ui Behavior (jsx)

Before creating a JSX component for an interaction, search the relevant core and part components for existing behavior and an accessibility contract. Reuse matching behavior. If no matching implementation exists and the interaction is domain-neutral, define its state and event handling once in headless core infrastructure, even when the first use is in one part or page. Site core may render reusable domain-neutral controls as headless JSX and semantic HTML. Put domain controls in the appropriate part site and site- or theme-specific controls in their owner. Core and part-site components must leave appearance styles to the consuming site or theme. Panel core may own reusable panel controls. Pass domain data and localized labels through generic props. A reusable clipboard action and its headless copy button may live in site core, with localized labels supplied through props and appearance supplied by the consuming site or theme.

Fix

Reuse matching interaction behavior or define missing domain-neutral behavior in headless core infrastructure. Keep rendered site controls in their owning site, theme, or part site.

Single Child Fragment (jsx)

When JSX contains only one element or expression, render it directly instead of wrapping it in an empty fragment. Use an empty fragment only to group multiple siblings.

Correct examples

<>
    <Title />
    <Content />
</>
<Field />

Incorrect examples

<>
    <Field />
</>

Fix

Remove the empty fragment around the single child while preserving the child and existing comments.

Static Jsx Export (jsx)

In panel and site code, export JSX directly when the default arrow has no parameters and its JSX contains no expressions or spreads. Panel builds wrap the value as a component; Qwik site code can render the value directly.

Correct examples

export default <div className='item'>
    <Title />
</div>
export default <ForcedVerticalScroll />
export default props => <Content {...props} />

Incorrect examples

export default () => <div className='item'>
    <Title />
</div>
export default () => <ForcedVerticalScroll />

Fix

Replace the parameterless arrow with its JSX body. In site code, update consumers to render the exported JSX value directly. Keep a function when props, hooks, or render-time values are needed.

Unparenthesized Returned Jsx (jsx)

Never wrap returned JSX in parentheses.

Correct examples

export default props => <Content {...props} />

Incorrect examples

export default props => (<Content {...props} />)

Fix

Remove parentheses around returned JSX while preserving comments.

Api Derived Data (site)

Keep clients as thin as possible by having the API calculate all required derived values. For example, never evaluate arrayVariable.length > 0 in client code. Instead, the API must provide a corresponding hasX boolean for conditional rendering, such as hasX && <Component />.

Client Api Environment (site)

Use local APIs for panel development and production APIs for site development. For example, admin.example.local connects to api.admin.example.local, while example.local connects to api.example.tld.

Component Placement (site)

In runnable sites, place components under site/parts/shared when used across multiple pages. Place components used by one page under site/parts/${page}, where ${page} is the page directory name. No component may reside directly in site/parts.

Correct examples

site/parts/shared/button.jsx
site/parts/contact/form.jsx

Incorrect examples

site/parts/form.jsx

Fix

Move the component into site/parts/shared or the matching page directory under site/parts, and update its imports.

Declarative Client (site)

Keep clients declarative and presentation-only. The API must return application data in its final render-ready shape, including ordering, filtering, grouping, ranking, normalization, counts, visibility flags, and other derived values. Client code must not interpret or transform application data; it may only map render-ready data to components and manage unavoidable presentation state or browser interactions. When uncertain, move the logic to the API.

Head Placement (site)

Define document metadata at supported site route or layout boundaries.

Image Component (site)

Use the platform image component instead of direct image tags when optimization and dimensions are available.

Import Order (site)

In site code, order imports from Qwik and Qwik City through third-party libraries, core, parts, and shared modules to local modules.

Correct examples

import { component$ } from '@builder.io/qwik'
import { routeLoader$ } from '@builder.io/qwik-city'
import SiteRoot from 'siteRoot'
import { Posts } from 'blog'
import { Header } from 'layout'

Incorrect examples

import { Header } from 'layout'
import { component$ } from '@builder.io/qwik'

Fix

Move imports into the required layer order.

Localized Site Text (site)

Store visitor-facing text and accessibility labels in localization resources.

No Inline Svg (site)

Never define SVG inline in a site or theme component. Extract every SVG into a standalone component in the owning site's or theme's parts/svg directory. Do not place SVG components in site core.

Fix

Move the standalone SVG component into the owning site or theme’s parts/svg directory and import it where needed.

No Qwik City Link (site)

Never use Qwik City's Link component. Use a standard semantic <a> element for links.

Optional Chaining (site)

Use optional chaining in site code wherever needed to prevent property access on an undefined or null value from causing the entire website to fail.

Responsive Image Sizing (site)

For Image, write the Tailwind sizing classes directly in containerClass, even when semantic class names are also present. Do not rely on semantic classes, @apply, or contextual CSS selectors to provide dimensions because Image reads the Tailwind classes from containerClass to calculate its dynamic srcset.

Serializable Boundary (site)

Pass only serializable values across Qwik serialization boundaries.

Tailwind Style Keywords (site)

In site and theme stylesheets, use Tailwind for shared design conventions: named responsive breakpoint variants and established spacing, sizing, and typography utilities when their meanings and values match the intended design. Use @apply to compose those utilities behind semantic selectors. Use plain CSS for custom values, CSS custom-property references, complex selectors, animations, and declarations that are clearer or more precise in native CSS. Do not force a declaration into an arbitrary-value utility or create an @utility merely to replace a clear CSS declaration; define custom utilities only for genuinely reusable behavior. Tailwind and plain CSS may coexist in the same rule. Preserve intended rendering, keep appearance in stylesheets, and follow the centralized breakpoint and theme-variable policies.

Philosophy

Tailwind provides shared design conventions; plain CSS remains appropriate when it expresses the intended rule more clearly. Do not convert declarations merely to maximize utility usage.

Correct examples

@variant md {
    .dialog {
        @apply p-8;
        min-height: 17rem;
    }
}
.detail {
    color: var(--textPrimary);
    font-size: 1.375rem;
}

Fix

Use named Tailwind breakpoint variants and matching established utilities for shared design conventions. Keep custom or clearer declarations in plain CSS without changing their rendered meaning or values.

Component Reuse (siteTheme)

Before creating UI in a site or theme, search site core at ~/site, the relevant part sites at ~/partName/site and the owning site or theme for reusable components. Reuse a component when it provides the intended structure and behavior. Put missing domain UI in its part site and site- or theme-specific UI in its owner. Site core may provide reusable domain-neutral components that render semantic HTML through JSX, together with shared behavior and accessibility. Part sites provide reusable domain components through the same headless JSX approach. Neither site core nor part-site components may define or import component appearance styles; the consuming site or theme supplies appearance through semantic classes. Core build infrastructure CSS remains permitted. Extend an existing component additively when that preserves its contract and behavior for dependent sites and themes. If it cannot support the intended result through such an extension, first add an explanation to a file named warning at the root of the site or theme. Name the component that cannot be reused and state the exact intended structure or behavior and why an additive extension cannot provide it. Then create a local component for that purpose. Keep theme appearance in theme styles.

Composable Styles (siteTheme)

Compose abstract core components with concrete part identity. A core List owns the list class and a core item component owns item; a part adds its domain class, such as videos on the list and video on each item, without replacing the core structure or behavior. The resulting root may be class="list videos" and each item class="item video". Both classes describe meaning or structural role. Do not add visual variant classes such as card or threeDimensional to markup. Style the abstract role first, then use combined role-and-domain selectors only for differences needed by that part. Keep CSS appearance in site or theme stylesheets.

Css Output Efficiency (siteTheme)

Keep generated site CSS small by reusing shared role rules and avoiding duplicate declarations across part, page, and content-type stylesheets. Place each common rule at the broadest site or theme style scope that needs it, and add only necessary overrides. When changing shared styles, inspect the production CSS output and representative pages to confirm that the rule is emitted once per theme, related UI remains consistent, and CSS size does not grow through duplication. Measure page performance when CSS changes are material; do not assume reuse alone guarantees a Lighthouse score.

Direct Core Images (siteTheme)

Do not create site or theme components whose sole purpose is to wrap the core Image component. Render the core component directly where the image is needed.

Philosophy

A wrapper adds an unnecessary abstraction without making the code cleaner.

Explicit Image Dimensions (siteTheme)

Every site and theme content image must declare explicit width and height sizing through the shared image component. For Image, put the Tailwind width and height classes directly in containerClass so shared infrastructure can select correctly sized resources. Define a base width and height and explicit breakpoint overrides wherever the displayed dimensions change. A fixed declaration may inherit across breakpoints where the dimensions stay the same. Scope fluid sizing such as w-full to the breakpoint ranges that require it; provide explicit width and height declarations for the remaining ranges. A base w-full is permitted only when later breakpoint overrides bound its range. Never use w-full across every breakpoint, h-auto, an aspect ratio, or contextual CSS as a substitute for the image sizing contract. Keep the inner image fitted to its declared container without distortion, and verify the rendered dimensions and responsive resource selection at every affected breakpoint.

Philosophy

Declared dimensions reserve image space and let shared image infrastructure request resources that match the layout.

Fix

Add the missing width and height classes to each shared image call, limit fluid sizing to its intended range, remove conflicting CSS dimensions, and check the rendered layout and requested image sizes across breakpoints.

Focused Style Imports (siteTheme)

Allow focused site and theme stylesheets to import other focused stylesheets. Use an acyclic import hierarchy: the main style.css imports coarse groups such as styles/items.css, and a group file imports its shared base before domain-specific styles. Keep each emitted stylesheet on one import path per compiled site or theme bundle. Import order must place base rules before overrides so the cascade is predictable. Do not import the same emitted stylesheet through several branches.

Correct examples

@import './list.css';
@import './item.css';
@import './videos.css';

Lighthouse Scores (siteTheme)

For every site theme section you design or change, run Lighthouse on a representative live page after publication. Keep the Performance score at 90 or above and Accessibility, Best Practices, and SEO at 100. Fix any regression before completing the work. If a required score cannot be reached, notify an administrator with the measured scores and unresolved findings.

Fix

Audit the affected live pages with Lighthouse, resolve the reported issues, publish the corrected section, and verify the scores again. Notify an administrator when a required score remains below its threshold.

No Site Or Theme Root Selector (siteTheme)

In site and theme stylesheets, do not wrap component rules in a site or theme root selector such as .siteRoot, .themeRoot, or .theme28. Write each component selector directly inside its owning @layer, with nested selectors only for that component’s descendants and states. Define site-wide or theme-wide custom properties at :root or the appropriate semantic root. A root class may remain in markup for runtime identity, but CSS must not depend on it.

Correct examples

@layer themePart {
    .news {
        background: var(--newsSurface);
    }
}
:root {
    --newsSurface: #272733;
}

Incorrect examples

@layer themePart {
    .themeRoot {
        .news {
            background: var(--newsSurface);
        }
    }
}
.theme28 {
    --footerSurface: #272733;
}

Fix

Remove the site or theme root selector and outdent its component rules one level so they sit directly inside @layer. Move shared custom properties to :root or the appropriate semantic root, then verify the compiled CSS and affected pages.

One Import Per File (siteTheme)

In sites and themes, import each platform-owned source file through its own generated alias and give that file one default export. A core file uses its camelCase filename as the alias, such as getThemeNumber. A part file prefixes its camelCase filename with the part name, such as contentsGetValues or globalizationGetGlobalization. Site-owned files receive generated file aliases. Inside a theme, use a theme-relative file alias without the theme number or structural parts segment, such as homeHome for theme05/parts/home/home.jsx. The importing theme takes priority over the site fallback. Keep explicit theme-prefixed aliases for imports outside the owning theme. Do not group several files behind a barrel, use named exports for ordinary platform code, create static leaf export files, or import platform modules through relative paths. Generate file aliases in core infrastructure. This rule governs JavaScript and TypeScript module imports; stylesheet imports follow the focused style import policies.

Philosophy

Large barrels can lower Lighthouse scores because importing one module through a barrel may pull unrelated modules into the bundle.

Correct examples

import getThemeNumber from 'getThemeNumber'
import contentsGetValues from 'contentsGetValues'
import globalizationGetGlobalization from 'globalizationGetGlobalization'
import HomeHome from 'homeHome'
import WideBackgroundHero from 'wideBackgroundHero'
export default props => <SiteRoot {...props} />

Incorrect examples

import { getThemeNumber } from 'core'
import { getValues } from 'contents'
import { Footer, Header } from 'layout'
import Header from '../parts/layout/header.jsx'
export const Header = props => <header>{props.title}</header>

Exceptions

  • Keep named exports when a framework requires them at a route boundary, such as Qwik City routeLoader$ hooks and head exports. Re-export a shared loader from the owning route layout or index when Qwik City requires registration.
  • Use the export form required by external libraries and framework APIs at their interoperability boundary.
  • Use direct relative imports in Node-loaded configuration and server modules when generated site aliases are unavailable before Vite starts.
  • Keep Qwik bootstrap imports relative when they connect root, router head, generated route head, or entry files before site aliases are available.

Fix

Give each ordinary platform module a default export, import it through its generated per-file alias, and remove grouped or handwritten barrels. Preserve named route exports required by Qwik City.

Part Style Isolation (siteTheme)

Use the part class as the top-level selector in CSS for that part. For example, the blog layout already has class='blog', so its CSS starts with .blog { }.

Correct examples

@layer partLayout {
    .blog {
        @apply grid;
    }
}
@layer themePart {
    .products {
        @apply rounded-lg;
    }
}

Incorrect examples

@layer partLayout {
    .layout {
        @apply grid;
    }
}

Fix

Use the existing part class as the top-level CSS selector.

Shared Style Ownership (siteTheme)

Put shared role appearance in focused stylesheets named for the role, such as styles/list.css, styles/item.css, styles/actions.css, and styles/pricing.css. Load these before focused part-specific files such as styles/videos.css or styles/products.css. Style .list and .item at the shared level; use .list.videos, .item.video, or nested .duration only for vlog-specific differences. Pricing shared by products and services belongs in one pricing.css file. Domain files may override shared declarations when needed but must not copy them. Keep visual presentations such as card or three-dimensional treatments in CSS, separate from the role and domain classes in markup.

Shared Visual Styles (siteTheme)

Style abstract UI roles before domain types. Define shared site or theme styles for lists, items, list actions, item actions, CTAs, links, titles, icons, forms, fields, dialogs, content, time, and pricing when those roles are present. Put each reusable role in a focused stylesheet and define its common colors, typography, spacing, borders, states, and responsive behavior once. Let post, video, episode, product, and service components inherit those role styles through their semantic role classes. Add domain-specific rules only for genuine differences.

Similar Ui Reuse (siteTheme)

In sites and themes, UI elements with the same role, structure, and interaction must share their component and styling rules. Render differences through data or properties so one fix improves every instance. This applies to menu items, social links, links and CTAs, read more buttons, and repeated sections such as men’s, women’s, and children’s clothing that differ only in content. Keep genuinely different behavior explicit while sharing the visual and interaction rules the elements have in common.

Correct examples

items.map(item => <MenuItem key={item.id} {...item} />)
socialLinks.map(link => <SocialLink key={link.id} {...link} />)
sections.map(section => <ClothingSection key={section.id} {...section} />)

Incorrect examples

<MenClothingSection title={menTitle} />
<WomenClothingSection title={womenTitle} />
<ChildrenClothingSection title={childrenTitle} />
.firstHeaderIcon:hover { background: var(--headerHoverSurface); }
.secondHeaderIcon:hover { background: var(--headerHoverSurface); }

Fix

Move repeated structure, interaction, and appearance into the existing shared component or one focused reusable component and shared style rule. Pass differing content and destinations as data or properties.

Style Entry (siteTheme)

The main style.css of a site process or theme may contain only @import statements. Import focused stylesheets or coarse style groups from it. Define colors, component rules, media queries, and other CSS directives in imported files or the site core, as appropriate.

Correct examples

@import './styles/theme.css';
@import './styles/items.css';

Incorrect examples

@import './styles/items.css';
.items {
    @apply grid;
}

Theme Abstraction (siteTheme)

Keep site and theme selectors abstract and reusable across parts. Style semantic roles such as list, item, title, and actions first. Use a domain class supplied by a part only when that domain needs a distinct treatment, such as .list.videos or .item.video. Keep visual presentation decisions in CSS rather than adding visual classes to JSX. Users must be able to create and reorder data-composed pages from registered parts through the admin interface without developers or AI adding page-specific code. Themes and runnable site processes must not contain routes, renderers, selectors, content, or composition keyed to an individual dynamic page, its slug, or its section keys. Do not style a reusable part through the dynamic renderer page wrapper, such as .dynamicPage [data-ui-part="callToAction"]. Resolve registered parts through shared infrastructure and give each reusable component its own theme appearance, independent of its containing page. A new page using existing parts must require only runtime content and configuration.

Correct examples

@layer themePart {
    .list {
        .item {
            .title {
                @apply font-semibold;
            }

            .actions {
                @apply flex;
            }
        }
    }
}

Incorrect examples

.videoItem {
    .videoTitle {}
    .videoActions {}
}

Fix

Move shared declarations to role selectors and keep only genuine domain differences in combined role-and-domain selectors. Remove page-specific code and page-wrapper styling from themes and runnable sites; place missing behavior in an existing reusable component and let runtime data select and compose registered parts.

Font Component Placement (siteThemes)

In sites and themes, use the shared <Font /> component only inside header.jsx. Never import or render it in any other file, including pages, layouts, or other components.

Philosophy

Keep font declarations in one predictable location within the site or theme header.

Correct examples

header.jsx: <Font name='montserrat' />

Incorrect examples

home.jsx: <Font name='montserrat' />
layout.jsx: <Font name='montserrat' />

Fix

Move every Font import and <Font /> declaration into the owning site or theme header.jsx file.

Layout Header And Footer (siteThemes)

In sites and themes, always prefer defining and rendering Header and Footer inside layouts rather than pages. Keep shared page framing in the owning layout whenever practical.

Philosophy

Layouts provide consistent page framing and avoid repeating Header and Footer composition across pages.

Fix

Move shared Header and Footer composition from pages into the owning layout, keeping page-specific content in the pages.

New Tab Link (siteThemes)

In sites and themes, including site core, runnable sites, theme repositories, and individual themes, use the shared NewTabLink component imported from newTabLink for links that open a new tab. Do not declare target="_blank" or a dynamic target in other JSX. NewTabLink owns target="_blank" and always includes noopener, preserving additional rel tokens. Add noreferrer only when hiding referral information is intended. Ordinary same-tab links may use semantic anchors.

Philosophy

Shared infrastructure owns new-tab behavior so sites and themes declare their intent once.

Correct examples

import NewTabLink from 'newTabLink'

<NewTabLink href={href}>Open page</NewTabLink>

Incorrect examples

<a href={href} target='_blank'>Open page</a>

Fix

Import NewTabLink from newTabLink and replace the new-tab link with it. Remove the target prop; forward the link attributes and children. Separate dynamic same-tab and new-tab rendering into the appropriate link components.

No Direct Child Selectors (siteThemes)

Do not use direct child selectors in site or theme CSS. Instead, provide more specific semantic classes for your JSX and HTML and target them with descendant selectors.

Philosophy

Direct child selectors tightly couple CSS to the nesting structure of JSX and HTML, so adding or removing a wrapper can break styling. Selectors should express semantic relationships through meaningful class names rather than depend on the physical nesting of elements.

Correct examples

Give the section heading a specific semantic class in JSX or HTML.

.disclosures {
    .sectionHeading {
        @apply mb-10;
    }
}

Incorrect examples

.disclosures {
    > .container > .heading {
        @apply mb-10;
    }
}

Fix

Add specific semantic classes to the affected JSX or HTML elements and replace direct child combinators with descendant selectors that target those classes.

Original Theme Verification (siteThemes)

For a requested theme queue, preserve its reported order and audit one theme at a time. Within each theme, verify browser branding and favicon first, then the header, hero, every subsequent section in page order, and finally the footer. Finish each section's applicable verification matrix before advancing; explicitly report blocked sections as unverified.

When the user instructs skipping themes that cannot be continued, resolve problems within the available access and authorized scope first. Skip only when a reference, required resource, repair connection, or other necessary dependency remains unavailable. Record the actual blocker and checks performed without marking the theme verified or complete. Solvable visual discrepancies and runtime errors remain findings to correct.

When reproducing an existing theme in a site or theme, verify every section from top to bottom and every element within it against the exact original version. Verification is a matrix: every element or section multiplied by every property below, every applicable interaction state, and every applicable responsive or contextual variant. Do not treat a matching default desktop screenshot as completion.

Reference conditions: record the original URL or source version, page, browser and version, operating system, viewport width and height, zoom, device pixel ratio, locale, content, scroll position, motion preferences, document visibility, and state. Bring each page to the foreground before exercising interactions or measuring motion, and confirm that scroll events, animation frames, and state updates have run; background-tab throttling is not evidence of the original behavior. When using operating-system pointer input, verify native window dimensions, viewport overrides, browser chrome offsets and the actual pointer coordinates before accepting a cursor comparison. Wait for foreground animation frames after pointer movement and scrolling; timer delays alone do not establish that browser hit testing or cursor rendering has updated. Compare under the same conditions with the original fonts, images, and styles fully loaded. If the reference or an asset cannot be inspected, mark that check unverified and report it; never infer an exact match.

For each element and section, check all of the following:

  1. Geometry: margin and padding on every side, width and height, minimum and maximum dimensions, aspect ratio, box sizing, borders and border radius, container and site-wide width, grid and flex layout, gaps and gutters, alignment, positioning, offsets, stacking order, overflow, clipping, and the distance to adjacent elements.

  2. Surface and color: background colors, images and gradients, foreground and text colors, opacity and transparency, overlays, border colors, shadows including offset, blur, spread, inset and opacity, and the colors of descendants and pseudo-elements.

  3. Typography: the actual loaded font family, weight and style, font size, line height, letter and word spacing, alignment, capitalization, decoration, wrapping, truncation, and text baseline. Check selected text and its selection background, foreground and contrast separately from ordinary text and from the current navigation item.

  4. Media and icons: the correct image, logo or icon, intrinsic and rendered dimensions, crop, aspect ratio, object fit and position, resolution, SVG view box, visible glyph bounds, stroke width, caps and joins, miter limits, dash patterns and offsets, fill rules, vector effects, fill, color, rotation, baseline and placement. An icon box matching in size does not prove that its visible shape matches. Preserve the required dynamic media and font infrastructure and reusable SVG components.

  5. Motion: animation and transition properties, duration, delay, easing, direction, travel distance, transforms, start and end states, opening and closing behavior, slide interval, autoplay, pause and resume behavior, and reduced-motion variants. Inspect intermediate frames and interactions during motion; endpoint screenshots alone cannot verify animation. Measure input-to-visible-state latency for first and repeated interactions, including cold or lazy-loaded handlers; matching normalized animation timelines does not verify response latency. Wait for the intended state and paused animations to become ready before comparing controlled frames, and record any normalization separately from real input timing.

  6. Interaction geometry and behavior: click and touch targets, pointer movement from parent items into submenus including pauses and diagonal movement across gaps, hover retention, opening and closing triggers, keyboard focus and activation, focus order, scrolling, sticky and fixed behavior, and overflow while overlays, menus or sliders are active.

  7. Scrollbars: vertical and horizontal visibility, width and height, track and thumb colors, shape and radius, hover and active appearance, corner appearance, scroll position, reserved gutter and resulting layout shifts. Check both page and nested scrolling regions.

  8. Browser branding: favicon and supported icon variants, the actual icon displayed in the browser tab, document title, logo identity, dimensions and aspect ratio, and light or dark variants when the original provides them. Verify resource loading, browser icon selection, and the rendered result, not just the presence of an icon link.

  9. Cursor: compare the actual computed cursor and visible pointer over every element, its descendants, pseudo-elements, and the entire interaction target, including buttons, links, carousel next and previous controls, draggable areas, and disabled controls. Check inherited cursors, custom cursor assets and hotspots, and cursor changes during hover, focus, pressing, dragging, loading, and disabled states. Verify the cursor remains correct while moving between the control background, text, and icon; do not infer it from click behavior or the HTML element type. Apply the same dynamic asset policy to custom cursor images.

  10. Accessible interaction contract: compare exposed roles, names, control relationships, focusability, focus order, and expanded, selected, checked, pressed, disabled or validation states in the browser accessibility tree. Verify state changes during opening and closing motion as well as at the endpoints. Referenced controls must exist and identify the intended content. Equivalent atomic composition may use different DOM structures and generated identifiers while preserving the original accessible behavior.

Apply the entire property checklist in each applicable state: default, hover, focus, focus-visible, focus-within, active or pressed, current navigation item, selected or checked, expanded and collapsed, open and closed, enabled and disabled, visited, loading, empty, error and validation states. Include text selection and combinations of states; checking the color of a link wrapper does not verify the visible child text.

Apply the entire property and state matrix in each variant supported by the original: mobile, tablet, desktop, XL and larger screens; immediately below, at and above every relevant breakpoint, including fractional CSS viewport widths produced by native zoom or window resizing and any gaps between inclusive and exclusive breakpoint rules; portrait and landscape; supported zoom and pixel densities; light and dark appearances; locales and text directions; short, long and missing content; mouse, keyboard and touch input; and initial, scrolled, sticky and fixed positions. Check section-specific variants and initial, intermediate and final animation states. Explicitly identify inapplicable checks instead of silently skipping them.

Verification evidence: compare screenshots, rendered bounding boxes and computed styles for the actual visible elements, their descendants and pseudo-elements. Use the original CSS and asset geometry to resolve differences, and exercise the real interactions. Verify the browser applied the intended properties after server rendering and hydration; source attribute or prop spelling alone is not evidence. Confirm rendered markup and runtime resource versions correspond to the revision under test; discard evidence from stale cached HTML or bundles. Confirm audit captures and pointer targets are not covered by development controls or other unintended overlays. Declare any unavoidable rendering tolerance before accepting it; do not dismiss a few pixels when they alter alignment, appearance or pointer access. Fix each discrepancy, repeat its affected property, state and variant checks, and verify the published page with its real runtime resources. Mark a section complete only when its applicable matrix passes; record remaining mismatches and unverified checks explicitly.

Keep a durable per-theme verification record with the reference conditions, section inventory, checks performed, evidence locations, discrepancies, fixes, and unverified or inapplicable checks. Report each theme separately. A theme state of homePageCompleted requires explicit user approval; an audit, implementation fix, successful build, or publication does not authorize that state change.

Fix

Build the element-by-property-by-state-by-variant checklist from the original, compare each cell with evidence, correct the responsible styles or shared behavior, and recheck the affected cells locally and after publication before reporting completion.

Page And Layout Component Ownership (siteThemes)

In sites and themes, each page or layout may import components only from parts/shared or from its own directory under parts. A component used by multiple pages or layouts must live in parts/shared. If a component belongs to a layout, define it in that layout’s directory under parts rather than a page directory. Keep each page and layout’s component ownership reflected in its directory and imports.

Philosophy

Component locations make ownership explicit and prevent pages and layouts from depending on each other’s private components.

Correct examples

Page components: parts/home/
Layout components: parts/layout/
Components shared by multiple pages or layouts: parts/shared/

Fix

Move each component into its owning page or layout directory under parts, or into parts/shared when used by multiple pages or layouts, and update imports to respect those ownership boundaries.

Page And Layout Orchestration (siteThemes)

In sites and themes, pages and layouts must directly import their parts and orchestrate their composition. Never create a single top-level orchestrator component inside a page’s directory under parts that imports and assembles all other page components. Apply the same ownership to layouts: keep layout orchestration in the layout itself rather than delegating it to a top-level component under parts.

Philosophy

Pages and layouts make their full composition visible while parts remain focused on individual sections or components.

Fix

Move top-level part imports and composition into the owning page or layout, update its imports, and remove the redundant orchestrator component.

Site Core Ui Ownership (siteThemes)

Site core may provide reusable domain-neutral UI components that render semantic HTML through JSX, along with shared behavior, data loading, routing, accessibility helpers, and other infrastructure. Part sites may provide reusable domain UI through the same headless JSX approach. Core and part-site components must not define or import component appearance styles; consuming sites and themes supply appearance through semantic classes. Core build infrastructure CSS remains permitted. Keep SVG shapes and site- or theme-specific visuals outside site core. Put site-specific UI in the owning site, theme-specific UI and SVGs in the owning theme, and reusable domain UI in the appropriate part site. Import and render an owned SVG component directly where it is used. If several themes need the same visual, each theme may own a copy. Do not add a site-core icon registry or select visual components by string names.

Correct examples

import VercelMark from '../parts/svg/vercelMark.jsx'

export default () => <VercelMark />
import ProductCard from 'products/site/productCard.jsx'

export default ({ product }) => <ProductCard product={product} />

Incorrect examples

import VercelMark from 'site/pageParts/svg/vercelMark.jsx'
const icons = { vercelMark: VercelMark }

export default ({ name }) => icons[name]

Fix

Keep reusable domain-neutral headless JSX in site core and reusable domain JSX in part sites. Move component appearance styles into the consuming site or theme, and keep SVG shapes and site- or theme-specific visuals in their owner.

Class Name Casing (tailwind)

Use camelCase for every platform-owned custom class name in Tailwind component styles.

Correct examples

.someClass {
    @apply block;
}

Incorrect examples

.some-class { @apply block; }

Fix

Rename kebab-case and snake-case custom classes to camelCase in styles and every matching JSX reference.

Class Name Namespace (tailwind)

Aim for single-word classes as much as possible. Separate a component role and its declared variant into class tokens on the same element: use class="hero minimal" and class="hero split", never heroMinimal or heroSplit as class names. Every variant keeps the base role so shared styles apply. Style the base with .hero and variant differences with nested &.minimal or the compound selector .hero.minimal, never the descendant selector .hero .minimal. Apply this to shared components, sites, and every theme, updating markup, selectors, and class-dependent behavior together. Keep component names, filenames, imports, and content renderer identifiers camelCase; they are not CSS class tokens. Do not mechanically split a compound word that names one cohesive semantic role. Let selector nesting express ownership instead of repeating the parent name in every child class. If sibling classes have the same prefix, that prefix may be their missing parent: move it up one level and name the children by their own roles. For example, browseDialogTitle and browseDialogContent indicate a shared browse parent with .title and .content children.

Correct examples

.footer {
    .cta {
        @apply block;
    }
}
.browse {
    .title {
        @apply font-semibold;
    }

    .content {
        @apply block;
    }
}
.hero {
    @apply block;

    &.minimal {
        @apply text-center;
    }
}

Incorrect examples

.footer {
    .footerCta { @apply block; }
}
.browseDialogTitle {
    @apply font-semibold;
}

.browseDialogContent {
    @apply block;
}

Fix

Separate component and variant class tokens on the same element, retain the base role on every variant, and update all matching selectors and class-dependent behavior across sites and themes. For descendant ownership, add the shared parent class, nest sibling selectors under it, and shorten child classes to their roles. Preserve unrelated semantic compound names and non-class identifiers.

Always Visible Vertical Scrollbar (ui)

Reserve vertical scrollbar space anywhere its appearance or disappearance would cause UI layout shift. Use overflow-y-scroll for primary page and panel scrolling regions, including every website root, or scrollbar-gutter: stable when the scrollbar itself should remain conditional.

Correct examples

.panelContent {
    @apply overflow-y-scroll;
}
html {
    overflow-y: scroll;
}
html {
    scrollbar-gutter: stable;
}

Incorrect examples

.panelContent {
    @apply overflow-y-auto;
}
html {
    overflow-y: auto;
}

Exceptions

  • Print styles may allow the full document to flow without reserving a screen scrollbar.

Fix

Reserve vertical scrollbar space with overflow-y-scroll or scrollbar-gutter: stable on the primary scrolling region.

Coarse Component Style Files (part/partSite)

Split theme CSS into files that each cover one coarse component or styling concern. Use focused files such as cards.css, card.css, post.css, blog.css, footer.css, footerCta.css, header.css, and menu.css, and import them through the theme's style entry instead of combining unrelated concerns in one file.

Correct examples

@import './styles/footer.css';
@import './styles/cards.css';
@import './styles/card.css';
@import './styles/info.css';

Incorrect examples

@import './styles/components.css';

Fix

Split the aggregate stylesheet into focused files that each cover one coarse component or concern.

File System Hierarchy (part/partSite)

Structure each part site directory with functions, loaders, getters, pages, and parts directories.

Correct examples

site/functions/useItemUrl.jsx
site/getters/getItem.jsx
site/loaders/loadItem.jsx
site/pages/items/index.jsx
site/parts/item.jsx

Incorrect examples

site/app/items/index.jsx
site/components/item.jsx

Route Shape (part/partSite)

Use /${part} as a part site home page. The final action segment in a part site URL may be a concrete slug, ID, or indexable selector. Do not add a list action merely to represent the part home page. Correct examples include /blog, /blog/featured, /blog/post/my-first-post, and /orders/invoice/123. Incorrect examples include /blog/list, /posts, /post/my-first-post, /blog/post/read/my-first-post, and /dashboard/orders.

Correct examples

/blog
/blog/featured
/blog/post/my-first-post
/orders/invoice/123

Incorrect examples

/blog/list
/posts
/post/my-first-post
/blog/post/read/my-first-post
/dashboard/orders

Theme Style Containment (part/partSite)

Keep every theme's styles self-contained. A theme must not import, inherit, or depend on styles from the runnable's style.css or styles directory. Store every style required by a theme within that theme's own style.css and styles directory.