Skip to main content

CSS Token Architecture

This document describes how NL Design System tokens are mapped to Nextcloud styling in the nldesign app.

Three-Layer Architecture

NL Design System repos          nldesign app                 Nextcloud
(upstream source of truth) (translation layer) (target)

ams.color.interactive.default --nldesign-color-primary --color-primary
utrecht.color.blue.35 --nldesign-color-link --color-primary-text
rhc.color.lintblauw.500 --nldesign-color-header-* #header { background }
... ... ...
  1. NL Design System repos define tokens using their own namespaces (ams.*, utrecht.*, rhc.*)
  2. nldesign token files (css/tokens/*.css) translate those into a unified --nldesign-* namespace
  3. theme.css maps --nldesign-* tokens to Nextcloud's CSS variables and element styling

Token Reference

Core Tokens (required for every token set)

TokenPurposeExample
--nldesign-color-primaryInteractive/accent color (buttons, links, accents)#004699
--nldesign-color-primary-textText on primary color#ffffff
--nldesign-color-primary-hoverPrimary hover state#003677
--nldesign-color-primary-lightLight tint of primary#e8f0f8
--nldesign-color-primary-light-hoverHover on light primary#d4e4f2

Header Tokens

TokenPurposeExample
--nldesign-color-header-backgroundNextcloud header bar background#154273
--nldesign-color-header-textText/icon color in header#ffffff
--nldesign-header-icon-filterCSS filter for header SVG iconsbrightness(0) invert(1)

The default icon filter is brightness(0) invert(1) (white icons). Override to none for light-colored headers where dark icons are needed (e.g., Amsterdam's white header).

Logo and Lint/Ribbon Tokens

The lint (ribbon) system follows the Rijkshuisstijl concept of rhc.logo.image.* tokens. A colored bar appears behind the logo only when these tokens are defined.

TokenPurposeDefault (fallback)Example (Rijkshuisstijl)
--nldesign-logo-urlLogo image pathnone (no logo)url('../../img/nederland-logo.svg')
--nldesign-color-logo-backgroundLint/ribbon background colortransparent (no ribbon)#154273
--nldesign-color-logo-textText color on ribbon(unused)#ffffff
--nldesign-size-lintRibbon width in header0px (no ribbon)48px
--nldesign-size-lint-heightRibbon/bar height on login page0px (no bar)96px
--nldesign-logo-filterCSS filter applied to logo imagenone (natural colors)brightness(0) invert(1)

Conditional behavior:

  • Lint tokens defined (currently only Rijkshuisstijl): Colored ribbon behind logo, logo displayed in white (inverted), login page shows colored bar
  • Only --nldesign-logo-url defined: Logo displayed in natural/original colors, no ribbon, login page shows logo on white background
  • Neither defined: No logo shown, Nextcloud's default logo behavior

Text Tokens

TokenPurposeExample
--nldesign-color-textDefault body text#202020
--nldesign-color-text-mutedSecondary/muted text#767676
--nldesign-color-text-lightText on dark backgrounds#ffffff

Status/Feedback Tokens

TokenPurpose
--nldesign-color-errorError states
--nldesign-color-error-rgbRGB values for rgba() usage
--nldesign-color-error-hoverError hover state
--nldesign-color-warningWarning states
--nldesign-color-warning-rgbRGB values
--nldesign-color-successSuccess states
--nldesign-color-success-rgbRGB values
--nldesign-color-infoInfo states
--nldesign-color-info-rgbRGB values
TokenPurpose
--nldesign-color-linkLink text color
--nldesign-color-link-hoverLink hover color
--nldesign-color-link-visitedVisited link color

Button Tokens

TokenPurpose
--nldesign-color-button-primary-backgroundPrimary button background
--nldesign-color-button-primary-textPrimary button text
--nldesign-color-button-primary-borderPrimary button border
--nldesign-color-button-primary-hoverPrimary button hover

Other Tokens

TokenPurpose
--nldesign-color-background-hoverHover background for elements
--nldesign-color-background-darkDark variant background
--nldesign-color-background-darkerDarker variant background
--nldesign-color-borderStandard border color
--nldesign-color-border-darkDark border color
--nldesign-color-focusFocus ring color (rgba)
--nldesign-color-focus-rgbFocus color RGB values
--nldesign-color-nav-backgroundNavigation panel background
--nldesign-font-familyFont stack
--nldesign-border-radiusBase border radius
--nldesign-border-radius-smallSmall border radius
--nldesign-border-radius-largeLarge border radius
--nldesign-border-radius-roundedRounded border radius
--nldesign-border-radius-pillPill/full border radius

Brand Color vs Interactive Color

Many Dutch municipalities have different colors for their brand identity and their interactive elements:

MunicipalityBrand/IdentityInteractive/PrimaryNote
AmsterdamRed (#ec0000)Blue (#004699)Red is only for the logo emblem and error feedback
UtrechtRed (#cc0000)Blue (#24578F)Red is the header/brand banner, blue is for buttons/links
Den HaagGreen (#1a7a3e)Green (#1a7a3e)Same color for both
RotterdamGreen (#00811f)Green (#00811f)Same color for both
RijkshuisstijlLintblauw (#154273)Lintblauw (#154273)Donkerblauw (#01689b) used for links

--nldesign-color-primary always maps to the interactive color, not the brand color. This is because Nextcloud's --color-primary drives buttons, links, and accent styling throughout the interface.

The brand/identity color may appear in:

  • --nldesign-color-header-background (e.g., Utrecht's red header)
  • --nldesign-color-logo-background (lint/ribbon behind logo)
  • Municipality-specific palette variables (e.g., --amsterdam-color-red)

Official Sources

Each token file maps values from the upstream NL Design System repositories:

Token fileSource repositoryToken prefix
rijkshuisstijl.cssnl-design-system/rijkshuisstijl-communityrhc.*
amsterdam.cssAmsterdam/design-systemams.*
utrecht.cssnl-design-system/utrechtutrecht.*
denhaag.cssnl-design-system/denhaagdenhaag.*
rotterdam.cssnl-design-system/rotterdamrods.*
Othersnl-design-system/themesVarious

Adding a New Token Set

  1. Create the CSS file at css/tokens/{id}.css with all required --nldesign-* variables
  2. Add metadata to token-sets.json:
    {
    "id": "myorg",
    "name": "My Organization",
    "description": "Design tokens for My Organization"
    }
  3. Optional: Add a logo at img/logos/{id}.svg and set --nldesign-logo-url in the CSS file
  4. Optional: Add theming metadata to token-sets.json for Nextcloud theming sync:
    {
    "id": "myorg",
    "name": "My Organization",
    "description": "...",
    "theming": {
    "primary_color": "#hexcolor",
    "background_color": "#FFFFFF",
    "logo": "img/logos/myorg.svg"
    }
    }
  5. Optional: Add lint tokens if the organization uses a ribbon/banner behind their logo (following the Rijkshuisstijl pattern)

The admin dropdown picks up new token sets automatically from the filesystem. No PHP changes are needed.

Mapping Guidelines

When translating tokens from an upstream NL Design System repo:

  • --nldesign-color-primary = the interactive color (buttons, accents), NOT the brand/logo color
  • --nldesign-color-header-background = the background of the Nextcloud top navigation bar
  • --nldesign-color-link = may differ from primary (e.g., Rijkshuisstijl uses donkerblauw for links)
  • --nldesign-color-error = map from *.color.feedback.error or equivalent
  • Always check the municipality's actual website to verify how colors are used in practice
  • Reference the upstream repo's component tokens to understand which palette color maps to which purpose