# Custom SVG Icons via SVGR — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Set up SVGR so SVG files from Figma can be imported as React components with `currentColor` and flexible sizing.

**Architecture:** `@svgr/webpack` transforms `.svg` files into React components at build time. Turbopack config handles dev, webpack config handles production. Icons live in `apps/web/src/shared/icons/` with a barrel re-export.

**Tech Stack:** Next.js 16, @svgr/webpack@^8, TypeScript, Tailwind CSS 4

**Spec:** `docs/superpowers/specs/2026-03-18-svg-icons-design.md`

---

### Task 1: Install @svgr/webpack

**Files:**
- Modify: `apps/web/package.json`

- [ ] **Step 1: Install the dependency**

```bash
cd apps/web && pnpm add -D @svgr/webpack@^8
```

- [ ] **Step 2: Verify installation**

```bash
cd apps/web && pnpm list @svgr/webpack
```

Expected: shows `@svgr/webpack 8.x.x`

- [ ] **Step 3: Commit**

```bash
git add apps/web/package.json pnpm-lock.yaml
git commit -m "chore: add @svgr/webpack dependency"
```

---

### Task 2: Configure Next.js for SVGR (Turbopack + Webpack)

**Files:**
- Modify: `apps/web/next.config.ts`

- [ ] **Step 1: Add Turbopack and Webpack SVG rules to `next.config.ts`**

Replace the current `nextConfig` object with:

```ts
import type { NextConfig } from 'next';
import { resolve } from 'path';
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin('./src/shared/i18n/request.ts');

const nextConfig: NextConfig = {
  output: 'standalone',
  outputFileTracingRoot: resolve(__dirname, '../../'),
  reactStrictMode: true,
  transpilePackages: ['@repo/shared', '@repo/ui'],
  reactCompiler: true,
  turbopack: {
    rules: {
      '*.svg': {
        loaders: [
          {
            loader: '@svgr/webpack',
            options: {
              svgoConfig: {
                plugins: [
                  {
                    name: 'preset-default',
                    params: {
                      overrides: {
                        removeViewBox: false,
                      },
                    },
                  },
                  {
                    name: 'convertColors',
                    params: {
                      currentColor: true,
                    },
                  },
                ],
              },
            },
          },
        ],
        as: '*.js',
      },
    },
  },
  webpack(config) {
    // Remove Next.js built-in SVG handling to avoid conflicts
    const fileLoaderRule = config.module.rules.find(
      (rule: { test?: RegExp }) => rule.test?.test?.('.svg'),
    );
    if (fileLoaderRule) {
      fileLoaderRule.exclude = /\.svg$/;
    }

    config.module.rules.push({
      test: /\.svg$/,
      use: [
        {
          loader: '@svgr/webpack',
          options: {
            svgoConfig: {
              plugins: [
                {
                  name: 'preset-default',
                  params: {
                    overrides: {
                      removeViewBox: false,
                    },
                  },
                },
                {
                  name: 'convertColors',
                  params: {
                    currentColor: true,
                  },
                },
              ],
            },
          },
        },
      ],
    });
    return config;
  },
  ...(process.env.NODE_ENV === 'development' && {
    async rewrites() {
      return [
        {
          source: '/api/v1/:path*',
          destination: `${process.env.API_URL || 'http://localhost:5001'}/api/v1/:path*`,
        },
      ];
    },
  }),
};

export default withNextIntl(nextConfig);
```

- [ ] **Step 2: Commit**

```bash
git add apps/web/next.config.ts
git commit -m "feat: configure SVGR for Turbopack and Webpack"
```

---

### Task 3: Add TypeScript declaration for SVG imports

**Files:**
- Create: `apps/web/svg.d.ts`

- [ ] **Step 1: Create `svg.d.ts` at project root (alongside `next-env.d.ts`)**

```ts
declare module '*.svg' {
  import { FC, SVGProps } from 'react';
  const component: FC<SVGProps<SVGSVGElement>>;
  export default component;
}
```

- [ ] **Step 2: Verify `tsconfig.json` includes it**

The existing `include` pattern `"**/*.ts"` already covers `svg.d.ts` at the project root. No changes needed.

Run:
```bash
cd apps/web && pnpm check-types
```

Expected: no errors

- [ ] **Step 3: Commit**

```bash
git add apps/web/svg.d.ts
git commit -m "feat: add TypeScript declaration for SVG imports"
```

---

### Task 4: Create icons directory and migrate existing SVG

**Files:**
- Create: `apps/web/src/shared/icons/index.ts`
- Move: `apps/web/public/icon/map-pin.svg` → `apps/web/src/shared/icons/map-pin.svg`
- Delete: `apps/web/public/icon/` (directory)

- [ ] **Step 1: Create the icons directory**

```bash
mkdir -p apps/web/src/shared/icons
```

- [ ] **Step 2: Move the existing map-pin.svg**

```bash
mv apps/web/public/icon/map-pin.svg apps/web/src/shared/icons/map-pin.svg
```

- [ ] **Step 3: Delete the empty `public/icon/` directory**

```bash
rm -r apps/web/public/icon
```

- [ ] **Step 4: Create `index.ts` barrel file**

```ts
export { default as MapPinIcon } from './map-pin.svg';
```

- [ ] **Step 5: Commit**

Note: `apps/web/public/icon/` was untracked by git, so deleting it requires no git operation. Only the new files need to be staged.

```bash
git add apps/web/src/shared/icons/
git commit -m "feat: create shared/icons directory, migrate map-pin.svg"
```

---

### Task 5: Verify the setup works end-to-end

**Files:**
- No new files — uses existing setup

- [ ] **Step 1: Run type check**

```bash
cd apps/web && pnpm check-types
```

Expected: no errors

- [ ] **Step 2: Run dev server and verify SVG import works**

```bash
cd apps/web && pnpm dev
```

In browser devtools or by temporarily adding to any page component:

```tsx
import { MapPinIcon } from '@/shared/icons';

// Inside the component JSX:
<MapPinIcon className="w-6 h-6 text-primary-500" />
```

Expected: the map pin icon renders, colored in primary-500, sized at 24x24px.

- [ ] **Step 3: Run production build**

```bash
cd apps/web && pnpm build
```

Expected: build succeeds without errors

- [ ] **Step 4: Clean up test usage (remove temporary import if added)**

- [ ] **Step 5: Commit any remaining changes**

```bash
git add -A && git commit -m "feat: verify SVG icons setup works"
```
