> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiveku.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Retrofitting an Existing Project

> Adding the Shopify integration to a Next.js project that wasn't started in Hiveku — pre-flight compat check, dry-run mode, and alias-aware path rewriting.

## What this is

If you imported an existing Next.js project (from GitHub, ejected from Lovable / v0 / Bolt, copied from a starter) and want to add Shopify commerce to it, the Hiveku scaffolder runs a pre-flight compatibility check first. The check catches the four classes of retrofit pain that silently break on every other AI builder:

1. **Pages Router** projects — Hiveku scaffolds emit App Router code; landing it in `app/` on a Pages Router project means the code is never rendered.
2. **`@/*` → `./*`** alias mappings (no `src/` wrapper) — templates emit to `src/components/...` but the alias resolves to `./components/...`, so imports miss.
3. **Routing collisions** — existing `app/products/[slug]/page.tsx` clashes with template's `app/products/[handle]/page.tsx` (Next.js refuses sibling dynamic segments at the same parent).
4. **Missing Tailwind** — scaffolded components use Tailwind utility classes; without it the storefront renders unstyled.

Catching these before any file is written is what makes Hiveku the only AI builder that retrofits Shopify cleanly into a non-greenfield project.

## How the AI agent uses it

When you ask the agent to "add Shopify to my project," the agent runs the compat check first:

```
GET /api/builder/shopify/[projectId]/scaffold/compat?feature=product-detail-route
```

The response is a structured report:

```json theme={null}
{
  "compatible": true,
  "router": "app",
  "pathAlias": {
    "token": "@/*",
    "mappedTo": "./src/*",
    "pointsIntoSrc": true
  },
  "tailwind": { "present": true, "configPath": "tailwind.config.ts" },
  "typescript": { "present": true, "tsconfigPath": "tsconfig.json" },
  "packageManager": "pnpm",
  "detectedDeps": { "next": "^15.5.0", "react": "^19.0.0" },
  "collisions": [],
  "findings": []
}
```

When the project shape passes, the agent proceeds with scaffolding. When it doesn't, the agent reports the findings and either refuses (hard blockers) or proceeds with explicit caveats (warnings).

## Sample report from a problematic project

A real-world ejected-from-Lovable project might look like:

```json theme={null}
{
  "compatible": false,
  "router": "pages",
  "pathAlias": {
    "token": "@/*",
    "mappedTo": "./*",
    "pointsIntoSrc": false
  },
  "tailwind": { "present": false, "configPath": null },
  ...
  "findings": [
    {
      "severity": "blocker",
      "code": "pages_router_only",
      "message": "This project uses the legacy Pages Router. The Shopify scaffolders only emit App Router code — adopt App Router (the `app/` directory) before scaffolding."
    },
    {
      "severity": "warning",
      "code": "no_tailwind",
      "message": "Tailwind CSS was not detected. Scaffolded components use Tailwind utility classes; without it the storefront will render unstyled..."
    }
  ]
}
```

The AI agent reads the `findings` array, surfaces it in chat as a numbered list, and stops before scaffolding because of the `pages_router_only` blocker.

## Finding codes (for branching logic)

Every finding has a stable `code` string. The agent (or any consumer) can branch on these without parsing the human-readable message:

| Code                                | Severity | Meaning                                           |
| ----------------------------------- | -------- | ------------------------------------------------- |
| `no_next`                           | blocker  | Next.js not in `package.json`                     |
| `pages_router_only`                 | blocker  | `pages/` directory present, no `app/`             |
| `mixed_router`                      | warning  | Both `app/` and `pages/` present                  |
| `unknown_router`                    | warning  | Neither directory exists                          |
| `no_path_alias`                     | warning  | tsconfig has no `paths` map                       |
| `unusual_path_alias`                | warning  | Alias is something other than `@/*`               |
| `no_tailwind`                       | warning  | Tailwind not detected                             |
| `route_collision_exact_path_exists` | warning  | Idempotent skip; existing file blocks the write   |
| `route_collision_parent_locked`     | blocker  | Sibling dynamic segment exists at the same parent |

## Alias-aware path rewriting

This is the silent feature that makes most retrofits succeed. Templates author paths under `src/` (matching greenfield Hiveku's `@/*` → `./src/*` alias). When `analyzeScaffoldCompat` detects the project's alias does **not** point into `src/`, the scaffolder rewrites:

```
src/components/cart/CartContext.tsx  →  components/cart/CartContext.tsx
src/lib/shopify/storefront-client.ts →  lib/shopify/storefront-client.ts
```

So files land where the alias actually resolves to. Imports inside the templates remain `@/components/cart/CartContext` (unchanged) — the alias resolves them correctly because the file landed at the matching path.

`app/` paths are **not** rewritten — Next.js's `app/` directory is convention, not alias-resolved.

<Note>
  If your project uses an alias other than `@/*` (e.g. `~/*` or `#/*`), file paths still land correctly via the rewrite, but template imports remain `@/...` and won't resolve. Compat surfaces this as `unusual_path_alias` warning. The proper fix — parameterizing template imports on the detected alias token — is on the roadmap.
</Note>

## Routing collision detection

For each scaffolder feature, the analyzer computes the routes it would write into `app/` and compares to existing routes:

| Collision type    | Example                                                                                     | Reaction                                                  |
| ----------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| Exact path exists | Template wants `app/cart/page.tsx`, project has it                                          | Idempotent skip (`exact-path-exists` finding, info-grade) |
| Parent locked     | Template wants `app/products/[handle]/page.tsx`, project has `app/products/[slug]/page.tsx` | Hard blocker (`parent-locked` finding)                    |

For locked-parent collisions, the suggestion is concrete:

> Existing route uses `[slug]` at `app/products`. Move scaffold under a different parent (e.g. `app/shop`) or rename the existing dynamic segment to match.

The AI agent quotes this back to the user and offers to either rename the project's existing route or scaffold under an alternate parent.

## Dry-run mode

Every `shopify_scaffold_*` POST also accepts `{ "dryRun": true }`. The response contains the compat report + the file list that **would** land, without writing anything:

```json theme={null}
{
  "ok": true,
  "dryRun": true,
  "compat": { ... },
  "wouldWrite": [
    "src/lib/shopify/storefront-client.ts",
    "app/products/page.tsx",
    "app/products/[handle]/page.tsx",
    "app/cart/page.tsx",
    ...
  ],
  "wouldSkip": [
    "src/components/cart/CartContext.tsx"
  ],
  "needsLayoutWrapper": true
}
```

This is useful for "show me what would change before I let you commit." The AI agent can run dry-run, narrate the plan, and only execute when the user approves.

## Recommended retrofit playbook

<Steps>
  <Step title="Connect Shopify">
    `/dashboard/commerce/settings/shopify`. The connection is account-scoped, not project-scoped — it doesn't touch your project files.
  </Step>

  <Step title="Run the AI agent's compat check">
    Prompt: "Check if my project can support Shopify."

    The agent calls `shopify_scaffold_compat_check?feature=product-detail-route` and quotes the findings back to you.
  </Step>

  <Step title="Fix any blockers">
    If you're on Pages Router, migrate to App Router first (Next.js has [a codemod for this](https://nextjs.org/docs/app/building-your-application/upgrading/from-vite#step-2-create-a-new-nextjs-project)). If you have a routing collision, rename one of the routes.
  </Step>

  <Step title="Optionally dry-run">
    Prompt: "Show me what files you'd write before doing it." The agent runs the scaffold with `dryRun: true` and reports.
  </Step>

  <Step title="Scaffold for real">
    Prompt: "Build the shop." The agent writes the files. If `needsLayoutWrapper: true` was returned, the agent edits your `app/layout.tsx` to wrap children in `<CartProvider>`.
  </Step>

  <Step title="Deploy and verify">
    Push to a preview environment. Visit `/products` and `/products/[handle]`. View-source confirms JSON-LD on first byte.
  </Step>
</Steps>

## Why this matters

For a Hiveku-native project, retrofit is essentially zero-friction — every assumption holds and the scaffolder lands clean. For a project ejected from elsewhere, the compat check turns "your Shopify integration silently broke at deploy time" into "the agent told me about the path-alias mismatch in chat and rewrote the file paths to match."

This is the single highest-value gap closing for the "I have an existing Next.js project" persona.

## What we haven't shipped (Phase 2)

* **Parameterized template imports** for non-`@/*` aliases (so `~/*` projects get `~/components/...` imports).
* **AST-based layout-wrapper auto-injection** (the agent edits `app/layout.tsx` manually today).
* **Tailwind config injection** (auto-add `@tailwindcss/postcss` to PostCSS config when missing).
* **Pages Router fallback templates** — currently we refuse instead of generating Pages Router code.

## What's next

<CardGroup cols={2}>
  <Card title="Storefront scaffolding" icon="hammer" href="/integrations/shopify/storefront">
    What lands when compat passes.
  </Card>

  <Card title="Connecting Shopify" icon="plug" href="/integrations/shopify/connecting">
    OAuth flow + multi-shop setup.
  </Card>
</CardGroup>
