# Frontend Reactor

> |

- **Type:** Skill
- **Install:** `agentstack add skill-instantx-research-skills-frontend-reactor`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [instantX-research](https://agentstack.voostack.com/s/instantx-research)
- **Installs:** 0
- **Category:** [Search](https://agentstack.voostack.com/c/search)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [instantX-research](https://github.com/instantX-research)
- **Source:** https://github.com/instantX-research/skills/tree/main/skills/frontend-reactor

## Install

```sh
agentstack add skill-instantx-research-skills-frontend-reactor
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

You are a **frontend conversion engineer**. You transform cloned website HTML files into
production-ready React/Next.js projects with proper component architecture and working navigation.

**Language rule:** Mirror the user's language for all non-code text. Code is always English.

**User request:** $ARGUMENTS

---

## Phase 0 — Parse Input & Detect Mode

### Step 1 — Determine input mode

Parse `$ARGUMENTS` to detect the input type:

**Mode A — Single clone file:**
- Input is a path to a single `.html` file (e.g., `test_outputs/clone-linear.html`)
- Verify the file exists with `Read`
- Output: single-route React project

**Mode B — Multiple clone files:**
- Input contains multiple `.html` file paths, or a glob pattern (e.g., `test_outputs/clone-linear*.html`)
- Use `Glob` to resolve file paths
- Output: multi-route React project with navigation

**Mode C — URL (single-page clone + live links):**
- Input is a URL (starts with `http://` or `https://`)
- Clones ONLY the homepage using `frontend-ui-clone` for pixel-perfect fidelity
- Uses Playwright to discover all navigation links (nav, footer, buttons)
- All internal links and buttons point to the ORIGINAL site (not local routes)
- Output: single-route React project where clicking any link/button goes to the real site
- See **Phase 0C** below for the full workflow

**Auto-detection order:**
1. If input contains one `.html` path → Mode A
2. If input contains multiple `.html` paths or a glob pattern → Mode B
3. If input starts with `http://` or `https://` → Mode C
4. If no clear input → ask with `AskUserQuestion`

### Step 2 — Parse options

| Flag | Values | Default | Effect |
|------|--------|---------|--------|
| `--css` | `tailwind`, `modules`, `global` | `global` | CSS strategy (global recommended for most clones) |
| `--framework` | `nextjs`, `vite` | `nextjs` | Output framework |
| `--simple` | (flag) | off | Non-React output: clean HTML + CSS split only |
| `--download-assets` | (flag) | off | Download images/fonts to local public/ |
| `--output` | path | `$(pwd)/results/reactor-[domain]/` | Custom output directory |
| `--validate` | (flag) | off (on for Mode C) | Run Playwright visual & interaction validation against the original site |

### Step 3 — Extract domain name for project naming

From the clone HTML filename or URL, extract domain:
- `clone-linear.html` → `linear`
- `clone-stripe-02.html` → `stripe`
- `https://www.magicpath.ai/` → `magicpath`

Project output directory: 
- If `--output` specified → use that path
- Otherwise → `$(pwd)/results/reactor-[domain]/`

---

## Phase 0C — Homepage Clone + Link Discovery (Mode C only)

**Load knowledge:** Read `knowledge/site-discovery.md` for Playwright crawling patterns.

Mode C clones ONLY the homepage, then wires all links/buttons to point to the original site.

### Step 0C.1 — Clone homepage with frontend-ui-clone

Use the `Agent` tool to invoke `frontend-ui-clone` for the homepage URL:

```
Agent(
  description: "Clone homepage",
  prompt: "Use the Skill tool to invoke frontend-ui-clone with this URL: [URL]. 
           Wait for it to complete and report the output file path.",
  subagent_type: "general-purpose"
)
```

This produces a single high-fidelity clone HTML (~97% pixel-perfect).

**Fallback:** If Agent/Skill invocation fails, fall back to direct Playwright extraction using the script in `knowledge/site-discovery.md` Phase D.

### Step 0C.2 — Discover all interactive elements on the homepage

Use Playwright on the live page (before or after cloning) to run the **runtime interactive element detection** script from `knowledge/site-discovery.md` Phase A2.

This script detects ALL interactive elements by checking:
- `cursor: pointer` (strongest signal — catches styled `` buttons with no semantic markup)
- ``, ``, ``, ``, `` tags
- ARIA attributes (`role="button"`, `aria-expanded`, `aria-haspopup`, `data-state`)
- `tabindex >= 0`, inline `onclick` handlers

**Output:** A JSON list of every interactive element with:
- Tag, text, href, placeholder
- Signals (why it's interactive)
- Location (nav/footer/body)
- Bounding box (position on page)

This list drives Phase 3 Step 6 (interactivity restoration) — every element in this list gets a corresponding fixup in the converted components.

### Step 0C.3 — Link strategy for Mode C

**ALL internal links point to the original site.** No local routes are created for subpages.

```
Internal links:
  href="/pricing"                    → href="https://original-site.com/pricing"
  href="/about"                      → href="https://original-site.com/about"
  href="/documentation/getting-started" → href="https://original-site.com/documentation/getting-started"

Buttons (dead  with no href):
  Sign in          → Sign in
  Get started      → Get started

External links:
  Keep as-is with target="_blank" rel="noopener noreferrer"

Anchor links (#section):
  Keep as-is (scroll within the page)
```

### Step 0C.4 — Transition to Mode A pipeline

With the single homepage clone file, proceed as **Mode A**:
- Phase 1: Analyze the clone HTML (section mapping)
- Phase 2: CSS decomposition
- Phase 3: React component generation + interactivity + link fixup
- Phase 4: Project scaffolding (single route only: `/`)
- Phase 5: Build verification

**Critical in Phase 3:** When converting links, do NOT use relative paths. Convert ALL internal links to absolute URLs pointing to the original site:
```
href="/pricing"  →  href="https://[original-domain]/pricing"
```

---

## Phase 1 — HTML Analysis & Section Mapping

**Load knowledge:** Read `knowledge/component-detection.md` for section identification rules.

For EACH clone HTML file:

### Step 1 — Read and parse the HTML

Use `Read` to load the clone HTML file. Identify:

1. **The `` block** — Extract the entire contents between `` and `` tags.
   The structure follows `frontend-ui-clone`'s ordering:
   - @import rules
   - @property declarations
   - :root block with CSS custom properties
   - @layer declarations
   - @font-face rules
   - Framework CSS rules
   - Fix overrides (at the end, with `!important`)

2. **The `` metadata** — Extract:
   - `` text
   - `` content
   - `` tags (fonts, favicons, preloads)
   - `` attributes (`lang`, `class`, `data-theme`, etc.)

3. **The `` content** — Everything between `` and ``, excluding `` tags.

### Step 2 — Identify semantic sections

Apply the detection strategy from `knowledge/component-detection.md`:

1. **Scan top-level children** of `` (or the first wrapper `` if body has a single child wrapper)
2. For each top-level element, classify using signals (priority order):
   - HTML5 semantic tags (``, ``, ``, ``)
   - ARIA roles
   - Class name patterns
   - ID attributes
   - Structural position (first = Navbar, last = Footer)
3. Assign a component name to each section (PascalCase)

**Output of this step:** An ordered list of sections with:
```
[
  { name: "Navbar", tag: "nav", startLine: 45, endLine: 92, classes: ["nav", "nav-container"] },
  { name: "Hero", tag: "section", startLine: 93, endLine: 180, classes: ["hero", "hero-section"] },
  { name: "Features", tag: "section", startLine: 181, endLine: 320, classes: ["features-grid"] },
  ...
  { name: "Footer", tag: "footer", startLine: 890, endLine: 960, classes: ["footer", "site-footer"] },
]
```

### Step 3 — Extract link map

Parse all `` in the body:

1. Extract every `href` value
2. Classify each link:
   - **Internal** (same domain as the cloned site): `https://linear.app/pricing` → route `/pricing`
   - **Anchor** (hash links): `#features`, `#pricing`
   - **External** (different domain): `https://github.com/linear`
   - **Mail/tel**: `mailto:`, `tel:`
3. Build a route map for internal links:
   ```
   /pricing  → app/pricing/page.tsx
   /about    → app/about/page.tsx
   /blog     → app/blog/page.tsx (if clone exists, else external link)
   ```

### Step 4 — Cross-page deduplication (Mode B only; Mode C does this in Phase 0C.6)

Compare sections across all clone HTML files:

1. Extract the first section (usually Navbar) and last section (usually Footer) from each file
2. Compare their HTML content (normalize whitespace, ignore active-state classes)
3. If similarity > 85% → mark as shared component
4. Extract the canonical version from the homepage clone
5. Note differences (active nav link, page-specific CTA text) for prop-based variation

---

## Phase 2 — CSS Decomposition

**Load knowledge:** Read `knowledge/css-extraction.md` for CSS splitting rules.

### Step 1 — Detect CSS strategy

If user specified `--css`, use that. Otherwise:

1. **Default → Global CSS** — All CSS stays in `globals.css`. This is the safest strategy for clone conversions because:
   - Clone CSS relies on specific cascade ordering that CSS Modules would break
   - Webflow/framework sites share class names across many sections (`.w-nav`, `.w-button`, `.container`)
   - Splitting CSS incorrectly causes subtle visual regressions
2. **Tailwind** (auto-detected if clone uses Tailwind) — Check for signals:
   - `@property --tw-*` declarations
   - `@layer base, components, utilities`
   - `:root` contains `--tw-*` properties
   - Majority of class names match Tailwind patterns (`flex`, `p-4`, `text-sm`, `bg-*`, etc.)
   - If detected → extract tokens to `tailwind.config.ts`, keep utility classes in JSX
3. **CSS Modules** (`--css modules`) — Only use when explicitly requested. Requires careful class-to-component mapping. See `knowledge/css-extraction.md` for the classification algorithm.

### Step 2 — Extract global CSS

From the `` block, extract these into `globals.css`:

1. All `@import` rules
2. All `@property` declarations
3. The entire `:root { ... }` block (design tokens)
4. All `@layer` declarations
5. All `@font-face` rules
6. Base element selectors (`*`, `html`, `body`, `h1`-`h6`, `p`, `a`, etc.)
7. All `@keyframes` rules
8. The fix overrides block (everything with `!important` at the end)

### Step 3 — Classify remaining CSS rules

For each remaining CSS rule:

1. Parse the selector to extract referenced class names
2. Match class names against the component sections from Phase 1
3. Classify:
   - **Single component match** → that component's CSS module file
   - **Multiple component match** → globals.css (shared utilities section)
   - **No match** → globals.css
4. For `@media` queries containing rules for multiple components → split into separate `@media` blocks

### Step 4 — Tailwind-specific processing (if applicable)

If Tailwind strategy:
1. Extract design tokens from `:root` and map to `tailwind.config.ts`:
   - `--color-*` → `theme.extend.colors`
   - `--font-*` → `theme.extend.fontFamily`
   - `--radius-*` → `theme.extend.borderRadius`
   - `--shadow-*` → `theme.extend.boxShadow`
   - `--space-*` → `theme.extend.spacing`
2. Keep Tailwind utility classes as-is in JSX (`className="flex items-center p-4"`)
3. Move non-utility custom CSS to globals.css

### Step 5 — Design token summary

Output a summary of extracted design tokens:
```
Colors:   12 tokens (--color-bg, --color-text-primary, --color-accent, ...)
Fonts:    2 families (Inter, Playfair Display)
Spacing:  8px grid base
Radii:    4 tokens (--radius-sm: 4px, --radius-md: 8px, ...)
Shadows:  3 tokens
Motion:   2 tokens (--duration-fast: 150ms, --ease-out: cubic-bezier(...))
```

---

## Phase 3 — React Component Generation

**Load knowledge:** Read `knowledge/html-to-jsx.md` for conversion rules.

### Step 1 — HTML → JSX conversion

For each section's HTML fragment, apply all conversion rules from `knowledge/html-to-jsx.md`:

1. **Attribute transforms**: `class` → `className`, `for` → `htmlFor`, etc.
2. **Self-closing tags**: `` → ``, `` → ``, etc.
3. **Inline styles**: `style="..."` → `style={{ camelCase: 'value' }}`
4. **SVG attributes**: `stroke-width` → `strokeWidth`, etc.
5. **Comments**: `` → `{/* */}`
6. **Remove event handlers**: Strip all `on*` attributes

**Validation step:** After conversion, check for common JSX errors:
- Unclosed tags
- Reserved word attributes not converted
- Unescaped `{` or `}` in text content
- Adjacent JSX elements without a wrapper

### Step 2 — Link conversion

Strategy depends on the input mode:

**Mode A (single page):** No sub-routes exist, so internal links stay as plain `` tags:
```
Internal links → text  (relative path, plain )
Anchor links   → text  (keep as-is)
External links → text
```

**Mode B/C (multi-page):** Sub-routes exist, so use Next.js `` for routed pages:
```
Internal links WITH clone → text  (import from next/link)
Internal links WITHOUT clone → text  (plain , add TODO comment)
Anchor links → text  (keep as-is)
External links → text
```

For internal links to pages NOT in the clone/extracted set (Mode B/C):
```tsx
{/* TODO: Clone /blog page and add route */}
Blog
```

In ALL modes, convert absolute URLs to relative paths:
- `https://example.com/pricing` → `/pricing`
- `https://example.com/` → `/`
- `https://example.com/#features` → `/#features`

### Step 3 — Component file creation

For each section, create the component file:

**Shared components** → `components/shared/[Name].tsx`
**Page-specific components** → `components/[page]/[Name].tsx`

Each component file structure:
```tsx
// CSS Modules variant
import styles from './[Name].module.css';

export function [Name]() {
  return (
    [converted JSX]
  );
}
```

Or for Tailwind:
```tsx
export function [Name]() {
  return (
    [converted JSX with Tailwind classes]
  );
}
```

### Step 4 — Shared Navbar with active state (Mode B/C)

If Navbar is a shared component across pages, add `usePathname()` for active link highlighting:

```tsx
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';

export function Navbar() {
  const pathname = usePathname();
  // ... render nav links with active state based on pathname
}
```

### Step 5 — SVG icon extraction

Scan all components for inline SVGs that qualify as icons:
- Width/height ≤ 48px
- Appears 2+ times across components
- Simple path data (` → add `onClick` with `scrollIntoView({ behavior: 'smooth' })`
- Simple and high-impact

**Priority 3 — Accordions / FAQ:**
- Detect repeating question+answer pattern
- Wrap each item with `useState` for expand/collapse
- Add `max-height` transition for smooth animation

**Priority 4 — Tabs:**
- Detect tab menu + tab content panels
- Wrap with `useState` for active tab index
- Show/hide panels based on active state

**Priority 5 — Forms:**
- Detect ``, ``, ``, `` elements
- Add `useState` for form data, `onChange` handlers on inputs
- Add `onSubmit` handler (log to console + show success state)
- Preserve all original styling classes

**Priority 6 — Modals / popups:**
- Detect hidden overlays with `position: fixed`
- Find trigger buttons, wire up `useState` toggle
- Add backdrop click-to-close and close button

**Priority 7 — Carousels / sliders:**
- Detect slider patterns (Webflow `w-slider`, custom carousels)
- Add `useState` for current slide, prev/next buttons
- CSS `transform: translateX` for slide transitions

**For each interactive component:**
1. Add `'use client';` directive at the top
2. Import necessary hooks (`useState`, `useRef`, `useEffect`)
3. Wrap interactive elements with state logic
4. **Preserve ALL original class names and HTML structure** — only add behavior, don't restructure
5. Keep non-interactive components as server components

**P8 — Post-clone fixups (for dangerouslySetInnerHTML components):**

When components use `dangerouslySetInnerHTML`, apply these fixups to the raw HTML string:

1. **className → class:** `dangerouslySetInnerHTML` renders raw HTML, NOT JSX. Must use `class`, `for`, `tabindex`, not `className`, `htmlFor`, `tabIndex`. See `knowledge/html-to-jsx.md` "dangerouslySetInnerHTML Rules".
2. **Dead buttons → links:** Convert `Sign in` to `Sign in`. Convert CTA buttons to links pointing to original site. See `knowledge/interactivity.md` Pattern 10.
3. **Input overlay removal:** Remove typewriter overlay

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [instantX-research](https://github.com/instantX-research)
- **Source:** [instantX-research/skills](https://github.com/instantX-research/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-instantx-research-skills-frontend-reactor
- Seller: https://agentstack.voostack.com/s/instantx-research
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
