Skip to content

Vail Platform Foundation: Convert Static Site to Next.js App Router#3

Merged
harbourviewcompany-create merged 33 commits into
mainfrom
feature/vail-platform-foundation
May 22, 2026
Merged

Vail Platform Foundation: Convert Static Site to Next.js App Router#3
harbourviewcompany-create merged 33 commits into
mainfrom
feature/vail-platform-foundation

Conversation

@harbourviewcompany-create
Copy link
Copy Markdown
Owner

@harbourviewcompany-create harbourviewcompany-create commented May 13, 2026

Status

HOLD pending live verification.

Summary

Converts the Vail Renovations repo from a static Netlify HTML foundation into a Next.js App Router platform foundation with TypeScript, Tailwind configuration, public route placeholders, shared layout components, mobile CTAs, legacy route redirects and a platform foundation report.

What changed

  • Added Next.js App Router platform files.
  • Added TypeScript, Tailwind, PostCSS and ESLint config.
  • Added public layout, header, footer and mobile sticky CTA components.
  • Added homepage foundation preserving the positioning: “Renovation help without the runaround.”
  • Added route placeholders for services, project request, scope builder, booking, callback, contact, privacy and terms.
  • Added service detail placeholders.
  • Updated Netlify config for Next.js build and @netlify/plugin-nextjs.
  • Replaced static HTML checker with platform-foundation checks.
  • Updated README and sitemap.
  • Added docs/control/VAIL_PLATFORM_FOUNDATION_REPORT.md.

Intentionally not built

  • CRM
  • Database
  • Auth
  • Lead creation
  • Project Starter functionality
  • Scope Builder functionality
  • Callback submission
  • Photo uploads
  • Private storage
  • Notifications
  • Analytics
  • Estimate workflow
  • Native booking engine

Verification

Not run in this environment. The implementation environment could not install dependencies or run npm run typecheck, npm run lint, or npm run build.

Required before merge:

npm install
npm run check
npm run typecheck
npm run lint
npm run build

GO/HOLD

HOLD until dependency install, typecheck, lint and build pass in CI or a local environment with npm registry access.

First blocker if HOLD

No package lock was generated and verification commands were not executed in this environment.


Open in Devin Review

Summary by CodeRabbit

Release Notes

  • New Features

    • Rebuilt homepage with marketing layout and service card grid
    • Added comprehensive site navigation header and footer
    • Created new pages: Services, How It Works, Project Request, Scope Builder, Book Call, Callback, Contact, Privacy, and Terms
    • Implemented dynamic service detail pages
    • Added fixed mobile CTA bar for improved mobile navigation
    • Enabled legacy URL redirects for existing links
  • Documentation

    • Updated README with platform architecture and route listing
    • Added platform foundation report
  • Chores

    • Updated sitemap with new routes

Review Change Stack

@netlify
Copy link
Copy Markdown

netlify Bot commented May 13, 2026

Deploy Preview for wurxx failed.

Name Link
🔨 Latest commit 19a40cd
🔍 Latest deploy log https://app.netlify.com/projects/wurxx/deploys/6a04784d5f17ce0008604c3c

@netlify
Copy link
Copy Markdown

netlify Bot commented May 13, 2026

Deploy Preview for wurx-can failed.

Name Link
🔨 Latest commit 19a40cd
🔍 Latest deploy log https://app.netlify.com/projects/wurx-can/deploys/6a04784d6db659000973de33

@netlify
Copy link
Copy Markdown

netlify Bot commented May 13, 2026

Deploy Preview for wurx-otta failed.

Name Link
🔨 Latest commit 19a40cd
🔍 Latest deploy log https://app.netlify.com/projects/wurx-otta/deploys/6a04784d5f17ce0008604c38

@harbourviewcompany-create harbourviewcompany-create marked this pull request as ready for review May 21, 2026 10:51
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 potential issues.

Open in Devin Review

Comment thread sitemap.xml
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Static sitemap.xml will diverge from actual routes over time

The sitemap.xml is a manually maintained static file rather than being generated by Next.js's built-in sitemap support (via app/sitemap.ts). This means any future route additions will require manual sitemap updates, creating a risk of drift. For this foundation PR, the sitemap matches all declared routes correctly. A future ticket could migrate to the Next.js metadata API for automatic sitemap generation.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread scripts/check-site.js
Comment on lines +91 to +93
for (const term of bannedLegacyTerms) {
if (body.includes(term)) {
failures.push(`${file} contains banned legacy term: ${term}`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Banned-term check regresses from case-insensitive to case-sensitive matching

The old check-site.js used case-insensitive regex patterns (/SummitLine/i, /Roofing/i, etc.) to catch legacy terms regardless of casing. The new code replaces these with String.includes(term), which is case-sensitive. This means variants like "roofing", "ROOFING", "summitline", or "Roof Repair" will no longer be caught, weakening the safety guardrail against legacy branding leaking into the codebase.

Suggested change
for (const term of bannedLegacyTerms) {
if (body.includes(term)) {
failures.push(`${file} contains banned legacy term: ${term}`);
for (const term of bannedLegacyTerms) {
if (body.toLowerCase().includes(term.toLowerCase())) {
failures.push(`${file} contains banned legacy term: ${term}`);
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +30 to +51
<details className="group relative lg:hidden">
<summary className="list-none rounded-full border border-forest/25 px-4 py-2 text-sm font-semibold text-forest marker:hidden">
Menu
</summary>
<div className="absolute right-0 mt-3 w-[min(88vw,22rem)] rounded-3xl border border-ink/10 bg-white p-4 shadow-soft">
<div className="grid gap-2">
{publicRoutes.map((route) => (
<Link key={route.href} href={route.href} className="rounded-2xl px-4 py-3 text-sm font-semibold text-ink hover:bg-oatmeal">
{route.label}
</Link>
))}
<div className="mt-2 grid grid-cols-2 gap-2">
<Link href="/project-request" className="rounded-2xl bg-forest px-4 py-3 text-center text-sm font-semibold text-white">
Start Project
</Link>
<Link href="/book-call" className="rounded-2xl border border-forest/25 px-4 py-3 text-center text-sm font-semibold text-forest">
Book Call
</Link>
</div>
</div>
</div>
</details>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Mobile menu uses

Details without close-on-navigate behavior

The SiteHeader at components/site-header.tsx:30-51 uses a native <details>/<summary> element for the mobile menu. Since this is a server component (no "use client" directive), there's no JavaScript to close the menu when a user navigates to a new route via a <Link>. In Next.js App Router with client-side navigation, the <details open> attribute will persist across navigations, meaning the mobile menu stays open after clicking a link. This is a UX issue rather than a bug — it works functionally but feels broken on mobile. A future ticket should either add a client component wrapper or use a different disclosure pattern.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread scripts/check-site.js
Comment on lines +86 to 96
for (const file of fs.readdirSync(root, { recursive: true }).filter((name) => typeof name === "string" && /\.(ts|tsx|js|html|md|toml)$/.test(name))) {
if (file.includes("node_modules") || file.includes(".next") || file === "scripts/check-site.js") {
continue;
}
const body = read(file);
for (const term of bannedLegacyTerms) {
if (body.includes(term)) {
failures.push(`${file} contains banned legacy term: ${term}`);
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Legacy static HTML files remain in the repo and are scanned by check-site.js

The old static HTML files (index.html, start-a-project.html, fix-list-builder.html, etc.) were not removed in this PR. The new check-site.js scans all .html files recursively for banned legacy terms via fs.readdirSync(root, { recursive: true }). Currently none of these old HTML files contain the banned terms (verified by grep), so the check passes. However, leaving stale HTML files alongside the Next.js app is confusing — they are superseded by Next.js routes and redirects but will still be served as static assets by Next.js if placed in public/ (they aren't, but the ambiguity is worth noting). The foundation report at docs/control/VAIL_PLATFORM_FOUNDATION_REPORT.md:150 acknowledges this explicitly.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread next.config.ts
Comment on lines +6 to +37
return [
{
source: "/start-a-project",
destination: "/project-request",
permanent: true
},
{
source: "/fix-list-builder",
destination: "/scope-builder",
permanent: true
},
{
source: "/maintenance-plans",
destination: "/services/repairs-refreshes",
permanent: false
},
{
source: "/inspection-report-repairs",
destination: "/services/pre-sale-improvements",
permanent: false
},
{
source: "/renovations",
destination: "/services",
permanent: true
},
{
source: "/thank-you",
destination: "/contact",
permanent: false
}
];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Redirect permanence is inconsistent across legacy routes

In next.config.ts:5-37, some legacy redirects use permanent: true (301) while others use permanent: false (307). Specifically /start-a-project, /fix-list-builder, and /renovations are permanent, while /maintenance-plans, /inspection-report-repairs, and /thank-you are temporary. This appears intentional — the first three are straightforward renamed routes, while the latter three map legacy concepts to different service categories where the mapping may change. Not a bug, but worth confirming the intent since permanent redirects are cached aggressively by browsers and search engines.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

This PR migrates a static Netlify HTML site to a Next.js App Router platform foundation. It establishes build and styling infrastructure, introduces route definitions, builds a reusable component library, creates placeholder pages across multiple routes, and implements dynamic service routes with proper metadata generation.

Changes

Next.js App Router Platform Foundation

Layer / File(s) Summary
Build Configuration & Dependencies
next.config.ts, tailwind.config.ts, tsconfig.json, postcss.config.js, eslint.config.mjs, next-env.d.ts, package.json, netlify.toml
Next.js, TypeScript, Tailwind CSS, ESLint, and PostCSS configs established; package.json updated with Next/React dependencies and npm scripts (dev, build, start, typecheck, lint, check); netlify.toml configured for npm run build and .next publish with @netlify/plugin-nextjs plugin.
Global Styles & Root Layout
app/globals.css, app/layout.tsx
Tailwind directives and baseline CSS variables, typography, and layout resets; root layout wraps all pages with SiteHeader, passed children, SiteFooter, and MobileCtaBar for consistent page structure.
Route & Navigation Data
lib/routes.ts
Three centralized route lists: publicRoutes (top-level nav), serviceRoutes (service objects with href/title/description), placeholderRoutes (placeholder path strings) used throughout the site for navigation generation.
Reusable UI Components
components/placeholder-page.tsx, components/site-header.tsx, components/site-footer.tsx, components/mobile-cta-bar.tsx
PlaceholderPage component with configurable eyebrow/title/body/CTAs used by eight pages; SiteHeader with sticky navigation and responsive mobile dropdown; SiteFooter listing public and service routes; MobileCtaBar with fixed bottom CTA buttons.
Home Page & Landing
app/page.tsx
Marketing homepage with hero section, project steps preview, features grid, dynamic services grid (mapped from serviceRoutes), and shareable-by-design CTA section linking to project-request, book-call, and scope-builder routes.
Placeholder Route Pages
app/book-call/page.tsx, app/callback/page.tsx, app/contact/page.tsx, app/how-it-works/page.tsx, app/privacy/page.tsx, app/project-request/page.tsx, app/scope-builder/page.tsx, app/terms/page.tsx
Eight placeholder pages with metadata and PlaceholderPage rendering; each exports page title/description and renders consistent CTA navigation to related routes (e.g., book-call links to callback and project-request).
Services Listing & Dynamic Routes
app/services/page.tsx, app/services/[slug]/page.tsx
Services landing page showing grid of all service routes from serviceRoutes; dynamic [slug] page with generateStaticParams (extracting slugs from hrefs), generateMetadata (resolving service by slug), and ServicePage rendering with notFound() fallback for unmatched slugs.
Validation Script & Documentation
scripts/check-site.js, docs/control/VAIL_PLATFORM_FOUNDATION_REPORT.md, README.md, sitemap.xml
Updated check-site.js to validate Next.js config files, required npm scripts, dependencies, netlify.toml settings, and scans for banned legacy terms; platform foundation report documenting scope/status/deferrals; README rewritten for Next.js foundation with implemented features and deploy instructions; sitemap updated with new service and page routes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 From static HTML to Next.js we hop,
Routes now dynamic, the builds don't stop!
Placeholders ready for features ahead,
TypeScript strict, Tailwind spread red.
Vail's platform foundation—a verdant bed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Vail Platform Foundation: Convert Static Site to Next.js App Router' clearly and accurately summarizes the main objective of the changeset: migrating from static HTML to a Next.js application with App Router architecture.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/site-footer.tsx`:
- Around line 23-24: Replace the two hardcoded <Link> entries with links sourced
from the centralized route registry in lib/routes.ts: import the privacy and
terms route entries (e.g., constants or objects named like privacyRoute /
termsRoute or lookup by key) and render <Link href={privacyRoute.path}
...>Privacy</Link> and <Link href={termsRoute.path} ...>Terms</Link> (or use the
registry lookup method used elsewhere) so the footer uses the canonical route
definitions instead of hardcoded paths.

In `@lib/routes.ts`:
- Around line 42-50: The placeholderRoutes array is missing the "/how-it-works"
entry; update the exported constant placeholderRoutes to include "/how-it-works"
alongside the other strings so the route registry matches the placeholder page
set in the migration (modify the placeholderRoutes declaration to add the
"/how-it-works" string to the tuple).

In `@package.json`:
- Around line 13-30: package.json lists pinned dependencies/devDependencies but
the repository is missing a lockfile; run a fresh install to generate and commit
the lockfile (e.g., run npm install to produce package-lock.json or yarn install
to produce yarn.lock), ensure the generated lockfile is added to the repo
alongside package.json so transitive dependencies are pinned and then include
the lockfile in the commit that updates the "dependencies"/"devDependencies".
- Line 11: The "check" npm script currently runs "node scripts/check-site.js &&
npm run typecheck && npm run build" but omits linting; update the "check" script
in package.json to include the lint step (e.g., add "&& npm run lint" at the
appropriate place) so that lint runs as part of the main validation gate, and
confirm the "lint" npm script (npm script named "lint") exists and is correctly
defined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7b513fd4-2e58-4b67-aa84-2327f167bdb7

📥 Commits

Reviewing files that changed from the base of the PR and between 6e00de5 and 19a40cd.

📒 Files selected for processing (30)
  • README.md
  • app/book-call/page.tsx
  • app/callback/page.tsx
  • app/contact/page.tsx
  • app/globals.css
  • app/how-it-works/page.tsx
  • app/layout.tsx
  • app/page.tsx
  • app/privacy/page.tsx
  • app/project-request/page.tsx
  • app/scope-builder/page.tsx
  • app/services/[slug]/page.tsx
  • app/services/page.tsx
  • app/terms/page.tsx
  • components/mobile-cta-bar.tsx
  • components/placeholder-page.tsx
  • components/site-footer.tsx
  • components/site-header.tsx
  • docs/control/VAIL_PLATFORM_FOUNDATION_REPORT.md
  • eslint.config.mjs
  • lib/routes.ts
  • netlify.toml
  • next-env.d.ts
  • next.config.ts
  • package.json
  • postcss.config.js
  • scripts/check-site.js
  • sitemap.xml
  • tailwind.config.ts
  • tsconfig.json
📜 Review details
🧰 Additional context used
🪛 Stylelint (17.11.1)
app/globals.css

[error] 1-1: Unexpected unknown at-rule "@tailwind" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)


[error] 2-2: Unexpected unknown at-rule "@tailwind" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)


[error] 3-3: Unexpected unknown at-rule "@tailwind" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)

🔇 Additional comments (31)
lib/routes.ts (1)

1-40: LGTM!

components/placeholder-page.tsx (1)

1-41: LGTM!

components/site-footer.tsx (1)

1-22: LGTM!

Also applies to: 25-40

components/site-header.tsx (1)

1-55: LGTM!

components/mobile-cta-bar.tsx (1)

1-16: LGTM!

app/page.tsx (1)

1-120: LGTM!

app/book-call/page.tsx (1)

1-20: LGTM!

app/callback/page.tsx (1)

1-20: LGTM!

app/contact/page.tsx (1)

1-20: LGTM!

app/how-it-works/page.tsx (1)

1-20: LGTM!

app/privacy/page.tsx (1)

1-20: LGTM!

app/project-request/page.tsx (1)

1-20: LGTM!

app/scope-builder/page.tsx (1)

1-20: LGTM!

app/terms/page.tsx (1)

1-20: LGTM!

app/services/page.tsx (1)

1-29: LGTM!

app/services/[slug]/page.tsx (1)

1-70: LGTM!

next.config.ts (1)

1-41: LGTM!

tailwind.config.ts (1)

1-24: LGTM!

tsconfig.json (1)

1-28: LGTM!

postcss.config.js (1)

1-7: LGTM!

eslint.config.mjs (1)

1-15: LGTM!

next-env.d.ts (1)

1-5: LGTM!

netlify.toml (1)

1-7: LGTM!

app/globals.css (2)

5-41: LGTM!


1-3: ⚡ Quick win

<stylelint @tailwind handling in app/globals.css needs evidence from the repo. The current search only shows @tailwind base/components/utilities in app/globals.css and Tailwind/PostCSS config; it didn’t find Stylelint config or the scss/at-rule-no-unknown/ignoreAtRules rule text. Add or adjust Stylelint config only if CI is actually running Stylelint with that rule and the file is included.

app/layout.tsx (1)

1-33: LGTM!

scripts/check-site.js (2)

5-83: LGTM!

Also applies to: 98-120


86-96: ⚡ Quick win

Missing input: Provide the original review comment inside <review_comment>...</review_comment> (and any verification outputs you have), so I can rewrite it in the required format.

docs/control/VAIL_PLATFORM_FOUNDATION_REPORT.md (1)

1-153: LGTM!

README.md (1)

1-81: LGTM!

sitemap.xml (1)

4-18: LGTM!

Comment on lines +23 to +24
<Link href="/privacy" className="hover:text-white">Privacy</Link>
<Link href="/terms" className="hover:text-white">Terms</Link>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove hardcoded legal links from the footer route list.

These links bypass the centralized route registry and can drift from route data over time. Prefer reading them from lib/routes.ts as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/site-footer.tsx` around lines 23 - 24, Replace the two hardcoded
<Link> entries with links sourced from the centralized route registry in
lib/routes.ts: import the privacy and terms route entries (e.g., constants or
objects named like privacyRoute / termsRoute or lookup by key) and render <Link
href={privacyRoute.path} ...>Privacy</Link> and <Link href={termsRoute.path}
...>Terms</Link> (or use the registry lookup method used elsewhere) so the
footer uses the canonical route definitions instead of hardcoded paths.

Comment thread lib/routes.ts
Comment on lines +42 to +50
export const placeholderRoutes = [
"/project-request",
"/scope-builder",
"/book-call",
"/callback",
"/contact",
"/privacy",
"/terms"
] as const;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add the missing placeholder route for /how-it-works.

placeholderRoutes is missing /how-it-works, which makes the route registry inconsistent with the placeholder page set in this migration.

Suggested fix
 export const placeholderRoutes = [
+  "/how-it-works",
   "/project-request",
   "/scope-builder",
   "/book-call",
   "/callback",
   "/contact",
   "/privacy",
   "/terms"
 ] as const;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const placeholderRoutes = [
"/project-request",
"/scope-builder",
"/book-call",
"/callback",
"/contact",
"/privacy",
"/terms"
] as const;
export const placeholderRoutes = [
"/how-it-works",
"/project-request",
"/scope-builder",
"/book-call",
"/callback",
"/contact",
"/privacy",
"/terms"
] as const;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/routes.ts` around lines 42 - 50, The placeholderRoutes array is missing
the "/how-it-works" entry; update the exported constant placeholderRoutes to
include "/how-it-works" alongside the other strings so the route registry
matches the placeholder page set in the migration (modify the placeholderRoutes
declaration to add the "/how-it-works" string to the tuple).

Comment thread package.json
"start": "next start",
"typecheck": "tsc --noEmit",
"lint": "eslint . --max-warnings=0",
"check": "node scripts/check-site.js && npm run typecheck && npm run build"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Include lint in the main validation gate.

check currently skips lint, so a single-command verification can pass with lint regressions.

Suggested update
-    "check": "node scripts/check-site.js && npm run typecheck && npm run build"
+    "check": "node scripts/check-site.js && npm run typecheck && npm run lint && npm run build"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"check": "node scripts/check-site.js && npm run typecheck && npm run build"
"check": "node scripts/check-site.js && npm run typecheck && npm run lint && npm run build"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 11, The "check" npm script currently runs "node
scripts/check-site.js && npm run typecheck && npm run build" but omits linting;
update the "check" script in package.json to include the lint step (e.g., add
"&& npm run lint" at the appropriate place) so that lint runs as part of the
main validation gate, and confirm the "lint" npm script (npm script named
"lint") exists and is correctly defined.

Comment thread package.json
Comment on lines +13 to 30
"dependencies": {
"next": "15.3.4",
"react": "19.0.0",
"react-dom": "19.0.0"
},
"devDependencies": {
"@eslint/eslintrc": "3.3.1",
"@netlify/plugin-nextjs": "5.11.3",
"@types/node": "22.15.30",
"@types/react": "19.0.12",
"@types/react-dom": "19.0.4",
"autoprefixer": "10.4.21",
"eslint": "9.28.0",
"eslint-config-next": "15.3.4",
"postcss": "8.5.6",
"tailwindcss": "3.4.17",
"typescript": "5.8.3"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Commit the lockfile alongside these pinned dependencies.

Without package-lock.json, transitive dependency resolution can still drift between environments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 13 - 30, package.json lists pinned
dependencies/devDependencies but the repository is missing a lockfile; run a
fresh install to generate and commit the lockfile (e.g., run npm install to
produce package-lock.json or yarn install to produce yarn.lock), ensure the
generated lockfile is added to the repo alongside package.json so transitive
dependencies are pinned and then include the lockfile in the commit that updates
the "dependencies"/"devDependencies".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19a40cde74

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sitemap.xml
@@ -1,9 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Serve sitemap via Next static assets

After this migration the site is built from .next, and Next.js only serves static files from public/ (or metadata routes under app/). Keeping sitemap.xml at the repo root means /sitemap.xml will not be published, so crawlers lose the sitemap despite this file being updated. Move it to public/sitemap.xml or implement app/sitemap.ts so the route is actually served.

Useful? React with 👍 / 👎.

Comment thread netlify.toml
publish = "."
command = ""
command = "npm run build"
publish = ".next"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep robots.txt accessible after switching to .next publish

Changing Netlify to publish .next stops serving root-level static files, and this commit does not add public/robots.txt or an app/robots.ts route. As a result, /robots.txt disappears in production, which removes the crawl policy and the sitemap discovery hint currently defined in the existing robots file.

Useful? React with 👍 / 👎.

Comment thread next.config.ts
Comment on lines +8 to +10
source: "/start-a-project",
destination: "/project-request",
permanent: true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redirect legacy .html URLs to the new routes

Before this migration, the static site shipped concrete files like start-a-project.html, fix-list-builder.html, and thank-you.html, so those direct URLs were valid and may still be bookmarked or indexed. The new redirect table only matches extensionless paths (for example /start-a-project) and does not include .html variants, so these legacy links now return 404 after moving publish output to .next.

Useful? React with 👍 / 👎.

@harbourviewcompany-create harbourviewcompany-create merged commit ce7edc3 into main May 22, 2026
3 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant