// Auto-generated from src/ai-service/skills/system/third-party-migration/SKILL.md
// Do not edit directly - edit the .md file instead
export const content = `---
name: third-party-migration
description: |
  Migrate a third-party app (Replit, Lovable, v0, or similar) into a Superblocks 3.0 full-stack app.
  Load when the user asks to migrate, import, or port an external app — or when the source tree contains hallmarks of a supported platform (\`replit.md\` / \`.replit\`, \`src/integrations/supabase/\`, \`supabase/functions/\`, \`lovable-tagger\`, an \`app/\` directory with \`next.config.*\` and \`"use client"\` / \`"use server"\` directives, etc.) and the user wants it turned into a Superblocks app.
readOnly: true
metadata:
  author: superblocks
  version: "1.0"
---

# Third-Party App → Superblocks 3.0 Migration

Port a user-provided external app into the Superblocks fullstack app you are running inside (template: \`app-fullstack\`). The source tree is **read-only material**. All edits land in the target app under \`server/\` and \`client/\`.

This file is the migration framework. **Per-platform mapping rules live in sibling files** — load the right one before you start mapping.

## Identify the source platform

Match the source tree against these signals, then read the matching reference file in this folder. Read it once, up-front — it tells you what shapes to look for and how each maps to Superblocks.

- **Replit** — \`replit.md\`, \`.replit\`, \`artifacts/\`, an Express server with an Orval-generated client. → load \`replit.md\`.
- **Lovable** — \`src/integrations/supabase/client.ts\`, \`supabase/config.toml\`, \`supabase/functions/\`, \`supabase/migrations/\`, \`lovable-tagger\` in \`vite.config.ts\`. → load \`lovable.md\`.
- **v0** — \`app/<segment>/page.tsx\` (Next.js App Router) plus \`next.config.{js,mjs,ts}\` and \`next\` in \`package.json\`, files with \`"use client"\` / \`"use server"\` directives, \`next/link\` / \`next/navigation\` imports, \`components/ui/\` with shadcn primitives. → load \`v0.md\`.
- **Ambiguous or neither** — stop and ask the user which platform the source came from. Do not guess. It is possible that it is No Platform. In this case, follow the general guidelines in this document and ask user questions for any ambiguity.

The framework below applies to every platform; the platform file fills in the source-specific mapping.

## Target layout

The app you are running inside looks like this. Do not invent new top-level directories.

\`\`\`
client/
  App.tsx           — root with <AppProvider> + <Outlet />
  router.tsx        — react-router v7 data mode (\`createBrowserRouter\`); see Router shape below
  index.css         — Tailwind v4 + theme tokens
  hooks/
    useApi.ts       — typed wrapper around useTypedApi<ApiRegistry>
    useApiData.ts   — typed wrapper around useTypedApiData<ApiRegistry>
  lib/executeApi.ts — non-React typed executeApi
  pages/<Name>/index.tsx
  components/ui/    — shadcn primitives (do not modify)
server/
  apis/
    index.ts        — registry: \`const apis = { ApiName: ... } as const;\`
    <ApiName>/api.ts
\`\`\`

## Universal mapping (applies to every source)

These hold regardless of source platform. Per-platform specifics layer on top.

- APIs are addressed by \`name\` via the registry — there is no URL path. Within \`api()\`:
  - All inputs (whatever shape the source had — body, query, params, function args) → one unified \`input\` Zod schema; destructure inside \`run(ctx, { ... })\`.
  - The handler's response → \`return { ... }\` from \`run\`. The \`output\` schema validates it automatically; do not \`safeParse\` by hand.
  - Auth → \`ctx.user\` (\`userId\`, \`email\`, \`name\`, \`groups\`, \`customClaims\`). Auth is platform-managed; drop the source's auth flows entirely.
  - Errors → throw the \`SdkError\` subtypes the sdk-api README documents (\`InputValidationError\`, \`OutputValidationError\`, \`IntegrationError\`, \`ExecutionError\`). Never invent error classes or return HTTP status codes.
  - DB clients (\`pg\`, \`knex\`, \`prisma\`, Drizzle, \`supabase.from(...)\`) → declare in \`integrations: { db: postgres(DB_INTEGRATION_ID) }\` and call \`ctx.integrations.db.query(sql, ZodSchema, params, { label: "..." })\` / \`.execute(...)\`. Parameterized SQL only. Hold integration UUIDs in module-level \`const\`s, not literals scattered through \`run\`.
  - External HTTP (\`axios\`, \`fetch\`, third-party SDKs) → declared integration + \`ctx.integrations.<name>.apiRequest({ method, path, body }, { response: ZodSchema })\`.
  - \`process.env.*\` / \`import.meta.env.*\` / \`Deno.env.get(...)\` → \`ctx.env\`. Logging → \`ctx.log.info/warn/error/debug(msg, data?)\`.
  - Server bootstrapping (\`app.listen\`, CORS, route grouping, middleware setup, \`Deno.serve\`) → drop entirely. The platform handles it.
- **Each frontend page → one Superblocks page** at \`client/pages/<Name>/index.tsx\`, wired into \`client/router.tsx\`.
- **Each backend data source (DB, REST client, S3, ...) → one Superblocks integration** referenced by UUID. Credentials live on the integration, never in code.

### Router shape (\`client/router.tsx\`)

The editor parses this file statically to build the page list and route table. **Use one of the supported page-component bindings — anything else silently drops every route and the editor shows a "404 / route has been deleted" overlay.**

Supported page bindings (mix freely):

\`\`\`tsx
// 1. Inline lazy on the route object (preferred — matches the template):
{ path: "about", lazy: () => import("./pages/About/index.tsx").then(m => ({ Component: m.default })) }

// 2. Static default import + Component / element:
import About from "./pages/About/index.tsx";
{ path: "about", Component: About }
{ path: "about", element: <About /> }

// 3. Top-level \`const\` bound to React.lazy + Component / element:
const About = lazy(() => import("./pages/About/index.tsx"));
{ path: "about", Component: About }
\`\`\`

Do **not**: assign \`Component\` / \`element\` to identifiers bound by anything other than a static import or \`lazy(() => import("..."))\` (no IIFEs, no helper wrappers, no conditional \`lazy(...)\`, no objects whose keys are computed from a loop). The parser only resolves the shapes above.

## Authoritative references (read just-in-time, not up front)

- \`node_modules/@superblocksteam/sdk-api/README.md\` and \`src/index.ts\` — the server \`api()\` contract and the full list of factory names. **Never invent factory names.** If a required file is missing, mark the affected checklist item \`failed\` with the missing path as the reason.
- Per-integration READMEs under \`node_modules/@superblocksteam/sdk-api/src/integrations/<kind>/\` — read once, when you first emit an API that uses that integration.
- \`skills/system/superblocks-frontend/SKILL.md\` — the client contract (\`useApi\` / \`useApiData\` / \`executeApi\` from \`@superblocksteam/library\`).

> ⚠️ **Never** load \`skills/system/superblocks-api/SKILL.md\`. It describes a different, block-based API pattern that is incompatible with the fullstack template's \`sdk-api\`. Mixing them produces code that does not compile.

## Non-negotiables

1. **Track everything in the checklist.** The **first tool call after exiting plan mode** or **during build mode, before building** is \`build_manageChecklist\` to seed. Before every per-item edit, \`update <itemId> in_progress\`; after, \`update <itemId> completed\` (or \`failed\` with a concrete \`failureReason\`). If you are about to write code and the checklist is empty, stale, or missing the item you are working on, **stop and fix the checklist first** — the orchestration depends on it. Free-text status reports are not a substitute.
2. **Discover before you edit.** Inventory routes, pages, data sources, env vars, _and visual surface_ (theme tokens, \`index.css\`, custom CSS, font setup, layout shells) across the entire source tree before writing any code. The platform file tells you what shapes to look for.
3. **Ask before guessing.** Multiple integrations of the same kind, missing integrations, unsupported data sources, or any platform-specific ambiguity → stop and \`askMultiChoice\`. Never pick for the user. The platform file lists ambiguities specific to that source.
4. **Preserve visual identity.** The migrated app must look and feel like the source. Carry over Tailwind config, shadcn theme tokens, \`index.css\` / \`globals.css\`, custom CSS modules, fonts, spacing, color palette, and layout shells (header/sidebar/grid). shadcn/ui components stay as-is. Do **not** redesign, restyle, or "clean up" while porting — visual regressions are bugs, not improvements. If the user wants a redesign, that is a separate task after migration.
5. **Never copy secrets.** DSN strings, API keys, anon/service-role keys, JWT secrets, env-var lookups for credentials — none move into the target tree. Integration UUIDs replace them. Surface every leaked secret you find (especially client-side \`VITE_*\` / \`NEXT_PUBLIC_*\` keys) in the discovery summary so the user can rotate them.
6. **No \`// TODO\`s.** Anything you can't finish deterministically becomes a \`failed\` checklist item with a concrete \`failureReason\`.
7. **Don't scaffold.** If \`server/apis/index.ts\` or \`client/router.tsx\` doesn't already exist, you're in the wrong app — stop and surface this.
8. **Don't fabricate a backend.** If the source is genuinely frontend-only, the migrated app should also be frontend-only. Don't invent APIs to "complete" the architecture.

## Workflow

1. **Locate the source.** If the user gave a path, use it. Otherwise look in the working tree for the platform signals listed above. If ambiguous, ask.
2. **Load the platform guide.** Read \`replit.md\`, \`lovable.md\`, or \`v0.md\` based on what you found. Do not start mapping before you've read it — it documents the source's shape and how each piece translates.
3. **Inventory.** Following the platform guide's discovery checklist, enumerate every route/handler, page, data source, env var, secret, and visual asset in the source tree. Surface a one-paragraph summary plus an itemized list of integrations and unsupported features before writing anything. If the source has bespoke styling, seed a \`setup_theme\` checklist item to port it.
4. **Resolve integrations.** For each data source kind: call \`searchIntegrations\` (filter by \`type\`). One match → bind it. Multiple → ask the user which. Zero → ask whether to create one; if yes, use \`listAvailableIntegrationTypes\` (if needed) and \`openIntegrationSetup\`, then ask the user explicitly whether they saved or cancelled before re-searching. Resolution is **blocking** — the checklist cannot be seeded until every kind maps to a UUID, is explicitly deferred, or has been confirmed unsupported.
5. **Seed the checklist** via \`build_manageChecklist\`. One \`api_<ApiName>\` per backend interaction, one \`frontend_<PageName>\` per page, plus \`setup_router\`, \`setup_registry\`, \`setup_cleanup\`, and any \`setup_theme\` / \`setup_storage\` / \`unsupported_<feature>\` items the platform guide tells you to add. Print the count as a sanity check; if it looks wrong, re-check discovery.
6. **Execute.** Every item follows the same ritual — no exceptions:
   - **Before touching files:** \`build_manageChecklist update <itemId> in_progress\`.
   - **Emit / edit the files** for that item.
   - **After the edit lands:** \`build_manageChecklist update <itemId> completed\` (or \`failed\` with a concrete \`failureReason\`).
   - You are not done with an item until its checklist entry has moved to a terminal state. Do not batch updates at the end; update as you go.
   - **For parallelizable work:** call \`spawnCodingSubagents\` with batches of tasks. Each batch's \`instructions\` names exact \`itemId\`s, includes the integration-UUID map and source path, any platform-specific context the sub-agent needs (e.g. RLS-replacement clauses for Lovable), and tells the sub-agent to follow the same \`in_progress\` → \`completed\`/\`failed\` ritual for every item it owns.
   - \`spawnCodingSubagents\` **must be the only tool call in that turn.** It blocks until every sub-agent finishes; there is no "while waiting" from your perspective. Other tool calls in the same turn race on the shared checklist and corrupt state. After it returns, read the checklist and handle \`failed\` items sequentially. If the tool itself errors, surface it and fall back to sequential — or fail the affected items with \`sub-agent orchestration failed: <error>\`.

## When emitting code

- **Server.** Default-export one \`api({ name, integrations, input, output, run })\` from \`@superblocksteam/sdk-api\`. The \`name\` and the registry key in \`server/apis/index.ts\` must equal \`<ApiName>\` verbatim — the client calls \`useApi("<ApiName>")\` by that exact string. Preserve the external response shape exactly so the migrated frontend keeps working. Use parameterized SQL only (\`$N\`); zero string interpolations. Throw the error classes the sdk-api README documents instead of returning HTTP status codes.
- **Client.** Replace the source's data hooks with \`useApiData\` (reads) or \`useApi\` (mutations) keyed by \`<ApiName>\`. **Import the typed wrappers from the template, not the library directly:** \`import { useApi } from "@/hooks/useApi.js"\`, \`import { useApiData } from "@/hooks/useApiData.js"\`, \`import { executeApi } from "@/lib/executeApi.js"\`. They give compile-time inference from \`ApiRegistry\`. Drop the source's generated client packages, \`QueryClientProvider\`, base-URL or auth-token getters, and any auth-context plumbing — Superblocks handles all of that. shadcn/form + react-hook-form + zod stays. Follow the loading-state guidance in \`superblocks-frontend/SKILL.md\`.
- **ESM imports.** Every relative import in emitted code uses an explicit \`.js\` extension (\`./api.js\`, \`../hooks/useApi.js\`) — even though the source is \`.ts\`. The template is ESM; bare specifiers fail at runtime.
- **Theme port.** When carrying over the source's theme, copy the existing color values **as-is** into \`client/index.css\`'s \`:root\` block. HSL values written \`hsl(222 47% 11%)\` (CSS Color Level 4 space-separated form) work directly with the \`@theme inline\` mapping in Tailwind v4. **Do not convert to OKLCH** unless the source already uses OKLCH — converting introduces drift and is a common visual-regression source.
- **Visual fidelity.** JSX structure, Tailwind classes, shadcn variants, custom CSS, theme tokens, fonts, and layout containers must transfer over **unchanged** from the source page. The only things that change in a page port are the data hooks, the auth touchpoints, and the router primitives. Do not "improve" markup, swap class names, or substitute components. If the diff between source and target page goes beyond data + auth + routing, you are over-editing — back out the cosmetic changes.
- **Sub-agents must not** call \`searchIntegrations\`, \`openIntegrationSetup\`, or any integration-resolution tool. If they hit a kind missing from the map, fail the item with \`unresolved integration kind: <kind>\` and let the main agent handle it on return.

## Done

Stop only when every checklist item is \`completed\` or \`failed\`. Report the counts plus any platform-specific findings the per-platform guide asks you to surface (e.g. leaked secrets, replaced RLS policies, unsupported realtime features). Do not claim success — defer verification to the user running the app.
`;
//# sourceMappingURL=skill.generated.js.map