Skip to content

chore: new config schema setup - #5357

Merged
mimarz merged 79 commits into
mainfrom
chore-new-config-schema-setup
Sep 16, 2026
Merged

mimarz merged 79 commits into
mainfrom
chore-new-config-schema-setup

Conversation

@mimarz

@mimarz mimarz commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

resolves #3807

In our current setup "defaults" and validation are handled in multiple places, split between the config schema and hard-coded values in the design-tokens generators.

As a first step this expands the schema with fields for all defaults that were defined in design-tokens (except colors, saved for a separate PR). This lays the groundwork for more configuration options for end users in JSON, JS and the theme builder.

The goal is to make it easier to:

  • Define defaults in one place.
  • Preview a user's configuration in places such as the theme builder and the Figma plugin.
  • Write transformers to other formats.
  • Support end users configuring more of Designsystemet in the future.
    • How the final end-user schema looks will be revisited, as we also want to simplify the design-tokens structure.
    • This can be done gradually, since the public/external schema picks individual fields from the full schema.
    • The idea is to only have the full schema in the future. We expose new configuration fields as we feel they are ready.

Summary

One schema, two views

  • The separate schema files (v1, v1.1 and next) are replaced by a single source in packages/cli/src/schemas/, with one part file per area.
  • configSchema is the full schema. externalConfigSchema is the public schema, derived from it with omit + pick + extend: the same top-level fields (outDir, clean, themes) and theme keys (colors, typography, borderRadius, overrides) users have today, with typography limited to the { fontFamily } shorthand and borderRadius to a number.
  • The published config.schema.json is generated from the public schema. config-next.schema.json is renamed to config-full.schema.json and generated from the full schema. The root designsystemet.config.json points its $schema at the full one.
  • A snapshot test (src/schemas/__snapshots__/config.schema.json) guards the public JSON schema against accidental changes.
  • The package's configSchema / ConfigSchema exports are unchanged and still refer to the public schema. Deep imports of schemas/v1/schema.js, schemas/v1.1/schema.js and schemas/next/schema.js no longer resolve. The Figma plugin and the theme builder import from schemas/schema.js.

Validate with the public schema, populate with the full schema

tokens create --config, the (not yet enabled) config command and the Figma plugin validate a config in two steps:

  1. externalConfigSchema validates what the user wrote. Theme fields and shapes that are not part of the public config are rejected with a user-facing error, and shorthands (typography: { fontFamily }, borderRadius: 4) are normalized.
  2. configSchema parses the config to populate every internal default (size modes, size-mode typography, components, shadows, border widths, opacities).

This keeps the public surface small while the generators always work on a fully defaulted config. Once a field is added to the public schema it flows through without further changes.

Output settings

  • outDir and clean are unchanged and remain the public output settings, with the same defaults as before and no deprecation.
  • The output array from the old next schema now lives in the full schema only. It is not exposed yet, and is only read by the config command, which stays disabled.

New config fields (full schema, not exposed)

  • typography is restructured into named font sets, per-size-mode values and shared components:
    • typography.fonts.<set>: fontFamily and fontWeight per set (defaults primary and secondary).
    • typography.size.<mode>: lineHeight, letterSpacing and fontSize per size mode, mirroring the primitives/modes/typography/size/<mode> token sets.
    • typography.components: heading and body typography tokens, shared by all sets.
    • The { fontFamily } shorthand still works and normalizes to this shape.
  • size (scale formula and steps with base, step, baseFontSize), borderWidth, shadow and opacity are new. borderRadius also accepts an object with steps, base and scale.
  • packages/cli/docs/designsystemet.config.defaults.json documents the fully defaulted config. It is regenerated by create-example-config.ts as part of build:json-schema. A draw.io diagram of the design-tokens structure is added alongside it.

Validation

  • Color names may only contain lowercase letters, digits and hyphens, matching the sanitizing done by the theme builder (Add validation logic for color names in CLI config file schema #3807). This applies to the public schema too.
  • At least one theme is required, and all themes must define the same color names. Both rules apply to the full and the public schema.
  • Values that end up in token sets shared by all themes (size, shadows, border widths, opacities, border-radius step names, typography set names, size-mode typography and components) must be identical across themes, with an issue pointing at the offending theme and field.
  • Token references in typography.components (e.g. {font-size.4}, {line-height.sm}, {font-weight.medium}) are checked against the keys defined in the theme. Font-size and font-weight references must resolve in every size mode and every font set.
  • Every step in size.steps must have a matching entry in typography.size.

Design-tokens generation

  • All hard-coded defaults in the generators (globals, size modes, typography primitives, theme font-weights, semantic style tokens) are replaced by values from the parsed config.
  • $themes.json and $metadata.json are generated from the size modes and typography sets in the config instead of fixed lists. The known Figma ids are kept for the default modes and sets; custom ones get a hashed id.
  • The CSS build no longer hardcodes primary and secondary: the first typography set becomes the :root default, primitives are filtered for any set name, and the entry-file section order follows default/non-default instead of the name.
  • createTokens takes the token set dimensions (color schemes, size modes, typography sets) derived from the first theme.
  • The --font-family CLI option is only applied when explicitly supplied, so it does not clobber a config that defines named typography sets.
  • Generated tokens and CSS for configs using the defaults are unchanged.

Figma plugin and theme builder

  • The plugin uses the same two-step validation as the CLI before generating preview tokens.
  • The theme builder uses ExternalConfigSchemaInput for the config it generates.

@mimarz
mimarz added this pull request to stack #5358 September 15, 2026 08:11
@changeset-bot

changeset-bot Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dd0a5c7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@digdir/designsystemet Patch
@digdir/designsystemet-css Patch
@digdir/designsystemet-react Patch
@digdir/designsystemet-types Patch
@digdir/designsystemet-web Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployments for this pull request:

storybook - 16. Sep 2026 - 14:55

themebuilder - 16. Sep 2026 - 14:55

www - 15. Sep 2026 - 11:22

@mimarz mimarz changed the title chore new config schema setup chore: new config schema setup Sep 15, 2026
@mimarz
mimarz requested a balanced review from Copilot September 15, 2026 08:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Public-schema rejection, size-step validation, deprecation warnings, and release compatibility need correction.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Centralizes configuration defaults and validation in a unified schema, then drives token generation from the fully populated configuration.

Changes:

  • Adds public and full schema views with validation and generated documentation.
  • Makes token dimensions, typography, sizing, shadows, borders, and opacity configuration-driven.
  • Updates CLI, Figma plugin, and theme builder integrations.
File summaries
File Description
plugins/designsystemet/src/plugin/code.ts Uses two-stage config validation and dynamic dimensions.
packages/cli/src/tokens/utils.ts Adds record-to-token and numeric-key helpers.
packages/cli/src/tokens/types.ts Adds configuration-derived token types.
packages/cli/src/tokens/process/platform.ts Determines typography defaults dynamically.
packages/cli/src/tokens/process/output/theme.ts Orders arbitrary typography CSS sections.
packages/cli/src/tokens/process/configs/typography.ts Supports configurable typography sets.
packages/cli/src/tokens/process/configs/type-scale.ts Filters arbitrary typography primitives.
packages/cli/src/tokens/process/configs/shared.ts Adds typography primitive detection.
packages/cli/src/tokens/generate-config.ts Uses the public schema input type.
packages/cli/src/tokens/format.ts Derives token dimensions per theme.
packages/cli/src/tokens/create/generators/themes/theme.ts Generates configured radius and font-weight tokens.
packages/cli/src/tokens/create/generators/semantic/style.ts Generates semantic tokens from configuration.
packages/cli/src/tokens/create/generators/primitives/typography.ts Generates configurable typography primitives.
packages/cli/src/tokens/create/generators/primitives/size.ts Generates configurable size scales.
packages/cli/src/tokens/create/generators/primitives/globals.ts Generates configurable global primitives.
packages/cli/src/tokens/create/generators/primitives/color-scheme.ts Updates schema import.
packages/cli/src/tokens/create/generators/primitives/color-scheme.test.ts Updates schema type import.
packages/cli/src/tokens/create/generators/$themes.ts Generates dynamic modes and identifiers.
packages/cli/src/tokens/create/generators/$metadata.ts Generates dynamic token-set ordering.
packages/cli/src/tokens/create.ts Builds token sets from schema values.
packages/cli/src/scripts/update-preview-tokens.ts Uses the unified schema and dimensions.
packages/cli/src/scripts/createJsonSchema.ts Generates the public JSON schema.
packages/cli/src/scripts/create-full-json-schema.ts Generates the full JSON schema.
packages/cli/src/scripts/create-example-config.ts Generates documented default configuration.
packages/cli/src/schemas/v1/schema.ts Removes the legacy v1 schema.
packages/cli/src/schemas/v1.1/schema.ts Removes the legacy v1.1 schema.
packages/cli/src/schemas/schema.ts Defines full and public configuration schemas.
packages/cli/src/schemas/schema.test.ts Tests schema validation and public contract.
packages/cli/src/schemas/schema-typography.ts Defines typography defaults and normalization.
packages/cli/src/schemas/schema-size.ts Defines size configuration defaults.
packages/cli/src/schemas/schema-shadow.ts Defines shadow defaults.
packages/cli/src/schemas/schema-overrides.ts Extracts override validation.
packages/cli/src/schemas/schema-output.ts Defines output configuration and deprecations.
packages/cli/src/schemas/schema-opacity.ts Defines opacity defaults.
packages/cli/src/schemas/schema-color.ts Adds strict color-name validation.
packages/cli/src/schemas/schema-border-width.ts Defines border-width defaults.
packages/cli/src/schemas/schema-border-radius.ts Defines radius shorthand and full form.
packages/cli/src/schemas/__snapshots__/config.schema.json Captures the public JSON schema.
packages/cli/src/index.ts Re-exports the public unified schema.
packages/cli/package.json Updates schema-generation scripts and exports.
packages/cli/docs/designsystemet.config.defaults.json Documents the fully defaulted configuration.
packages/cli/docs/design-tokens-structure.drawio Documents token architecture.
packages/cli/bin/designsystemet.ts Integrates two-stage validation and dimensions.
packages/cli/bin/config.ts Validates and populates CLI configuration.
designsystemet.config.json References the full generated schema.
biome.jsonc Excludes generated snapshots from formatting.
apps/themebuilder/app/_components/token-modal/use-token-modal.ts Uses the external configuration input type.
.changeset/ten-rabbits-relax.md Adds an empty changeset marker.
.changeset/strict-color-names.md Records stricter color-name validation.
Review details
  • Files reviewed: 47/49 changed files
  • Comments generated: 4
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .changeset/strict-color-names.md
Comment thread packages/cli/src/schemas/schema-size.ts
Comment thread packages/cli/src/schemas/schema.ts
Comment thread plugins/designsystemet/src/plugin/code.ts Outdated
@mimarz
mimarz force-pushed the chore-new-config-schema-setup branch 5 times, most recently from b69204b to 9d32e7d Compare September 15, 2026 12:33
@mimarz
mimarz marked this pull request as ready for review September 15, 2026 13:30
@mimarz
mimarz force-pushed the chore-new-config-schema-setup branch from 91e6412 to 9013921 Compare September 15, 2026 13:55
@mimarz
mimarz requested a balanced review from Copilot September 15, 2026 13:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Reserved or empty dimension names can overwrite token sets, and some invalid typography references bypass validation.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

packages/cli/src/schemas/schema-size.ts:10

  • steps currently accepts both an empty record and the reserved name global. An empty record creates no Size group and later produces size-mode/undefined.css; a global mode collides with primitives/modes/size/global in create.ts, so the mode token set is overwritten. Reject both states in the schema.
    steps: z
      .record(
        z.string(),

plugins/designsystemet/src/plugin/code.ts:64

  • This comment says the public-schema result is discarded, but externalConfig is passed directly to configSchema below. Update it to describe that the normalized/sanitized result is intentionally reused; the current wording contradicts the two-stage validation flow.
  • Files reviewed: 48/50 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread packages/cli/src/schemas/schema-typography.ts
Comment thread packages/cli/src/schemas/schema.ts Outdated
@mimarz
mimarz force-pushed the chore-new-config-schema-setup branch from d541235 to 24ab9bb Compare September 16, 2026 06:23
@mimarz
mimarz requested a balanced review from Copilot September 16, 2026 06:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

New full-schema fields permit invalid dimensions and unsafe or empty token-set identifiers that can produce invalid output or downstream build failures.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

plugins/designsystemet/src/plugin/code.ts:64

  • This comment says the public-schema result is discarded and that the full schema parses the original input, but the code correctly passes externalConfig into configSchema. Update the comment so it describes the actual normalization flow.
  • Files reviewed: 48/50 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread packages/cli/src/schemas/schema-size.ts
Comment thread packages/cli/src/schemas/schema-typography.ts
Comment thread packages/cli/src/schemas/schema-border-width.ts Outdated
Comment thread packages/cli/src/schemas/schema-opacity.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Empty typography sets pass validation, custom size-mode typing is unsound, and normalized CSS output settings break CSS-only generation.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

packages/cli/src/schemas/schema-typography.ts:109

  • The full schema accepts typography.fonts: {}, but every downstream generation path requires a first typography set (createTokens throws at tokens/create.ts:34-35). This makes a configuration pass schema validation and then fail during token generation. Require at least one entry here, as is already done for size.steps.
    packages/cli/src/tokens/create.ts:19
  • Custom size-mode names are now valid, but this assertion hides that SizeModes is still the closed 'small' | 'medium' | 'large' union in tokens/types.ts:42. For a valid compact mode, the exported TokenSetDimensions value contains data its type says is impossible. Broaden or derive SizeModes from the new record-based schema instead of asserting here.
  • Files reviewed: 48/50 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@mimarz

mimarz commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

waiting after release before merging this.

mimarz and others added 25 commits September 16, 2026 14:52
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Michael Marszalek <mimarz@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Michael Marszalek <mimarz@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Michael Marszalek <mimarz@gmail.com>
@mimarz
mimarz force-pushed the chore-new-config-schema-setup branch from 30338f4 to dd0a5c7 Compare September 16, 2026 12:52
@mimarz
mimarz merged commit 61f1945 into main Sep 16, 2026
22 checks passed
@mimarz
mimarz deleted the chore-new-config-schema-setup branch September 16, 2026 13:02
@github-actions github-actions Bot mentioned this pull request Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add validation logic for color names in CLI config file schema

4 participants