Add Stark UI/UX design plugin - #98
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces 'Stark', a comprehensive UI/UX design plugin for AI coding agents that supports Web, Windows, Apple, and Android platforms. It includes a vast library of design references, skill definitions, and utility scripts for token export and platform detection. The review feedback highlights a critical bug in the token resolution logic regarding circular references and type preservation, suggests adopting idiomatic camelCase for SwiftUI variable names, and advises against using fragile timeouts in the Playwright-based screenshot tool.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 330079c825
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Updated the PR after the review feedback:
Validation run locally:
|
Code Review SummaryStatus: 6 Issues Found (1 fixed, 5 remaining) | Recommendation: Address before merge Overview
Issue Details (click to expand)FIXED
REMAINING — WARNING
REMAINING — SUGGESTION
Other Observations (not in diff)No new issues outside the diff. This is an incremental re-review — 3 prior issues were fixed, 1 new issue was introduced in Files Reviewed (8 changed files)
Reviewed by step-3.5-flash · 2,420,938 tokens |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9c58869c47
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e40d8df176
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Updated after the latest review feedback:
Validated locally with:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 251e2a6bd3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Follow-up update for the remaining actionable review threads:
Validated locally with:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 083801e5eb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if t == "color": | ||
| lines.append(f" --color-{kebab(path)}: {v};") | ||
| elif t == "dimension": | ||
| lines.append(f" --spacing-{kebab(path)}: {v};") |
There was a problem hiding this comment.
Strip type prefixes before emitting Tailwind theme keys
When exporting any DTCG bundle grouped under color/spacing (including the bundled token files and the skill's own example), this prepends the Tailwind namespace to the full token path, producing keys like --color-color-brand-primary and --spacing-spacing-xs. Tailwind v4 theme namespaces map variables such as --color-mint-500 to utilities like bg-mint-500, and the skill's matrix promises --color-brand-primary; the current output instead forces unexpected class names like bg-color-brand-primary. Strip the leading token category before building the @theme variable names.
Useful? React with 👍 / 👎.
| if t == "color": | ||
| v_str = str(v) | ||
| if v_str.startswith("#"): | ||
| lines.append(f" val {var} = {hex_to_compose(v_str)}") |
There was a problem hiding this comment.
Emit a Compose ColorScheme, not only loose colors
When users run the documented Compose export path to get Material3 ColorScheme + Typography, this exporter only writes individual Color vals and optional Typography, never a ColorScheme. With the bundled material3-expressive.json, the generated file cannot be passed to MaterialTheme(colorScheme = ...), so Android consumers must hand-map primary, onPrimary, dark colors, etc., defeating the token export. Generate a ColorScheme/lightColorScheme/darkColorScheme from semantic color tokens alongside the typography.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7b6177f74a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| def resolve(value: Any, all_tokens: dict[str, dict[str, Any]], visited: set[str] | None = None) -> Any: | ||
| if not isinstance(value, str): | ||
| return value |
There was a problem hiding this comment.
Resolve references inside composite token values
When a typography token follows the common DTCG pattern of referencing primitive tokens inside its $value object, e.g. fontSize: "{size.body}" or fontWeight: "{weight.semibold}", this early return leaves those nested references unresolved. The SwiftUI/Compose exporters then parse the literal {...} strings and fall back to defaults such as 16/regular, so valid token bundles silently produce incorrect typography even though the script advertises reference resolution.
Useful? React with 👍 / 👎.
| | Apple (SwiftUI) | `extension Color { static let brandPrimary = ... }` + `Color` asset catalog JSON | | ||
| | Android (Compose) | `ColorScheme(primary = Color(0xFF...), ...)` + `Typography` | | ||
| | Windows (WinUI 3) | `<ResourceDictionary>` with `<Color>`, `<SolidColorBrush>`, `<x:Double>` | | ||
| | Flutter | `ThemeData(colorScheme: ColorScheme(...))` | |
There was a problem hiding this comment.
Remove or implement the Flutter token target
This matrix tells agents to use the token exporter for Flutter ThemeData, but token_export.py only accepts tailwind, css, swiftui, compose, and winui as --target choices, so a user asking for Flutter token output will be routed to a documented path that immediately fails with an invalid choice. Either add a Flutter exporter or drop this row until it is supported.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9b3639026
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| | `.swift` `.swiftui`, "SwiftUI", "iOS app", "iPadOS", "macOS", "Liquid Glass", "HIG", "SF Symbols", "App Store", "Tahoe" | `apple-design` | | ||
| | `.kt` `.kts`, "Compose", "Jetpack Compose", "Material 3", "Material You", "Pixel app", "Android app" | `android-design` | | ||
| | "Tauri", "Electron", "Flutter", "React Native", "Expo", "Compose Multiplatform", "CMP", "Uno Platform", "Avalonia", "MAUI" | `cross-platform-design` | | ||
| | "translate this UI", "translate this screen", "translate this design", "port this UI", "convert this screen", "from iOS to Windows", "from Apple to Android" | `cross-platform-design` first, then the target platform skill | |
There was a problem hiding this comment.
Prioritize translation before target-platform rows
Because this table says it is scanned "in priority order", this translation row is unreachable for the README's documented prompt Translate this iOS settings screen into a Windows app: the earlier Windows row matches Windows app first, so the router sends the request straight to windows-design instead of doing the cross-platform idiom translation step. Move the translate/port/convert signals above the single-platform rows so source-and-target prompts are handled by cross-platform-design first.
Useful? React with 👍 / 👎.
| if len(runner_up) > 1 and runner_up[0] - runner_up[1] < 2: | ||
| # Close call — multi-platform request | ||
| return "cross-platform" |
There was a problem hiding this comment.
Do not treat single-platform dashboards as cross-platform
This close-score fallback turns common single-platform prompts into cross-platform solely because dashboard is also counted as a web signal; for example, I checked Build an iOS app dashboard, Build an Android app dashboard, and Make a Win11 dashboard with Mica, and all return cross-platform despite naming one target platform. That routes users away from the platform skill and contradicts the router's goal of picking the named native idiom; only return cross-platform when an actual multi-platform signal is present or multiple platform names are explicit.
Useful? React with 👍 / 👎.
| ], | ||
| "apple": [ | ||
| r"\bswiftui\b", r"\buikit\b", r"\bappkit\b", r"\bmacos\b", | ||
| r"\bipados?\b", r"\bios\s*\d+\b", r"\bios app\b", |
There was a problem hiding this comment.
The Apple detector only matches ios when it is followed by a version or the word app, so prompts like Build an iOS settings screen return ambiguous even though the README and router examples use plain iOS wording. Add a standalone \bios\b/iPhone/iPad signal here so normal Apple requests route to apple instead of asking an unnecessary platform question.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf809461f1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if key.startswith("$"): | ||
| continue | ||
| new_prefix = f"{prefix}.{key}" if prefix else key | ||
| out.update(flatten(child, new_prefix)) |
There was a problem hiding this comment.
Inherit group-level token types
When a valid DTCG bundle defines $type on a group instead of repeating it on every leaf, this recursion drops that parent metadata, so exporters see tok.get("$type") as None and silently emit nothing for those tokens. For example, { "color": { "$type": "color", "brand": { "$value": "#ff0000" } } } currently flattens to a token with no type and produces an empty CSS/Tailwind output; carry inherited $type into child tokens while flattening.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f75ce905c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| | `.kt` `.kts`, "Compose", "Jetpack Compose", "Material 3", "Material You", "Pixel app", "Android app" | `android-design` | | ||
| | "Tauri", "Electron", "Flutter", "React Native", "Expo", "Compose Multiplatform", "CMP", "Uno Platform", "Avalonia", "MAUI" | `cross-platform-design` | | ||
| | "translate this UI", "translate this screen", "translate this design", "port this UI", "convert this screen", "from iOS to Windows", "from Apple to Android" | `cross-platform-design` first, then the target platform skill | | ||
| | "design tokens", "export tokens", "DTCG", "token JSON", "ColorScheme", "Typography tokens" | `design-tokens` | |
There was a problem hiding this comment.
Move token routing above platform rows
Because this table is scanned in priority order, the token row is reached only after target-platform rows. Common token requests such as “export tokens to Tailwind”, “make a Compose ColorScheme from a Figma palette”, or “generate SwiftUI tokens” match Tailwind/Compose/SwiftUI first and get routed to web/android/apple instead of design-tokens, bypassing the exporter this skill is meant to invoke. Put token-specific signals before platform-specific implementation rows so target-specific token exports still use the token workflow.
Useful? React with 👍 / 👎.
|
|
||
| def compose_text_style_expr(value: dict[str, Any]) -> str: | ||
| size = numeric_token_value(value.get("fontSize"), 16) | ||
| line_height = numeric_token_value(value.get("lineHeight"), size) |
There was a problem hiding this comment.
Scale unitless line heights before Compose export
When a typography token uses a unitless line-height multiplier, which the skill's own DTCG example and bundled Awwwards tokens do, this treats 0.95 or 1.05 as an absolute sp value. Running the bundled awwwards-editorial.json through --target compose emits lineHeight = 0.95.sp for a 48sp display style, causing unreadably clipped/overlapped text; unitless values should be multiplied by the resolved font size before appending .sp.
Useful? React with 👍 / 👎.
| - Product quality checks force specific jobs, proof surfaces, complete states, scan speed, and one memorable anchor before code. | ||
| - Creative direction turns "make it creative" into a concrete world, metaphor, material language, repeated motif, forbidden defaults, and one tasteful risk. | ||
| - Interaction guidance chooses CSS, Motion, GSAP, native scroll CSS, Lenis, command palettes, split panes, timelines, or no motion by surface and product job. | ||
| - Web implementation tracks choose static HTML/CSS/JS, Vite React, Next, Astro, or the existing stack by interaction needs and dependency risk. |
There was a problem hiding this comment.
SUGGESTION: Inconsistent framework naming
The bullet uses "Vite React" while the detailed "Web Implementation Tracks" section uses "Vite + React". Use consistent terminology throughout.
| - material language | ||
| - typography personality | ||
| - layout grammar | ||
| - repeated motif |
There was a problem hiding this comment.
SUGGESTION: Creative Direction checklist omits "Motion voice"
The "Creative Direction" section lists eight items but the full creative-direction.md brief template includes "Motion voice" between "layout grammar" and "repeated motif". Consider adding it to the README checklist for completeness.
| - Platform idiom: web / Windows / Apple / Android / cross-platform translation | ||
| - Product thesis: the specific job, risk, queue, artifact, or decision this surface exists for | ||
| - Visual direction: ... | ||
| - Creative direction: world, visual metaphor, material language, repeated motif, tasteful risk |
There was a problem hiding this comment.
SUGGESTION: Creative direction field in UI decision brief is incomplete
The template lists only "world, visual metaphor, material language, repeated motif, tasteful risk". It omits several items from the full creative direction brief (World, Mood, Typography personality, Layout grammar, Motion voice, Forbidden defaults, Restraints). Either list all items or reference the full creative-direction.md file.
| | Vite + React | advanced landing page, animated campaign, dashboard, command palette, filters, inspectors, app shell, stateful demo | content-heavy SEO site that needs server/rendering decisions | | ||
| | Next.js | marketing + app hybrid, SEO, routing, server data, auth, docs/product pages at scale | static one-pager or local prototype where framework weight adds little | | ||
| | Astro | content/editorial site, docs, mostly static pages with islands of interactivity | dense app UI, complex client-side state everywhere | | ||
| | SvelteKit/Solid/Qwik | user explicitly asks, existing project uses it, or performance/interaction model fits | when the agent would choose it just to be novel | |
There was a problem hiding this comment.
SUGGESTION: Framework table row ambiguous
The fifth track row combines "SvelteKit/Solid/Qwik" with slashes, which could be read as a single option. Use commas or separate rows for clarity: "SvelteKit, Solid, Qwik".
| - Product quality checks force specific jobs, proof surfaces, complete states, scan speed, and one memorable anchor before code. | ||
| - Creative direction turns "make it creative" into a concrete world, metaphor, material language, repeated motif, forbidden defaults, and one tasteful risk. | ||
| - Interaction guidance chooses CSS, Motion, GSAP, native scroll CSS, Lenis, command palettes, split panes, timelines, or no motion by surface and product job. | ||
| - Web implementation tracks choose static HTML/CSS/JS, Vite + React, Next, Astro, or the existing stack by interaction needs and dependency risk. |
There was a problem hiding this comment.
SUGGESTION: Inconsistent framework naming — bullet uses "Vite React" while the "Web Implementation Tracks" section uses "Vite + React". Use consistent terminology throughout.
| - material language | ||
| - typography personality | ||
| - layout grammar | ||
| - motion voice |
There was a problem hiding this comment.
SUGGESTION: Creative Direction checklist omits "motion voice" — it's listed in creative-direction.md between "layout grammar" and "repeated motif" but missing from the README summary.
| - Platform idiom: web / Windows / Apple / Android / cross-platform translation | ||
| - Product thesis: the specific job, risk, queue, artifact, or decision this surface exists for | ||
| - Visual direction: ... | ||
| - Creative direction: see `creative-direction.md` brief, including world, mood, visual metaphor, material language, typography personality, layout grammar, motion voice, repeated motif, forbidden defaults, tasteful risk, and restraints |
There was a problem hiding this comment.
SUGGESTION: Creative direction field in the UI decision brief template is incomplete — lists only a subset of items from the full creative-direction.md brief. Reference the full file instead.
| | Vite + React | advanced landing page, animated campaign, dashboard, command palette, filters, inspectors, app shell, stateful demo | content-heavy SEO site that needs server/rendering decisions | | ||
| | Next.js | marketing + app hybrid, SEO, routing, server data, auth, docs/product pages at scale | static one-pager or local prototype where framework weight adds little | | ||
| | Astro | content/editorial site, docs, mostly static pages with islands of interactivity | dense app UI, complex client-side state everywhere | | ||
| | SvelteKit, Solid, or Qwik | user explicitly asks, existing project uses it, or performance/interaction model fits | when the agent would choose it just to be novel | |
There was a problem hiding this comment.
SUGGESTION: Ambiguous framework row — "SvelteKit/Solid/Qwik" could be read as a single option. Use commas or separate rows: "SvelteKit, Solid, Qwik".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0bb1047db1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| r"\bfluent\b", r"\bmica\b", r"\bacrylic\b", r"\bwindows 1[12]\b", | ||
| r"\bwin11\b", r"\bwin12\b", r"\bsegoe\b", r"\bmicrosoft store\b", |
There was a problem hiding this comment.
Recognize plain Windows requests
For prompts that say just Windows app (including this plugin's README examples), the fallback detector never counts Windows because the Windows signals only match versioned Windows 11/12, Win11/Win12, WinUI/Mica/etc. I checked python3 plugins/f0d010c/stark/scripts/detect_platform.py --text 'Translate this iOS settings screen into a Windows app', and it returns apple, so router fallback sends common Windows translation/native-app requests to the wrong skill whenever the user doesn't also say WinUI/Mica/Win11. Add a standalone \bwindows\b / \bwindows app\b signal.
Useful? React with 👍 / 👎.
| if not isinstance(v, dict) or "lineHeight" not in v: | ||
| continue | ||
| line_height_count += 1 | ||
| line_height = numeric_token_value(v.get("lineHeight"), numeric_token_value(v.get("fontSize"), 16)) |
There was a problem hiding this comment.
Scale SwiftUI unitless line heights
When typography tokens use unitless line-height multipliers, the SwiftUI exporter writes the multiplier directly as a CGFloat instead of converting it to points. For example, exporting the bundled awwwards-editorial.json produces typographyDisplayLineHeight: CGFloat = 0.95 for a 48pt display style, so consumers using the generated line-height token get effectively sub-point spacing rather than the intended ~45.6pt line height. Reuse the same multiplier scaling logic used by the Compose exporter before emitting Swift line-height constants.
Useful? React with 👍 / 👎.
|
Follow-up hardening update:
Current checks are green locally and on the PR: alphabetical, marketplace sync, and Kilo review all pass. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e254e23cd4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| elif t == "dimension": | ||
| spacing_path = strip_category(strip_category(path, "spacing"), "space") | ||
| lines.append(f" --spacing-{kebab(spacing_path)}: {v};") |
There was a problem hiding this comment.
Emit Tailwind radius variables for radius tokens
When a bundle contains non-spacing dimensions such as the bundled fluent-2.json radius.* or Material shape.* tokens, this branch emits all of them under --spacing-* (for example --spacing-radius-medium). Tailwind's border-radius utilities read the --radius-* theme namespace, so exported radius/shape tokens are not usable by rounded-* classes and users following the token workflow silently lose those platform shape values.
Useful? React with 👍 / 👎.
| }, | ||
| "typography": { | ||
| "$description": "SwiftUI Font.TextStyle — never hard-coded points. Sizes adapt with Dynamic Type.", | ||
| "large-title": { "$value": "Font.largeTitle", "$type": "string", "$description": "34pt regular" }, |
There was a problem hiding this comment.
Preserve Apple system Font tokens in Swift export
In the current tree, exporting the bundled apple-system.json with --target swiftui produces only colors because these SwiftUI text-style tokens are recorded as $type: "string", while the exporter only builds the extension Font from $type: "typography" dictionary values. This leaves the advertised Apple Color/Font token output without any Font.largeTitle/Font.body constants; either encode these as exportable typography tokens or teach the SwiftUI exporter to pass through Font.* string values.
Useful? React with 👍 / 👎.
Summary
Adds Stark, a UI/UX design plugin for AI coding agents. Stark routes product-flow, platform-native UI, asset planning, and shipped-reference analysis work into focused design skills before code.
Included
Validation