refactor(app): move site routes into a (frontend) route group
Payload's admin panel ships its own root layout rendering html/body. Next allows multiple root layouts only when no app/layout.tsx exists, so the site's routes move into their own group. Route groups are invisible to routing: every public URL is unchanged, verified against the build's route table. The metadata file conventions deliberately stay at the app/ root. Moving them into the group renamed /icon.png to /icon-4usi79.png (likewise apple-icon and opengraph-image) and dropped /robots.txt altogether, which would have broken the /icon.png cache-control rule, the outputFileTracingIncludes entry for the share card, and robots.txt. darkThemeSafety reads app/globals.css off disk rather than importing it, so it needed its own path fix — a grep for import specifiers misses it, and it fails as an unrunnable suite rather than a failed assertion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017YmbBhr8s7GusjDE12hrZM
This commit is contained in:
1 parent
eb648f3f76
commit
2437ffce42
21 files changed
+57
-26
No files matched your search
@@ -83,9 +83,21 @@ route to `/cms-api` is sufficient and complete. Do not add the exclusion.
|
||||
## File Structure
|
||||
|
||||
**Moved (Task 2)** — `app/*` → `app/(frontend)/*`, unchanged in content:
|
||||
`layout.tsx`, `page.tsx`, `globals.css`, `robots.ts`, `opengraph-image.tsx`,
|
||||
`icon.png`, `apple-icon.png`, `rankings/`, `admissions/`, `compare/`,
|
||||
`schools/`, `school/`, `api/`, `sitemaps/`, `sitemap.xml/`.
|
||||
`layout.tsx`, `page.tsx`, `globals.css`, `rankings/`, `admissions/`,
|
||||
`compare/`, `schools/`, `school/`, `api/`, `sitemaps/`, `sitemap.xml/`.
|
||||
|
||||
**Deliberately NOT moved — they stay at the `app/` root:** `robots.ts`,
|
||||
`opengraph-image.tsx`, `icon.png`, `apple-icon.png`.
|
||||
|
||||
Next.js metadata file conventions only produce stable root URLs at the `app/`
|
||||
root. Inside a route group they are treated as segment-scoped: verified during
|
||||
execution, moving them into `(frontend)` renamed `/icon.png` to
|
||||
`/icon-4usi79.png`, `/apple-icon.png` to `/apple-icon-4usi79.png`,
|
||||
`/opengraph-image` to `/opengraph-image-4usi79`, and dropped `/robots.txt`
|
||||
entirely. That would have broken the `/icon.png` cache-control rule and the
|
||||
`outputFileTracingIncludes['/opengraph-image']` entry in `next.config.mjs`,
|
||||
and silently removed the site's robots.txt. Route handlers (`sitemap.xml/`,
|
||||
`sitemaps/`, `api/`) are unaffected and move normally.
|
||||
|
||||
**Created:**
|
||||
|
||||
@@ -264,20 +276,25 @@ Write down the passing test count. It must be identical at Step 5.
|
||||
|
||||
```bash
|
||||
cd nextjs-app/app && mkdir -p "(frontend)"
|
||||
git mv layout.tsx page.tsx globals.css robots.ts opengraph-image.tsx \
|
||||
icon.png apple-icon.png \
|
||||
git mv layout.tsx page.tsx globals.css \
|
||||
rankings admissions compare schools school api sitemaps sitemap.xml \
|
||||
"(frontend)/"
|
||||
```
|
||||
|
||||
Verify nothing is left behind — `app/` should now contain only `(frontend)`:
|
||||
`robots.ts`, `opengraph-image.tsx`, `icon.png` and `apple-icon.png` stay at the
|
||||
`app/` root — see "Deliberately NOT moved" in the File Structure section above.
|
||||
Moving them silently changes their URLs and drops robots.txt.
|
||||
|
||||
Verify the split — `app/` should now contain `(frontend)` plus exactly the four
|
||||
metadata conventions:
|
||||
|
||||
```bash
|
||||
cd /Users/tudor/projects/school_compare/nextjs-app && ls app
|
||||
cd /Users/tudor/projects/school_compare/nextjs-app && ls -A app
|
||||
```
|
||||
|
||||
If anything else appears, move it too. `git status --short` is the
|
||||
authoritative check: untracked files do not show in `git diff --stat`.
|
||||
Expected: `(frontend)`, `apple-icon.png`, `icon.png`, `opengraph-image.tsx`,
|
||||
`robots.ts`. If a route directory is still there, move it. `git status --short`
|
||||
is the authoritative check: untracked files do not show in `git diff --stat`.
|
||||
|
||||
- [ ] **Step 3: Update the four test imports**
|
||||
|
||||
@@ -304,13 +321,27 @@ import { GET } from '@/app/(frontend)/api/[...path]/route';
|
||||
|
||||
- [ ] **Step 4: Find any other references to the old paths**
|
||||
|
||||
Two searches, because import specifiers are not the only way a file names a
|
||||
path. Quote the `--include` globs or zsh expands them.
|
||||
|
||||
```bash
|
||||
cd /Users/tudor/projects/school_compare && grep -rn "app/layout\|app/page\|@/app/" \
|
||||
--include=*.ts --include=*.tsx --include=*.js --include=*.mjs \
|
||||
cd /Users/tudor/projects/school_compare
|
||||
# 1. Import specifiers
|
||||
grep -rn "app/layout\|app/page\|@/app/" \
|
||||
--include="*.ts" --include="*.tsx" --include="*.js" --include="*.mjs" \
|
||||
nextjs-app --exclude-dir=node_modules --exclude-dir=.next | grep -v "app/(frontend)"
|
||||
|
||||
# 2. Filesystem paths — readFileSync/path.join targets, which search 1 misses.
|
||||
# __tests__/components/darkThemeSafety.test.ts reads app/globals.css this way
|
||||
# and fails to *run* when the path is stale, so it shows as a failed suite
|
||||
# rather than a failed assertion.
|
||||
grep -rn "'app'" nextjs-app/__tests__ --include="*.ts" --include="*.tsx" \
|
||||
| grep -v "(frontend)"
|
||||
```
|
||||
|
||||
Expected: no output. Fix anything that appears.
|
||||
Expected: no output from either. Fix anything that appears — note that
|
||||
`renderSchoolDetail.tsx` names `app/layout.tsx` in a comment, which should be
|
||||
updated for accuracy even though nothing breaks.
|
||||
|
||||
- [ ] **Step 5: Verify tests, types and build**
|
||||
|
||||
@@ -595,7 +626,7 @@ proxy's catch-all."
|
||||
indexed and must not be reachable through search results.
|
||||
|
||||
**Files:**
|
||||
- Modify: `nextjs-app/app/(frontend)/robots.ts`
|
||||
- Modify: `nextjs-app/app/robots.ts`
|
||||
- Modify: `nextjs-app/next.config.mjs`
|
||||
- Modify: `nextjs-app/__tests__/app/nextConfig.test.ts`
|
||||
- Create: `nextjs-app/__tests__/app/robots.test.ts`
|
||||
@@ -609,7 +640,7 @@ indexed and must not be reachable through search results.
|
||||
Create `nextjs-app/__tests__/app/robots.test.ts`:
|
||||
|
||||
```ts
|
||||
import robots from '@/app/(frontend)/robots';
|
||||
import robots from '@/app/robots';
|
||||
|
||||
describe('robots.txt', () => {
|
||||
it('disallows the admin panel and the CMS API', () => {
|
||||
@@ -651,7 +682,7 @@ rule exists.
|
||||
|
||||
- [ ] **Step 3: Add the robots disallow entries**
|
||||
|
||||
In `nextjs-app/app/(frontend)/robots.ts`, change the `disallow` array to:
|
||||
In `nextjs-app/app/robots.ts`, change the `disallow` array to:
|
||||
|
||||
```ts
|
||||
disallow: ['/api/', '/_next/', '/admin/', '/cms-api/'],
|
||||
@@ -1527,7 +1558,7 @@ without a webhook."
|
||||
- Create: `nextjs-app/components/blog/CalloutBlock.tsx` + `.module.css`
|
||||
- Create: `nextjs-app/app/(frontend)/blog/rss.xml/route.ts`
|
||||
- Create: `nextjs-app/app/(frontend)/content-sitemap.xml/route.ts`
|
||||
- Modify: `nextjs-app/app/(frontend)/robots.ts`
|
||||
- Modify: `nextjs-app/app/robots.ts`
|
||||
- Modify: `nextjs-app/lib/jsonld.ts`
|
||||
- Create: `nextjs-app/__tests__/app/blogMetadata.test.ts`
|
||||
- Modify: `e2e/tests/journeys.spec.ts`
|
||||
@@ -2123,7 +2154,7 @@ ${urls.map(({ loc, lastmod }) =>
|
||||
|
||||
- [ ] **Step 9: List both sitemaps in robots.txt**
|
||||
|
||||
In `nextjs-app/app/(frontend)/robots.ts`, change the `sitemap` key to:
|
||||
In `nextjs-app/app/robots.ts`, change the `sitemap` key to:
|
||||
|
||||
```ts
|
||||
sitemap: [absoluteUrl('/sitemap.xml'), absoluteUrl('/content-sitemap.xml')],
|
||||
|
||||
Reference in new issue
Block a user