Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nuejs/nue/llms.txt

Use this file to discover all available pages before exploring further.

Nue’s approach to visual design is built on a straightforward principle: CSS is the design language of the web, and it works best when it has full access to the entire document. Rather than scattering styles into component files, JS-in-CSS objects, or utility class strings embedded in markup, Nue keeps all design decisions in global stylesheets. Your HTML stays semantic, your JavaScript stays focused on behavior, and your CSS has the complete picture it needs to apply consistent, cascade-aware design across the whole site.

The three layers

Every Nue project has a clean three-layer architecture:

Structure

HTML — semantic markup from Nuemark content and layout modules. No presentational class names, no inline styles.

Logic

JavaScript — pure modules for business logic, data fetching, and state. No style manipulation, no className toggling.

Design

CSS — global stylesheets with design tokens, cascade rules, and responsive layouts. No component scoping.
This separation is enforced structurally, not just by convention. Nuemark content outputs clean semantic HTML with no class attributes. Layout modules use semantic element names. CSS selects by element type and semantic role, not by generated class hashes.

The @shared/design/ directory

All global design files live in @shared/design/. Nue auto-includes everything in this directory on every page, in alphabetical order within the asset priority system.
@shared/design/
  tokens.css custom properties, design tokens
  reset.css base element resets
  typography.css type scale, font families, line heights
  layout.css grid, spacing, page structure
  components.css shared element styles (buttons, forms, cards)
  themes/
    light.css
    dark.css
A well-structured design system in Nue reads from abstract tokens at the top, through semantic roles, down to specific element rules:
/* tokens.css — abstract design decisions */
:root {
  /* Color primitives */
  --blue-500: #3b82f6;
  --blue-600: #2563eb;
  --gray-50:  #f9fafb;
  --gray-900: #111827;

  /* Semantic roles */
  --color-primary:    var(--blue-500);
  --color-primary-hv: var(--blue-600);
  --color-surface:    var(--gray-50);
  --color-text:       var(--gray-900);

  /* Spacing scale */
  --space-xs:  0.25rem;
  --space-sm:  0.5rem;
  --space-md:  1rem;
  --space-lg:  2rem;
  --space-xl:  4rem;

  /* Type scale */
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.25rem;
  --text-2xl:  1.5rem;
  --text-4xl:  2.25rem;
}

Why global CSS over scoped styles

Component-scoped CSS, whether from CSS Modules, styled-components, or Vue’s <style scoped>, solves one problem — style isolation — at the cost of several larger ones.
The CSS cascade is not a bug to be worked around. It is how browsers apply consistent styles across related elements. When every component owns its styles in isolation, you lose the ability to set h2 styles in one place and have them apply everywhere. You end up overriding the same properties in dozens of component files.
A color, font, or spacing value that should be defined once ends up hardcoded — or re-imported from a shared file — in each component that uses it. Global CSS custom properties defined once in tokens.css are available to every selector in the entire stylesheet without any import.
When a designer wants to understand the visual language of a site built with scoped styles, they must read dozens or hundreds of component files. A global design system in @shared/design/ is a single, readable source of truth.
CSS-in-JS and utility-first approaches embed design decisions in the markup. A className="text-sm font-medium text-gray-700 hover:text-gray-900" string in JSX is a style description masquerading as a class attribute. Changing the design requires changing the markup.
In Nue, the HTML output of a Nuemark page looks like this:
<article>
  <h1>Why semantic HTML matters</h1>
  <p class="lead">Modern frameworks encourage building UIs from generic containers...</p>
  <h2>The problem with div soup</h2>
  <p>...</p>
</article>
There are no utility class strings. There are no scoped class hashes. CSS selects the elements by their semantic role:
/* @shared/design/typography.css */
article h1 {
  font-size: var(--text-4xl);
  font-family: var(--font-heading);
  line-height: 1.1;
  margin-bottom: var(--space-sm);
}

article p.lead {
  font-size: var(--text-lg);
  color: var(--color-muted);
  max-width: 55ch;
}

article h2 {
  font-size: var(--text-2xl);
  margin-top: var(--space-xl);
}

Design tokens and CSS custom properties

CSS custom properties are Nue’s primary mechanism for design tokens. They provide the flexibility of variables with the full power of the cascade — a child element can override a token for its subtree without affecting the rest of the page.
/* Default theme tokens */
:root {
  --color-surface: #ffffff;
  --color-text: #111827;
  --color-border: #e5e7eb;
}

/* Dark mode override via media query */
@media (prefers-color-scheme: dark) {
  :root {
    --color-surface: #0f172a;
    --color-text: #f1f5f9;
    --color-border: #1e293b;
  }
}

/* Contextual override — inverted hero section */
.hero {
  --color-surface: var(--color-primary);
  --color-text: #ffffff;

  background: var(--color-surface);
  color: var(--color-text);
}
The --color-text custom property defined in .hero cascades to all children of that element. Any component inside a hero that uses color: var(--color-text) automatically gets white text, without any conditional logic in the component itself.

Theming with custom properties

To support multiple themes — brand variations, customer whitelabels, or seasonal changes — define a base set of tokens and override them per theme:
/* @shared/design/tokens.css — base tokens */
:root {
  --color-primary: #3b82f6;
  --font-heading: 'Inter', system-ui;
  --radius-base: 0.375rem;
}

/* themes/enterprise.css — enterprise theme override */
:root {
  --color-primary: #1e3a5f;
  --font-heading: 'Georgia', serif;
  --radius-base: 0;
}
Switching themes requires only swapping which theme file is included — no component changes, no markup changes, no build-time conditionals.
Keep primitive values (hex colors, pixel sizes) in one layer and semantic role names (primary, muted, surface) in another. Components and typography rules reference only the semantic names. This way you can change an entire color palette by editing a single block of primitives.

App-level style scoping

Even without component-scoped styles, you can scope styles to a specific app or section of your site by adding styles to the app directory:
dashboard/
  index.html
  dashboard.css scoped to dashboard app
  @shared/design/
    tokens.css global, always included
/* dashboard/dashboard.css — styles for this app only */
.sidebar {
  width: 240px;
  background: var(--color-surface-raised);
}

.metric-card {
  padding: var(--space-lg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
}
Because dashboard.css is in the dashboard/ directory (not in @shared/), Nue’s dependency resolver includes it only in pages that belong to that app.

Design-first development

Nue’s architecture supports a workflow where design is built before components. You can create a complete, responsive design system in CSS — with tokens, type scale, layout rules, and component styles — and then write HTML content that picks up that design automatically.
1

Define tokens

Write tokens.css with all design decisions as custom properties. Colors, spacing, type scale, radii, shadows.
2

Build the type system

Write typography.css using only the semantic tokens. Define styles for h1h6, p, a, blockquote, code, ul, ol, table.
3

Define layout rules

Write layout.css for page structure — header, main content width, sidebar, footer, responsive breakpoints.
4

Add content

Write Nuemark content. It outputs clean semantic HTML that your design system styles automatically. Adjust the design system as needed; never add presentational markup to the content.
This order is intentional. When design leads, content slots naturally into a visual system rather than being styled piece by piece. Changes to the design system propagate everywhere at once, through the cascade, without touching content files or component templates.

Build docs developers (and LLMs) love