ui-architecture-icon

Add SVG icons to the Nums game client — convert SVG, create component, export, update storybook. Use when adding, modifying, or removing icon components.

9 stars

Best use case

ui-architecture-icon is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Add SVG icons to the Nums game client — convert SVG, create component, export, update storybook. Use when adding, modifying, or removing icon components.

Teams using ui-architecture-icon should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/ui-architecture-icon/SKILL.md --create-dirs "https://raw.githubusercontent.com/cartridge-gg/nums/main/.agents/skills/ui-architecture-icon/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/ui-architecture-icon/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How ui-architecture-icon Compares

Feature / Agentui-architecture-iconStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Add SVG icons to the Nums game client — convert SVG, create component, export, update storybook. Use when adding, modifying, or removing icon components.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Adding an Icon

## Step 1: Identify the Category

| Category   | Location          | Pattern                                              | When to Use          |
| ---------- | ----------------- | ---------------------------------------------------- | -------------------- |
| `regulars` | `icons/regulars/` | Simple, no variants                                  | General UI icons     |
| `powers`   | `icons/powers/`   | File-based variants (`.regular`, `.lock`, `.used`)   | Game power icons     |
| `traps`    | `icons/traps/`    | File-based variants (`.regular`, `.shadow`, `.used`) | Game trap icons      |
| `states`   | `icons/states/`   | Prop-based variants (`solid` / `line`)               | Toggle/nav icons     |
| `exotics`  | `icons/exotics/`  | Simple, no variants                                  | Logos, special icons |
| `effects`  | `icons/effects/`  | Simple, no variants                                  | Visual effects       |

## Step 2: Create the Icon Component

### Template for `regulars` / `exotics` (simple icon)

File: `client/src/components/icons/<category>/<icon-name>.tsx`

```tsx
import { forwardRef, memo } from "react";
import { iconVariants, type IconProps } from "..";

export const MyIconIcon = memo(
  forwardRef<SVGSVGElement, IconProps>(
    ({ className, size, ...props }, forwardedRef) => (
      <svg
        width="24"
        height="24"
        viewBox="0 0 24 24"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
        className={iconVariants({ size, className })}
        ref={forwardedRef}
        {...props}
      >
        {/* SVG paths here */}
      </svg>
    ),
  ),
);

MyIconIcon.displayName = "MyIconIcon";
```

### Template for `powers` / `traps` (file-based variants)

Create 3 files per icon: `<name>.regular.tsx`, `<name>.lock.tsx`, `<name>.used.tsx`

Each file uses the same template above but with different SVG content and component names:

- `<name>.regular.tsx` → `export const MyIconIcon = ...`
- `<name>.lock.tsx` → `export const MyIconLockedIcon = ...`
- `<name>.used.tsx` → `export const MyIconUsedIcon = ...`

### Template for `states` (prop-based variants)

```tsx
import { forwardRef, memo } from "react";
import { iconVariants, type StateIconProps } from "..";

export const MyIconIcon = memo(
  forwardRef<SVGSVGElement, StateIconProps>(
    ({ className, size, variant, ...props }, forwardedRef) => (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
        className={iconVariants({ size, className })}
        ref={forwardedRef}
        {...props}
      >
        {(() => {
          switch (variant) {
            case "solid":
              return <path d="..." fill="currentColor" />;
            case "line":
              return <path d="..." fill="currentColor" />;
          }
        })()}
      </svg>
    ),
  ),
);

MyIconIcon.displayName = "MyIconIcon";
```

## Step 3: Convert SVG for React

When pasting SVG from a design tool:

1. **Keep** the `<svg>` wrapper with `width="24" height="24" viewBox="0 0 24 24" fill="none"`
2. **Replace** the `<svg>` attributes with the template's (className, ref, etc.)
3. **Convert** kebab-case attributes to camelCase:
   - `fill-rule` → `fillRule`
   - `clip-rule` → `clipRule`
   - `flood-opacity` → `floodOpacity`
   - `color-interpolation-filters` → `colorInterpolationFilters`
   - `filter-units` → `filterUnits`
   - `stroke-width` → `strokeWidth`
   - `stroke-linecap` → `strokeLinecap`
   - `stroke-linejoin` → `strokeLinejoin`
4. **Replace** hardcoded fill colors with `fill="currentColor"` (so color inherits from CSS)
5. **Remove** unnecessary `<defs>` blocks (filters, gradients) unless they are referenced by paths via `filter="url(#...)"` or `fill="url(#...")"`
6. **Remove** `xmlns:xlink` and other unnecessary namespace attributes

## Step 4: Export from Index

Add to `client/src/components/icons/<category>/index.ts`:

```ts
export * from "./<icon-name>";
// For file-based variants:
export * from "./<icon-name>.regular";
export * from "./<icon-name>.lock";
export * from "./<icon-name>.used";
```

Keep the exports **sorted alphabetically** by file name.

## Step 5: Update Storybook

Edit `client/src/components/icons/<category>/index.stories.tsx`.

**IMPORTANT**: Before editing, read the existing storybook file to match the exact code style.

### For `regulars` / `exotics` — add to the icons array:

```tsx
const regularIcons = [
  // ... existing icons (alphabetical)
  { name: "MyIconIcon", component: Icons.MyIconIcon },
];
```

### For `powers` / `traps` — add to the variant array:

```tsx
const powers = [
  // ... existing powers
  {
    name: "MyIcon",
    color: "text-mycolor-100",
    normal: Icons.MyIconIcon,
    locked: Icons.MyIconLockedIcon,
    used: Icons.MyIconUsedIcon,
  },
];
```

### For `states` — add to the state icons array:

```tsx
const stateIcons = [
  // ... existing state icons
  { name: "MyIconIcon", component: Icons.MyIconIcon },
];
```

---

## Naming Conventions

| What               | Convention               | Example                                 |
| ------------------ | ------------------------ | --------------------------------------- |
| File (simple)      | `kebab-case.tsx`         | `laurel.tsx`                            |
| File (variant)     | `kebab-case.variant.tsx` | `boost-high.regular.tsx`                |
| Component          | `PascalCaseIcon`         | `LaurelIcon`                            |
| Component (locked) | `PascalCaseLockedIcon`   | `BoostHighLockedIcon`                   |
| Component (used)   | `PascalCaseUsedIcon`     | `BoostHighUsedIcon`                     |
| displayName        | Same as component        | `LaurelIcon.displayName = "LaurelIcon"` |

## Icon Size Tokens

```ts
const size = {
  "4xs": "h-1 w-1",
  "3xs": "h-2 w-2",
  "2xs": "h-3 w-3",
  xs: "h-4 w-4",
  sm: "h-5 w-5",
  md: "h-6 w-6", // DEFAULT
  lg: "h-8 w-8",
  xl: "h-12 w-12",
  "2xl": "h-14 w-14",
  "3xl": "h-16 w-16",
};
```

## Type Definitions

```ts
// client/src/components/icons/types.ts
import type { VariantProps } from "class-variance-authority";
import type { SVGProps } from "react";
import type { iconVariants } from ".";

// For icons WITHOUT variant prop
export type IconProps = Omit<
  SVGProps<SVGSVGElement> & VariantProps<typeof iconVariants>,
  "variant"
>;

// For icons WITH variant prop (solid/line)
export type StateIconProps = Omit<
  SVGProps<SVGSVGElement> & VariantProps<typeof iconVariants>,
  "variant"
> & { variant: "solid" | "line" };
```

## Checklist

- [ ] File created at correct path with correct naming
- [ ] `memo()` + `forwardRef<SVGSVGElement, IconProps>()` wrapping
- [ ] `iconVariants({ size, className })` for className
- [ ] `ref={forwardedRef}` on `<svg>`
- [ ] `{...props}` spread on `<svg>`
- [ ] `fill="currentColor"` on paths (not hardcoded colors)
- [ ] SVG attributes in camelCase (no kebab-case)
- [ ] Unnecessary `<defs>` removed
- [ ] `displayName` set
- [ ] Export added to category `index.ts` (alphabetical order)
- [ ] Storybook entry added to category `index.stories.tsx`

Related Skills

ui-architecture

9
from cartridge-gg/nums

UI component patterns for the Nums game client — Radix primitives, elements, containers, theming, Storybook conventions. Use when creating or modifying UI components, adding storybook stories, or working with the design system.

dojo-architecture

9
from cartridge-gg/nums

Shinigami architecture for fully onchain Dojo games — Elements, Types, Models, Components, Systems, Helpers, Store, Events, Interfaces. Use when structuring a new game, adding modules, understanding the codebase hierarchy, or implementing new game mechanics.

ui-ux-pro-max

9
from cartridge-gg/nums

UI/UX design intelligence for web and mobile. Includes 50+ styles, 161 color palettes, 57 font pairings, 161 product types, 99 UX guidelines, and 25 chart types across 10 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui, and HTML/CSS). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, and check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, and mobile app. Elements: button, modal, navbar, sidebar, card, table, form, and chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, and flat design. Topics: color systems, accessibility, animation, layout, typography, font pairing, spacing, interaction states, shadow, and gradient. Integrations: shadcn/ui MCP for component search and examples.

shadcn

9
from cartridge-gg/nums

Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset".

render-daily-replay

9
from cartridge-gg/nums

Auto-render a Remotion video replay of a Nums game on Mainnet. Resolves the target `gameId` from Torii (best reward of the day OR best score of the day, OR a specific gameId the user provides), silently auto-fetches the current NUMS price from Ekubo, then runs `pnpm remotion:render:game` with the right props. Use when the user asks to render today's top game, the daily winner, the biggest reward, the highest score, or any specific gameId, without having to assemble the render command by hand.

remotion-best-practices

9
from cartridge-gg/nums

Best practices for Remotion - Video creation in React

nums-remotion-replay

9
from cartridge-gg/nums

Project-specific skill for the Nums Remotion package that generates game replay videos by reusing the existing client React components. Covers the cross-package webpack setup, client-component overrides, Torii data fetching, font loading, render flow quirks, and hosting. Use when working on `remotion/` or the `SlidingNumber` component, adding new compositions, debugging font/animation issues, or setting up hosting for the Remotion Studio. Pairs with the generic `remotion-best-practices` skill.

dojo

9
from cartridge-gg/nums

Dojo Engine framework patterns — World, Systems, Models, Events, Components, Store, permissions, testing with spawn_test_world, and deployment with sozo.

dojo-world

9
from cartridge-gg/nums

Manage world permissions, namespaces, resource registration, and access control. Use when configuring world ownership, setting up authorization policies, or managing resource permissions.

Cartridge VRF Integration

9
from cartridge-gg/nums

Integrate Cartridge's Verifiable Random Function (VRF) for provably fair, atomic randomness in Dojo games.

dojo-token

9
from cartridge-gg/nums

Implement, deploy, and index ERC20 and ERC721 tokens in Dojo. Use when adding token contracts, deploying them, or configuring Torii to index balances and transfers.

dojo-test

9
from cartridge-gg/nums

Write tests for Dojo models and systems using spawn_test_world, cheat codes, and assertions. Use when testing game logic, verifying state changes, or ensuring system correctness.