Peridio & Avocado OS: semantic tokens and AI-native design systems

Semantic design tokens for Peridio and Avocado OS: surfaces, complementary intent colors, and JSON-first specs that let AI and Figma stay aligned.

design tokensdesign systemsPeridioAvocado OSAI workflowsFigmasemantic color

Design tokens are the contract between brand, product, and code. At Peridio and Avocado OS, that contract had to stretch across customer-facing product surfaces, developer tooling, internal operations software, and narrative marketing—without fragmenting into five different “almost the same” palettes. This post is how I think about that problem now: a semantic, JSON-first token system with explicit surfaces, complementary accents, and intent roles (informational, warning, success, critical), wired into Figma and AI-assisted code workflows so the whole company can ship on-brand.

The core idea is simple to state: primitives hold raw values; semantics describe purpose; contexts choose which semantics apply. AI tools and MCP-style integrations only work reliably when those layers are explicit—otherwise models hallucinate hex codes and spacing, and every team reinvents the same decisions.

For how tokens stay synchronized with engineering branches and releases, see branching strategies for design-engineering collaboration. For the marketing-and-code side of AI-assisted delivery, ship landing pages with Claude Code and GitHub covers the same operational rhythm at a different altitude.

Multi-surface reality: one company, many “products”

A platform company rarely ships one UI. You get:

  • External products — what customers buy and recognize on a pricing page.
  • Internal products — dashboards and consoles your team lives in daily.
  • Internal solutions — glue software: workflows, approvals, lightweight tools that will never have a marketing site but still need clarity.
  • Internal software — longer-lived internal apps that behave like product: permissions, audit trails, SLAs.

Each surface has different risk and density. Customer UIs need polish and accessibility at scale. Internal tools need scannability, error recovery, and speed. Semantic tokens let you reuse one component library while shifting emphasis—density, contrast, and accent usage—without forking components.

Avocado OS carries the story of a production-grade OS: trust, stability, and technical depth. Peridio carries fleet operations, security, and control. The visual system should let both narratives coexist: shared infrastructure tokens, distinct brand ramps where the story diverges.

Semantic surfaces: where color does its job

Surface tokens answer “what is behind this UI?”—not “what blue is this?”

A workable baseline set:

  • Canvas — the default page background; lowest elevation.
  • Raised — cards, panels, popovers; one step above canvas.
  • Inset — wells, inputs, dense tables; visually pushed back.
  • Overlay — scrims and modal shells; may carry blur or alpha.
  • Brand — hero bands, marketing strips; may use larger chroma.

Components never consume #2B6CFF directly. They consume roles like surface.canvas.default, surface.raised.default, surface.inset.muted. Dark themes remap those roles without touching component code.

Complementary color: brand primary without muddy neutrals

Enterprise palettes often die in the grays: everything looks like a spreadsheet. Complementary accents sit next to your brand primary—used for highlights, secondary CTAs, data viz series, and “related but not primary” actions.

In token terms, split brand from accent complementary:

  • Brand primary — main actions, key links, focus rings tied to identity.
  • Accent complementary — charts, tags, secondary emphasis, illustration strokes.

Both reference primitive ramps (brand.500, complement.400) but semantic aliases (action.primary, data.series.secondary) keep components honest. Marketing can push chroma in hero sections; product UI stays restrained—same token architecture, different context overrides.

Intent: informational, warning, success, and critical

Intent tokens encode meaning: “this message is for awareness” vs “this could break production.” Map them consistently across toast, banner, inline field validation, and system badges.

Define semantics for:

  • Informational — neutral or cool bias; never implies failure.
  • Warning — attention without panic; reversible states, deprecations.
  • Success — completion, healthy status, positive diff.
  • Critical — destructive actions, blocking errors, security issues.

Each intent gets a full mini-palette: background, foreground, border, and optional icon. That avoids the classic bug where warning text passes contrast on white but fails on tinted warning backgrounds.

Pair intent tokens with elevation so dense internal apps stay readable: intent.warning.surface on surface.raised.default should meet WCAG for both default and high-contrast modes.

JSON-first tokens: scalable, fluid, and machine-readable

The format below is not a dump of every hex value. It is a shape you can extend: add brands, locales, density modes, or new product lines without renaming the world. Tools (Style Dictionary, Tokens Studio exports, custom scripts) can flatten this for CSS, iOS, Android, or Tailwind.

Dimensions worth encoding:

  1. Meta — schema version, default theme, supported audiences.
  2. Theme — light/dark/high-contrast; each maps semantic roles to primitives.
  3. Brand — Peridio vs Avocado OS ramps; optional co-brand for partner collateral.
  4. Audienceexternal, internal, mixed (e.g. docs read by customers and staff).
  5. Product line — which app shell loads which subset (console vs marketing site).
  6. Motion & fluid — optional clamp() references for type and spacing scales.
{
  "$schema": "https://example.com/design-tokens/peridio-avocado/2026-03-20",
  "meta": {
    "name": "peridio-avocado-os",
    "version": "1.0.0",
    "defaultTheme": "light",
    "defaultAudience": "external",
    "modes": ["light", "dark", "hc-light"]
  },
  "primitive": {
    "color": {
      "neutral": { "0": "#FFFFFF", "950": "#0B1220" },
      "brand": { "400": "#3B82F6", "500": "#2563EB", "600": "#1D4ED8" },
      "complement": { "400": "#F59E0B", "500": "#D97706" },
      "intent": {
        "info": { "500": "#0EA5E9", "surface": "#E0F2FE" },
        "warning": { "500": "#F97316", "surface": "#FFEDD5" },
        "success": { "500": "#22C55E", "surface": "#DCFCE7" },
        "critical": { "500": "#DC2626", "surface": "#FEE2E2" }
      }
    },
    "space": {
      "static": { "1": "4px", "2": "8px", "3": "12px", "4": "16px", "6": "24px" },
      "fluid": {
        "section-y": "clamp(2rem, 5vw, 5rem)",
        "gutter-x": "clamp(1rem, 3vw, 2rem)"
      }
    },
    "radius": { "sm": "6px", "md": "10px", "lg": "16px", "pill": "999px" },
    "type": {
      "family": { "sans": "Inter, system-ui, sans-serif", "mono": "JetBrains Mono, monospace" },
      "size": { "fluid-body": "clamp(0.95rem, 0.35vw + 0.9rem, 1.05rem)" }
    }
  },
  "semantic": {
    "surface": {
      "canvas": { "default": "{primitive.color.neutral.0}", "muted": "{primitive.color.neutral.50}" },
      "raised": { "default": "{primitive.color.neutral.0}", "muted": "{primitive.color.neutral.0}" },
      "inset": { "default": "{primitive.color.neutral.100}", "muted": "{primitive.color.neutral.50}" },
      "overlay": { "scrim": "rgba(11,18,32,0.55)" }
    },
    "text": {
      "primary": "{primitive.color.neutral.950}",
      "secondary": "{primitive.color.neutral.600}",
      "inverse": "{primitive.color.neutral.0}",
      "link": "{primitive.color.brand.600}",
      "link-hover": "{primitive.color.brand.500}"
    },
    "border": { "default": "{primitive.color.neutral.200}", "strong": "{primitive.color.neutral.300}" },
    "focus": { "ring": "{primitive.color.brand.500}", "offset": "2px" },
    "intent": {
      "info": {
        "fg": "{primitive.color.intent.info.500}",
        "bg": "{primitive.color.intent.info.surface}",
        "border": "{primitive.color.intent.info.500}"
      },
      "warning": {
        "fg": "{primitive.color.intent.warning.500}",
        "bg": "{primitive.color.intent.warning.surface}",
        "border": "{primitive.color.intent.warning.500}"
      },
      "success": {
        "fg": "{primitive.color.intent.success.500}",
        "bg": "{primitive.color.intent.success.surface}",
        "border": "{primitive.color.intent.success.500}"
      },
      "critical": {
        "fg": "{primitive.color.intent.critical.500}",
        "bg": "{primitive.color.intent.critical.surface}",
        "border": "{primitive.color.intent.critical.500}"
      }
    },
    "accent": {
      "brand": "{primitive.color.brand.500}",
      "complement": "{primitive.color.complement.500}"
    }
  },
  "context": {
    "brand.peridio": {
      "semantic.accent.brand": "{primitive.color.brand.500}",
      "semantic.text.link": "{primitive.color.brand.600}"
    },
    "brand.avocado": {
      "semantic.accent.brand": "{primitive.color.brand.500}",
      "semantic.surface.canvas.muted": "{primitive.color.neutral.50}"
    },
    "audience.external": {},
    "audience.internal": {
      "semantic.surface.canvas.default": "{primitive.color.neutral.50}",
      "semantic.text.secondary": "{primitive.color.neutral.700}"
    },
    "product.console": {
      "semantic.surface.raised.default": "{primitive.color.neutral.0}",
      "primitive.radius.md": "8px"
    },
    "product.marketing": {
      "primitive.space.fluid.section-y": "clamp(3rem, 8vw, 7rem)"
    }
  }
}

This structure scales because new contexts are additive. When internal operations needs a denser table mode, you add density.compact overrides—not new components.

Fleet consoles and OS narratives: what the tokens optimize for

Firmware and edge platforms introduce UI patterns that generic SaaS kits ignore: long technical strings (versions, hashes, device IDs), multi-step deployment timelines, region or fleet segmentation, and destructive actions that can brick hardware or strand devices in the field.

Token design should anticipate those patterns:

  • Monospace semanticstext.code or text.data reference a mono stack and slightly tighter line-height; they pair with surface.inset so dense tables remain legible without turning the whole app into a terminal.
  • Status chroma — device health maps to intent semantics: provisioning might use informational blue, degraded performance warning orange, offline neutral gray—not arbitrary badge colors picked per screen.
  • Destructive emphasis — critical intent wraps confirm dialogs and irreversible fleet actions; the same tokens appear in marketing copy when you explain risk, so language and UI stay aligned.

Avocado OS needs to feel like infrastructure you can trust: stable neutrals, restrained motion, crisp type. Peridio needs to feel like control at scale: hierarchy that surfaces what changed, what failed, and what needs a human—without shouting. Shared surfaces and intent tokens let both stories use one library; brand context swaps accent emphasis and photography treatment where the narrative diverges.

Figma MCP, variables, and why the graph matters

Figma is still the fastest place to validate hierarchy, spacing rhythm, and brand feel—but variables must mirror the same semantic graph as JSON. When an MCP or plugin can read named collections (theme / brand / audience), the model does not guess: it binds to semantic.surface.canvas.default the same way Style Dictionary does.

Practical alignment checklist:

  • One variable per semantic role in Figma; primitives live in a separate collection.
  • Modes for light/dark; optional brand mode for Peridio vs Avocado OS art direction.
  • Component props reference variables, not raw styles—same discipline as code.

Claude Code and repo-native workflows

Once JSON lives in the repo, Claude Code (and similar agents) can refactor themes, propose contrast fixes, or generate Tailwind/CSS layers from the same source. The win is not “AI picks colors”—it is AI edits the contract under review, in git, with diffs your team can audit.

I treat AI-assisted design workflows as the umbrella: prompts and guardrails matter, but structured inputs matter more. A flat list of hex codes is unstructured; layered JSON with semantic names is structured—models behave better, and humans do too.

Tokens in CI: snapshots and contrast as regression tests

When tokens live in git, they can be tested like code. That is the difference between a design system that slides backward quietly and one that stays honest.

Useful checks:

  • Contrast pairs — script that fails CI if text.primary on surface.canvas.default (and each intent surface) drops below your chosen WCAG threshold for body and UI copy.
  • Resolved snapshots — generate a flat JSON or CSS artifact in CI and diff it against the previous release; unexpected renames or missing aliases show up as build failures, not mystery bugs in production.
  • Component visual baselines — Storybook or Loki against a small matrix: light/dark × one external page × one internal console frame. You are not screenshot-testing every pixel of marketing; you are guarding token wiring.

The point is not to slow down design iteration. The point is to make token edits reviewable: a PR that changes a semantic alias should show up as a small, explainable diff—in Figma, in JSON, and in the snapshot output.

How do you keep internal tools from drifting off-brand?

Internal software moves fast and often skips design review. The antidote is defaults, not policing: if the shared component library pulls from the same semantic map, “fast” still looks like the company. Reserve exceptions for real security or density needs—document them as context overrides, not one-off hacks.

Governance I use in practice:

  • Token changes go through the same visibility as API changes: changelog, migration notes.
  • Visual QA samples: one external page, one console screen, one internal form—same release.
  • Deprecation: alias old names for a full minor cycle before removal.

Key Takeaways

  • Surfaces and intent should be first-class semantic roles—not ad hoc fills—so themes and brands remap without refactors.
  • Complementary accents sit beside brand primaries for charts, tags, and secondary emphasis without polluting neutrals.
  • JSON that encodes theme, brand, audience, and product line scales to external product, internal product, internal solution, and internal software through context overrides, not forked libraries.
  • Figma variables and repo-native tokens stay aligned when they share one semantic graph; MCP-style tooling then reads stable names instead of guessing.
  • AI-assisted coding pays off when agents edit structured token files under review—diffable, testable, and reusable across the org.

Deeper product context lives in the Peridio case study and Avocado OS case study—this article is the system layer underneath both stories.