# How to Enforce Design System Consistency in SwiftUI Apps: The Palmier-Pro Token Architecture

> Enforce design system consistency in SwiftUI apps with our AppTheme enum. Centralize visual tokens like colors and typography to automatically propagate design changes and eliminate magic numbers.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: architecture
- Published: 2026-06-24

---

**Enforce design system consistency in SwiftUI apps by centralizing every visual token—colors, spacing, typography, and effects—in a single `AppTheme` enum that eliminates magic numbers and guarantees automatic propagation of design changes across your entire codebase.**

Maintaining visual consistency across a growing SwiftUI codebase requires architectural guardrails to prevent hard-coded values from fragmenting your interface. The Palmier-Pro macOS application solves this challenge by treating its `AppTheme` structure as the sole authority for all styling decisions. By routing every visual property through this centralized enum located in [`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift), the codebase enforces design system consistency at compile time while making global redesigns trivial.

## Centralize Tokens in a Single Source of Truth

The foundation of Palmier-Pro's design system is the `AppTheme` enum, which serves as the **single definition point** for every visual property. This structure contains nested enums organized by purpose—`Spacing`, `FontSize`, `Background`, `Border`, `Opacity`, `Radius`, `Shadow`, and `Anim`—each containing strictly typed constants.

For example, `AppTheme.Spacing.smMd` is defined as `8` points at line 2001, while `AppTheme.FontSize.smMd` equals `12` points at line 2014. By prohibiting literal values like `12` or `0.5` anywhere outside this file, the architecture guarantees that changing a token in `AppTheme` automatically propagates to every component consuming it. This eliminates the drift that occurs when developers copy-paste values between views.

## Enforce Usage Through Typed Grouping

Palmier-Pro organizes tokens by **semantic purpose** to improve discoverability and prevent accidental cross-use. The `Spacing` enum contains only layout constants, while `FontSize` manages typography scales, and `Background` defines surface colors. This typed grouping ensures that `AppTheme.Spacing.lgXl` cannot be mistaken for a color value, catching conceptual errors at compile time.

Real-world enforcement is visible in [`Sources/PalmierPro/UI/SidebarRowButton.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/SidebarRowButton.swift), where the button's horizontal padding, font size, and corner radius all reference `AppTheme` constants. This pattern forces developers to use `AppTheme.Spacing.smMd` rather than guessing values, ensuring that sidebar components remain visually aligned with the rest of the application.

## Streamline Implementation with SwiftUI Extensions

To reduce friction for developers, Palmier-Pro extends SwiftUI's `View` protocol with convenience modifiers that apply theme values automatically. Located at lines 28-33 of [`AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.swift), these extensions include methods like `shadow(_:)` and `panelHeaderBar()` that internally resolve the correct token values.

This abstraction allows developers to write `myView.shadow(AppTheme.Shadow.md)` without memorizing specific color codes or opacity levels. The `panelHeaderBar()` modifier bundles background color, border treatment, and height constraints from the theme into a single call, ensuring that every panel header in [`Sources/PalmierPro/UI/GeneratingOverlay.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/GeneratingOverlay.swift) and similar views shares identical visual properties.

## Bridge Cross-Platform Visual Tokens

For macOS applications mixing SwiftUI with AppKit, Palmier-Pro exposes each token as both `NSColor` and SwiftUI `Color` types. Each color token in `AppTheme` provides computed properties that return the appropriate type for the current framework, enabling the same spacing and color definitions to power both legacy AppKit views and modern SwiftUI components.

This bridging ensures consistency across the entire application surface. When a token updates in [`AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.swift), both the AppKit sidebar and the SwiftUI toolbar in [`Sources/PalmierPro/Toolbar/ToolbarView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Toolbar/ToolbarView.swift) update simultaneously, maintaining visual coherence without manual synchronization.

## Eliminate Magic Numbers with Enforcement Rules

Adopting the Palmier-Pro pattern requires strict governance to prevent regression. The team enforces these through four concrete practices:

1. **Define tokens exclusively in `AppTheme`** – Never declare numeric literals in view files like [`Sources/PalmierPro/Timeline/TimelineView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Timeline/TimelineView.swift).
2. **Reference via the enum namespace** – Always use [`AppTheme.Spacing.md`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.Spacing.md) instead of local constants.
3. **Prefer theme modifiers** – Use `.panelHeaderBar()` over manual background and border configuration.
4. **Lint for violations** – Run greps for numeric literals (`\b\d+(\.\d+)?\b`) across Swift files to catch stray values during code review.

This governance model ensures that the compiler and CI pipeline enforce design consistency. When a developer attempts to hard-code `padding(.horizontal, 12)`, the lint check flags the violation, redirecting them toward `AppTheme.Spacing.sm`.

## Code Examples: Themed versus Hard-Coded

The following examples demonstrate the transformation from fragile magic numbers to robust theme-based styling:

### Consistent Button Implementation

```swift
struct MyPrimaryButton: View {
    let title: String
    var action: () -> Void
    
    var body: some View {
        Button(action: action) {
            Text(title)
                .font(.system(size: AppTheme.FontSize.md,
                             weight: AppTheme.FontWeight.semibold))
                .foregroundStyle(AppTheme.Text.primaryColor)
                .padding(.vertical, AppTheme.Spacing.sm)
                .padding(.horizontal, AppTheme.Spacing.lgXl)
        }
        .background(AppTheme.Background.raisedColor)
        .cornerRadius(AppTheme.Radius.md)
        .shadow(AppTheme.Shadow.sm)
    }
}

```

### Panel Header Using Theme Extensions

```swift
struct SettingsHeader: View {
    var title: String
    
    var body: some View {
        Text(title)
            .font(.system(size: AppTheme.FontSize.title1,
                         weight: AppTheme.FontWeight.bold))
            .foregroundStyle(AppTheme.Text.secondaryColor)
            .panelHeaderBar()
    }
}

```

### Anti-Pattern: Hard-Coded Values

```swift
// Avoid this approach
Text("Inconsistent")
    .font(.system(size: 13))
    .padding(.horizontal, 12)
    .foregroundColor(Color.white.opacity(0.8))

```

### Refactored with Design Tokens

```swift
// Correct approach
Text("Consistent")
    .font(.system(size: AppTheme.FontSize.sm,
                 weight: AppTheme.FontWeight.regular))
    .padding(.horizontal, AppTheme.Spacing.sm)
    .foregroundStyle(AppTheme.Text.secondaryColor.opacity(AppTheme.Opacity.soft))

```

## Summary

- **Centralize all visual tokens** in a single `AppTheme` enum located at [`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift) to create a single source of truth.
- **Organize tokens by semantic type** using nested enums like `Spacing`, `FontSize`, and `Background` to prevent cross-contamination of values.
- **Extend SwiftUI's `View` protocol** with convenience modifiers such as `panelHeaderBar()` and `shadow(_:)` to streamline theme application.
- **Support cross-platform consistency** by providing both `NSColor` and `Color` computed properties for every color token.
- **Enforce the architecture** through linting rules that reject numeric literals outside the theme file, ensuring compliance at build time.

## Frequently Asked Questions

### How does AppTheme prevent developers from accidentally using hard-coded values?

The Palmier-Pro codebase enforces a **zero-tolerance policy for magic numbers** combined with automated linting. By requiring all visual constants to live exclusively in [`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift), code reviews can quickly identify violations. Additionally, the typed grouping of tokens makes it easier to discover the correct constant than to guess a literal value, steering developers toward the sanctioned API.

### Can this token system support both SwiftUI and AppKit in the same project?

Yes. Each color token in `AppTheme` exposes computed properties for both `Color` (SwiftUI) and `NSColor` (AppKit), allowing the same spacing and color definitions to power views in [`Sources/PalmierPro/Timeline/TimelineView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Timeline/TimelineView.swift) and legacy AppKit components simultaneously. This dual-type approach ensures consistency during gradual UI migrations.

### What happens when a design token needs to change globally?

Because each token exists in exactly one location within `AppTheme`, changing a value like `AppTheme.Spacing.sm` from `6` pt to `8` pt instantly updates every view referencing that constant. This centralized architecture eliminates the need for find-and-replace operations across dozens of files, reducing regression risk when iterating on design.

### How do View extensions contribute to design consistency?

The `View` extensions defined at the bottom of [`AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.swift) (lines 28-33) bundle complex styling decisions into single modifiers like `.panelHeaderBar()`. These extensions internally reference multiple theme tokens—background color, border width, and height—ensuring that every panel header uses identical specifications without requiring developers to remember the correct combination of values.