feat(screens): Next.js as a Screens app — pages, route handlers, links and redirects
- frameworks/nextjs.ts (split out of react.ts): App Router app/**/page.tsx and Pages Router pages → routes named by path ((group) stripped, [slug] → :slug, [...all] → :all*), bound to the default export; app/**/route.ts exports → METHOD /api/… endpoints referencing their functions; pages/api → ANY; resolve() claims router.push/replace/prefetch, redirect/permanentRedirect and NextResponse.redirect(new URL(…)) into navigates edges via the Expo href readers, against a Next-only route table gated on the app's root
- next-router-synthesizer.ts: <Link href> and internal <a href> → dashed navigates edges from the component (next-link, registeredAt)
- expo-router.ts: href readers exported; matcher accepts :param / :all* segments
- steps.ts: a Next page's own work fires from page load; a Next page makes the project a web app; {status: 201} read off the call site (branch-guards CallSiteText.status) for response rows
- frameworks/package-deps.ts: nested package.json files probed on disk (getAllFiles lists only sources); Express/React/Expo/Nest detectors use it; routing manifest names constant handlers
- tests: nextjs.test.ts (file→route rules, extract, verbs, end to end with Screens and Steps); frameworks.test.ts Next cases moved to the Next resolver
- docs: CHANGELOG, spec §3.12 frameworks paragraph, CLAUDE.md, synthesis doc, plan P4 built, playbook rows for Next / MERN / Nest channels
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
co-authored by
Claude Fable 5
parent
b1f40c57dd
commit
9c6bc23b21
@@ -1516,6 +1516,7 @@ app.get(
|
||||
});
|
||||
|
||||
import { reactResolver } from '../src/resolution/frameworks/react';
|
||||
import { nextjsResolver } from '../src/resolution/frameworks/nextjs';
|
||||
import { svelteResolver } from '../src/resolution/frameworks/svelte';
|
||||
import { astroResolver } from '../src/resolution/frameworks/astro';
|
||||
|
||||
@@ -1555,13 +1556,14 @@ describe('reactResolver.extract — React Router', () => {
|
||||
});
|
||||
|
||||
it('does not treat config files or a nextjs-pages dir as Next.js routes', () => {
|
||||
const cfg = reactResolver.extract!('apps/nextjs-pages/next.config.mjs', 'export default {}');
|
||||
const cfg = nextjsResolver.extract!('apps/nextjs-pages/next.config.mjs', 'export default {}');
|
||||
expect(cfg.nodes.filter((n) => n.kind === 'route')).toHaveLength(0);
|
||||
const vite = reactResolver.extract!('src/pages/vite.config.ts', 'export default {}');
|
||||
const vite = nextjsResolver.extract!('src/pages/vite.config.ts', 'export default {}');
|
||||
expect(vite.nodes.filter((n) => n.kind === 'route')).toHaveLength(0);
|
||||
// a real page still works
|
||||
const page = reactResolver.extract!('src/pages/about.tsx', 'export default function About(){return null}');
|
||||
// a real page still works — and the React resolver leaves it to the Next one
|
||||
const page = nextjsResolver.extract!('src/pages/about.tsx', 'export default function About(){return null}');
|
||||
expect(page.nodes.filter((n) => n.kind === 'route').map((n) => n.name)).toEqual(['/about']);
|
||||
expect(reactResolver.extract!('src/pages/about.tsx', 'export default function About(){return null}').nodes).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user