Install
$ agentstack add skill-boparaiamrit-skills-by-amrit-nextjs-to-nuxt-migration ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Next.js to Nuxt Migration
Overview
Work module by module. For each module handed to you: analyse the full flow first, verify the backend, create a task plan, then build. Never translate blindly — understand what the module does end-to-end before writing a single line of Vue code.
Core principle: Understand → Map → Plan → Build. In that order. Every time.
The Iron Law
NEVER WRITE CODE BEFORE YOU HAVE:
1. A submodule analysis (what it does, full data flow, all UI actions)
2. A backend verification (which endpoints exist, which are missing)
3. A written task plan (ordered list of what to build/fix)
NEVER DECLARE A MODULE DONE WITHOUT RUNNING THE FEATURE CHECKLIST AGAINST THE SOURCE.
The Root Cause of Incomplete Ports
Claude translates what is visible in JSX — the template structure. It routinely misses:
- Business logic buried inside custom hooks (
useRecipients,useChatContext) - Keyboard shortcuts and
onKeyDownhandlers - Conditional rendering paths for empty state, error state, loading state
useEffectside effects (scroll restoration, focus management, analytics)- Permission/role-based branches (
if (user.role === 'admin')) - Responsive behavior (
useMediaQuery, mobile-specific logic) - Optimistic UI updates and rollback logic
- Debounced/throttled handlers
- Form validation rules (especially cross-field rules)
- URL query param sync (
?page=2&search=foo) - Clipboard, drag-drop, file upload behaviors
- WebSocket/real-time subscriptions inside hooks
refforwarding and imperative handles- Context value shape (partial consumption — only reading 2 of 10 context values)
These are invisible in the template. You MUST read every hook and every handler — not just the JSX.
When to Use
- Porting a Next.js/React app to Nuxt/Vue 3
- Converting PM-built React prototypes (mock/JSON-backed) to production Vue apps
- Building NestJS backend endpoints to replace Next.js API routes
- Converting React Context state to Pinia stores
When NOT to Use
- Migrating between different Vue versions (use
refactoring-safely) - Adding features to an existing Nuxt app (use
full-stack-api-integration) - Auditing the migrated code after porting (use
codebase-conformity)
Multi-Agent Strategy
Choose before starting. Do not change strategy mid-migration.
digraph strategy {
"How many modules?" [shape=diamond];
"1 module" [shape=box];
"2+ modules" [shape=box];
"Sequential — one agent, one module at a time" [shape=box];
"Parallel — spawn one agent per module" [shape=box];
"Modules share state or components?" [shape=diamond];
"Sequential to avoid conflicts" [shape=box];
"Parallel safe — independent codebases" [shape=box];
"How many modules?" -> "1 module";
"How many modules?" -> "2+ modules";
"1 module" -> "Sequential — one agent, one module at a time";
"2+ modules" -> "Modules share state or components?";
"Modules share state or components?" -> "Sequential to avoid conflicts" [label="yes"];
"Modules share state or components?" -> "Parallel safe — independent codebases" [label="no"];
}
Sequential (default — one module handed at a time)
User hands off module → Agent runs Phase -1 through Pass 3 → Reports done → User hands next
Use when:
- Modules share Pinia stores, composables, or service files
- Backend endpoints overlap (same controller)
- You want to review each module before the next starts
Parallel (agent team — agent-team-coordination)
Spawn one agent per module. Each agent receives:
Agent brief per module:
- Module name: {module} ← the user will provide this (e.g. recipients, campaigns, vishing)
- Source path: {react-repo}/ ← Next.js PM prototype repo the user will provide
- Target path: {nuxt-repo}/ ← Production Nuxt frontend repo the user will provide
- Backend path: {nestjs-repo}/ ← NestJS backend repo the user will provide
- Task: Run Phase -1 analysis only. Produce submodule analysis report + task plan. Do NOT write code yet.
- Constraint: Read-only during analysis. Report back before writing anything.
Example (recipients module):
- Module name: recipients
- Source path: C:/path/to/vishing-simulation-platform/
- Target path: C:/path/to/admin.humanfirewall.ai/
- Backend path: C:/path/to/admin-backend.humanfirewall.ai/
When the user gives you a module name and repo paths, substitute them everywhere in this skill. The skill uses {module}, {react-repo}, {nuxt-repo}, {nestjs-repo} as placeholders throughout.
REQUIRED: Analysis-only pass first. Orchestrator reviews all plans before any agent writes code. This prevents agents from creating conflicting service files or duplicate Pinia stores.
NEVER let parallel agents write backend code simultaneously — NestJS module registration and Prisma schema changes conflict.
The Iron Questions (ASK BEFORE STARTING)
STOP. Before translating anything, answer these:
1. Does the existing Nuxt codebase already have this feature/page? (check pages/, components/, services/)
2. What Pinia store manages state for this domain? (check store/ and stores/)
3. Does the backend (NestJS) already have endpoints for this data?
4. Which Axios service file owns this domain? (check services/api/)
5. What layout does this page use? (shadcn.vue, auth.vue, admin.vue, portal.vue)
6. What permissions does this page require? (definePageMeta permission)
7. Are there existing composables for this behavior? (check composables/)
8. Which shadcn-vue component maps to the source React component? (check ~/components/ui/shadcn/ — don't create new ones)
If you cannot answer these from reading the codebase, READ the codebase before translating.
Phase -1: Submodule Analysis (START HERE — EVERY MODULE)
When handed a module (e.g. "recipients", "campaigns", "vishing"), do this before anything else.
Step 1: Understand What the Module Does
READ every file in the source module:
- pages/ → what routes exist?
- components/ → what UI pieces compose it?
- hooks/ → what logic is encapsulated?
- lib/data/ → what JSON operations does it do?
- app/api/ → what backend routes does it call?
Produce a one-paragraph plain-English summary:
"This module allows users to [primary action]. It lists [data],
lets users [create/edit/delete], filters by [fields], and [special behavior].
Data comes from [source]. State is managed by [mechanism]."
Step 2: Map the Full Data Flow
For every data entity in the module, trace it end-to-end:
| Entity | React Source | API Call | NestJS Endpoint | Prisma Model | Nuxt Target |
|--------|-------------|----------|-----------------|--------------|-------------|
| {Module} list | lib/data/{module}.ts readAll() | GET /api/{module} | GET /v1/{module} | {Model} | services/api/{module}.service.ts get{Module}s() |
| Create {module} | lib/data/{module}.ts create() | POST /api/{module} | POST /v1/{module} | {Model} | services/api/{module}.service.ts create{Module}() |
| Bulk delete | lib/data/{module}.ts bulkDelete() | POST /api/{module}/bulk | POST /v1/{module}/bulk-delete | {Model} | services/api/{module}.service.ts bulkDelete{Module}s() |
// Example (recipients):
// | Recipient list | lib/data/recipients.ts readAll() | GET /api/recipients | GET /v1/recipients | Recipient | services/api/recipients.service.ts getRecipients() |
Step 3: Inventory All UI Actions
READ every interactive element in every component of the module.
For each one, document:
| UI Action | Trigger | What it does | State changes | API call | Missing in Nuxt? |
|-----------|---------|-------------|---------------|----------|-----------------|
| Search | type in search box | filters table | searchQuery ref | debounced GET ?search= | ? |
| Select page rows | header checkbox | selects visible rows | selectedRows Set | none | ? |
| Select ALL records | "Select all N" banner | sets selectAll flag | selectAllFlag bool | none — sent with mutation | ? |
| Bulk delete | "Delete selected" button | opens confirm modal | deleteModal open | POST /bulk-delete | ? |
| Export CSV | export button | downloads file | loading state | GET /export | ? |
| Column sort | click column header | re-sorts | sortField, sortDir | GET with sort params | ? |
| Filter by status | status dropdown | filters results | filters ref | GET with status param | ? |
| **Row action: Edit** | row "..." menu → Edit | opens edit modal/page | activeRow ref | GET /:id then PUT /:id | ? |
| **Row action: Delete** | row "..." menu → Delete | opens confirm modal | deleteTarget ref | DELETE /:id | ? |
| **Row action: Duplicate** | row "..." menu → Clone | creates copy | loading state | POST /clone/:id | ? |
| **Row action: View** | row "..." menu → View / row click | opens detail sheet | detailRow ref | GET /:id | ? |
| **Row action: Toggle status** | row "..." menu → Enable/Disable | toggles status inline | row.status | PATCH /:id/status | ? |
| Pagination | page buttons / page size | changes page | page, pageSize | GET with page params | ? |
| Empty state CTA | "Add first X" button | opens create flow | createModal open | none | ? |
| Form submit | submit button | creates/updates record | loading, errors | POST or PUT | ? |
| Form validation | on blur / on submit | shows field errors | errors ref | none | ? |
| Modal close | X button / backdrop | closes modal | modal open = false | none | ? |
Row-level action menus are almost always missing. Every table has a ... dropdown per row — read the source's columns definition or DropdownMenu inside the row renderer to find every action. Do not skip this.
Fill the "Missing in Nuxt?" column by checking the existing Nuxt component.
Step 3b: JSON → Server-Side Behavior Translation
The React/JSON version loads ALL data into memory. The backend has limits. Every "unlimited" React behavior needs a server-side equivalent.
Map every assumption:
| React/JSON Behavior | Why it worked | Server-Side Translation | |---------------------|--------------|------------------------| | readAll() returns every record | JSON file in memory | Paginated API — default page size, never load all | | filter(r => r.status === x) client-side | All data loaded | GET /v1/recipients?status=x server filter | | sort(...) client-side | All data loaded | GET /v1/recipients?sortBy=email&order=asc | | "Select all" → items.map(i => i.id) | All IDs in memory | Two-stage: select page rows + "select all N records" flag | | Instant search as you type | Filter in-memory | Debounced search (300ms) → server query | | Count total from array.length | All records loaded | Backend returns { data: [], total: N } — use total | | CSV export from local array | All data in JS | Backend export endpoint streams the file | | Bulk action on all matching | Filter in memory | Send filter params to backend, backend applies to all |
The "Select All" Pattern — implement exactly this:
Problem: React shows "select all 3 rows on this page" via checkbox.
Backend has 500 records across 50 pages.
Solution: Two-level selection UI
Level 1 — Select page rows (default checkbox behavior):
selectedIds = Set of IDs visible on current page
Level 2 — "Select all N records" banner (appears when all page rows selected):
"All 20 rows on this page are selected. Select all 500 recipients?"
→ sets selectAll = true (a boolean flag, not an ID list)
→ bulk actions send { selectAll: true, filters: currentFilters } to backend
→ backend applies action to all matching records server-side
Never try to load all IDs to the frontend for "select all".
Pagination — always server-side:
// Nuxt composable pattern
const page = ref(1)
const pageSize = ref(20)
const total = ref(0)
const items = ref([])
const fetch = async () => {
const res = await getRecipients({ page: page.value, pageSize: pageSize.value, ...filters })
items.value = res.data
total.value = res.total // always from backend
}
watch([page, pageSize, filters], fetch, { immediate: true })
Step 4: Backend Verification
For every API call identified above:
| Endpoint | Exists in NestJS? | Controller File | Notes |
|----------|------------------|-----------------|-------|
| GET /v1/recipients | ✅ YES | recipients.controller.ts | Has pagination? |
| POST /v1/recipients | ✅ YES | recipients.controller.ts | — |
| POST /v1/recipients/bulk-delete | ❌ NO | — | Must create |
| GET /v1/recipients/export | ❌ NO | — | Must create |
For missing endpoints, note:
- What DTO is needed?
- What Prisma query?
- What permission check?
Step 5: Produce the Task Plan
Only after Steps 1–4 are complete, produce a numbered task list:
## Task Plan: [Module Name]
### Backend (build first — frontend depends on it)
- [ ] B1. Create BulkDeleteRecipientsDto + POST /v1/recipients/bulk-delete endpoint
- [ ] B2. Create GET /v1/recipients/export endpoint (returns CSV stream)
### Frontend — Missing Features (fix existing ported component)
- [ ] F1. Add search with debounce — wire to GET /v1/recipients?search=
- [ ] F2. Add "select all" checkbox — selectedRows Set, bulk action toolbar
- [ ] F3. Add bulk delete flow — confirm modal → B1 endpoint → refetch
- [ ] F4. Add CSV export button → B2 endpoint → browser download
- [ ] F5. Add column sort — sortField/sortDir state → re-query
- [ ] F6. Add status filter dropdown → filters state → re-query
### Frontend — New Pages (not yet ported)
- [ ] F7. Port recipients/[id]/detail page
- [ ] F8. Port recipients/import page
### Verification
- [ ] V1. Every UI action from Step 3 works end-to-end
- [ ] V2. No direct fetch() calls remain — all through service files
- [ ] V3. All backend endpoints return correct data shapes
Present this plan to the user and get approval before writing any code.
Multi-Pass Execution (Run for Every Module)
Each module requires multiple passes. Never declare a module done after one pass.
Pass 1 — Backend wiring (make features work at all)
- Create missing NestJS endpoints
- Wire Nuxt service files to real API
- Replace any remaining JSON/mock reads
- Server-side pagination, filtering, sorting in place
- Row-level actions wired (edit, delete, clone, toggle)
- Bulk actions wired (including "select all N" flag)
Goal: Every feature WORKS. Ugly is acceptable.
Pass 2 — Feature completeness (match source feature-for-feature)
- Re-run Phase 0 feature inventory against the source
- Tick every checkbox — implement any still missing
- Empty state, error state, loading skeleton present
- Form validation matches source rules exactly
- Keyboard shortcuts, debounce, URL param sync
Goal: Nothing missing. No "I'll add that later."
Pass 3 — CSS and visual polish (see "UI Design Patterns" section for rules)
- Large modal → convert to USlideover; wrap body in
- Check slideover padding: content must not touch the edges
- Match font color/size/contrast: headings gray-900, secondary gray-500/muted-foreground
- Metric/stat cards must have gradient backgrounds (see UI Design Patterns)
- Match spacing, typography, color to the production Nuxt design system
- Responsive breakpoints work (mobile/tablet/desktop)
- Loading skeletons match the content shape
- Animations/transitions present where source had them
- Row hover states, selected states, disabled states styled correctly
- Compare component visually against existing Nuxt pages for consistency
Goal: Looks production-grade, consistent with the rest of the app.
Pass 4 — Verification
- Run the feature checklist: every UI action works end-to-end
- Open browser, visit every route in the module
- Trigger every error state (network off, invalid input, empty data)
- Confirm no console errors
- Confirm no direct fetch() calls remain
- Confirm all backend endpoints protected by correct @CheckAbility guards
Goal: Zero regressions, zero
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [boparaiamrit](https://github.com/boparaiamrit)
- **Source:** [boparaiamrit/skills-by-amrit](https://github.com/boparaiamrit/skills-by-amrit)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.