Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .agents/skills/migrate-to-vinext/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,23 @@ See [references/troubleshooting.md](references/troubleshooting.md) for common mi
| `runtime` / `preferredRegion` | Route segment configs ignored |
| PPR (Partial Prerendering) | Use `"use cache"` directive instead (Next.js 16 approach) |

## Field Learnings (From Real Migrations)

1. Auth/session behavior can regress even when pages appear to load.
- In request-wide auth guards (`proxy.ts` / middleware equivalents), treat vinext static asset paths (`/assets/*`) as internal like `/_next/*`. Redirecting these to sign-in breaks anonymous/public rendering.
- When calling auth APIs server-side, do not rely only on `headers()`. Merge cookie-store cookies into the request headers so RSC/server-action paths consistently see session cookies.
- For any DB-backed auth stack, use persistent/shared storage (not in-memory) and ensure required schema exists before first request. Keep stack-specific details in troubleshooting docs.
2. Avoid server actions for high-frequency client mutations.
- If a UI action creates many records (for example AI parsing into many day/category entries), use one route handler (`/api/...`) batch request instead of looped server actions.
- Reason: server actions trigger RSC replay and layout re-execution; with auth-protected layouts this can surface `NEXT_REDIRECT` noise and UX churn. This pattern also applies to Next.js generally, but often becomes more visible during migration.
3. Be careful with `optimizeDeps.exclude`.
- Excluding broad component libraries can cause ESM/CJS runtime mismatches (for example `react/jsx-runtime` named export errors in dev).
- Prefer default optimization unless there is a proven incompatibility.
4. Route segment `error.tsx` can expose shim/runtime gaps.
- If adding segment error boundaries triggers runtime import errors from vinext shims, remove that segment `error.tsx` and rely on the nearest parent or root error boundary until upstream fix is available.
5. Some dev warnings are plugin/internal noise.
- Example: `<link rel=preload> must have a valid as value` can be emitted by current RSC tooling and may be non-blocking.

## Anti-patterns

- **Do not modify `app/`, `pages/`, or application code.** vinext shims all `next/*` imports — no import rewrites needed.
Expand Down
49 changes: 49 additions & 0 deletions .agents/skills/migrate-to-vinext/references/config-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,55 @@ Nitro auto-detects the platform in most CI/CD environments, so the `NITRO_PRESET
| `appDir` | `string` | project root | Custom base directory for `app/` and `pages/` |
| `rsc` | `boolean` | `true` | Auto-register `@vitejs/plugin-rsc` for App Router |

## Known-Safe Migration Checklist (App Router)

Use this checklist to avoid common real-world regressions during vinext migration.

### 1) Auth guard must bypass vinext assets

If you use request-wide auth (`proxy.ts`), treat `/assets/*` as internal/static just like `/_next/*`.

```ts
function isInternalRequest(request: Request): boolean {
const pathname = new URL(request.url).pathname;
if (pathname.startsWith("/_next/")) return true;
if (pathname.startsWith("/assets/")) return true; // vinext static assets
if (request.headers.has("rsc")) return true;
if (request.headers.has("next-action")) return true;
return false;
}
```

### 2) Prefer API route handlers for high-volume client mutations

Avoid looped server actions for workloads like "AI parsed N entries".

Use:
- one client request to `/api/.../batch`
- server-side validation/auth in the route
- one batch write/update flow

```ts
// client
await fetch("/api/dashboard/work-blocks/batch", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ entries }),
});
```

### 3) Keep dependency optimization defaults unless proven otherwise

Do not broadly add libraries to `optimizeDeps.exclude` unless you have a verified reason.
This can trigger ESM/CJS runtime mismatches in dev.

### 4) Better Auth + SIWE should use persistent/shared DB

For SIWE nonce verification reliability:
- use shared DB-backed auth storage
- ensure Better Auth tables exist (`verification` in particular)
- run explicit bootstrap migration scripts rather than relying on per-request introspection

## vinext deploy flags

| Flag | Description |
Expand Down
12 changes: 12 additions & 0 deletions .agents/skills/migrate-to-vinext/references/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
| `vinext: command not found` | vinext not installed or not in PATH | Install vinext: `npm install vinext`, then run via `npx vinext` or package.json scripts |
| RSC environment crash on dev start | Native Node module (sharp, satori) loaded in RSC env | vinext auto-stubs these in production; in dev, ensure these are only imported in server code behind dynamic `import()` |
| `ASSETS binding not found` | wrangler.jsonc missing assets config | Add `"assets": { "not_found_handling": "none" }` to wrangler.jsonc |
| `NEXT_REDIRECT` during/after server action | Mutation implemented as server action triggers RSC replay + auth-protected layout re-exec | Move high-volume mutations to route handlers (`/api/...`) and batch writes in one request |
| `The requested module '/node_modules/react/jsx-runtime.js' does not provide an export named 'jsx'` | Dependency optimization/shim mismatch (often after `optimizeDeps.exclude` changes) | Remove broad `optimizeDeps.exclude` entries and restart dev with fresh Vite cache |
| Public pages lose CSS/JS when logged out | Request guard redirects vinext assets | Treat `/assets/*` as internal/static in auth guard matcher and bypass auth redirects |

## ESM Conversion Issues

Expand All @@ -34,6 +37,15 @@ Alternatively, convert these files to ESM (`export default` syntax) and keep the
**Cause:** These are Pages Router APIs. They only work in `pages/`, not `app/`.
**Fix:** This is expected Next.js behavior, not a vinext issue.

## Auth + Session Stability (App Router)

- If using `proxy.ts` auth gating, include vinext assets (`/assets/*`) in the internal/public bypass list.
- In server-side auth helpers, merge cookie-store cookies into request headers before calling auth session APIs.
- For Better Auth with SIWE:
- use persistent/shared DB storage
- ensure schema bootstrap includes Better Auth tables (especially `verification`)
- avoid running migration introspection on every request; run explicit bootstrap migrations instead

## Cloudflare Deployment Issues

**Symptom:** Build succeeds but deploy fails with worker size errors.
Expand Down
Loading