Skip to content

feat(routing): implement dynamic routing using sanity cms - #2

Open
srikishore5727 wants to merge 2 commits into
masterfrom
feature/dynamic-routing-sanity-cms
Open

srikishore5727 wants to merge 2 commits into
masterfrom
feature/dynamic-routing-sanity-cms

Conversation

@srikishore5727

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Introduces CMS-driven page routing using Sanity and Next.js dynamic routes
  • Adds a Page schema in Sanity with structured fields (title, slug, description, heroBanner)
  • Registers the Page schema in the Sanity schema index to enable document creation in Studio
  • Implements dynamic routing in Next.js using app/[slug]/page.tsx to render pages based on CMS slugs
  • Adds GROQ query logic to fetch page data by slug from Sanity
  • Updates Sanity client configuration to ensure environment variables are strongly typed
  • Ensures required validation on the title field in the Page schema
  • Enables CMS editors to create, update, and control public URLs without code changes

What steps does your reviewer have to take to test this PR manually?

  1. Run npm install to install dependencies
  2. Run npm run dev and open http://localhost:3000
  3. Open http://localhost:3000/studio and verify Page appears in the left sidebar
  4. Create two pages in Sanity Studio:
    • Title: Home, Slug: home
    • Title: About, Slug: about
    • Publish both pages
  5. Visit the following URLs in the browser:
    • http://localhost:3000/home
    • http://localhost:3000/about
  6. Modify the slug of the Home page to home-page and republish
  7. Verify:
    • http://localhost:3000/home-page works
    • http://localhost:3000/home returns 404
  8. Confirm there are no hardcoded routes like /app/home/page.tsx or /app/about/page.tsx
  9. Verify Sanity client environment variables are correctly configured in .env.local

Pull Request standards checklist - Please check off

  • This branch carries a single responsibility: CMS-driven page routing and schema setup
  • I have followed conventional commit messages and descriptive branch naming
  • My PR uses a clean, descriptive folder structure aligned with scalability best practices

Testing checklist - Please check off

  • I have performed manual testing locally to validate dynamic routing and CMS integration

Definition of Done - Please check off

  • Pages are created and managed entirely through Sanity CMS
  • Dynamic routing correctly fetches and renders content by slug
  • 404 behavior works for non-existent slugs
  • Linting and formatting are enabled and all highlighted issues have been resolved
  • Schema fields and validations behave as expected in Studio
  • No secrets or environment variables are committed to the repository
  • My branch is up to date with the base branch and all commits in this PR are my own

Outcome: The CMS now fully controls which pages exist and what their URLs are, with Next.js dynamically rendering content based on Sanity data.

@mergemitra

mergemitra Bot commented Jan 29, 2026

Copy link
Copy Markdown

Change Summary

This PR implements CMS-driven page routing by integrating Sanity with Next.js. It introduces a Page document schema registered in the Sanity schema index and a Next.js dynamic route that fetches page data by slug using GROQ, returning 404 when not found.

File Changes

File Summary
app/[slug]/page.tsx Adds Next.js dynamic route rendering Sanity pages by slug; fetches via GROQ and handles 404.
lib/sanity/client.ts Updates Sanity client to use non-null asserted env vars and sets apiVersion/useCdn.
sanity/schemaTypes/index.ts Registers Page schema in Sanity schema index so Studio can create Page documents.
sanity/schemaTypes/page.ts Adds Page document schema with title (required), slug, description, and heroBanner image fields.

@mergemitra

mergemitra Bot commented Jan 29, 2026

Copy link
Copy Markdown

PR Scorecard

Score

Communication Quality Code Correctness & Design Quality Test Quality & Coverage Code Readability & Maintainability
Scoring Methodology

Communication Scoring Framework

The overall communication score is a weighted average:

Dimension Weight Evaluates
PR Description Quality 60% Title format (conventional commits) + Description clarity (what changed & why)
PR Size & Scope 25% Appropriate sizing, scope cohesion, and justification for size
Commit Messages 15% Conventional commits format, atomic & descriptive changes

Formula: (Description x 0.6) + (PR Size x 0.25) + (Commits x 0.15)

Code Scoring Framework

The scorecard evaluates code using 3 key reviewer questions:

Reviewer Question Category
Is this the right solution, implemented the right way? Code Correctness
Would this catch bugs if the code broke tomorrow? Test Quality
Can someone new understand and safely modify this in 6 months? Maintainability
PR Communication Notes

Description Quality

  • ✅ Title follows conventional commits format with clear scope 'routing' and concise summary
  • ✅ Description thoroughly explains changes, why, and provides clear manual testing steps
  • ❌ PR checklists in the description are all unchecked; please mark completed items or explain exceptions
  • ❌ Description omits generated Sanity runtime files and package-lock.json addition; mention or exclude artifacts
  • ❌ Description says env vars are 'strongly typed' but lib/sanity/client.ts uses TypeScript non-null assertions (!) not runtime validation

PR Size & Scope

  • ✅ PR is focused on CMS-driven routing and schema; core changes are small after excluding generated files
  • ✅ Size is ideal: ~60 added LOC across 5 source files when .sanity/runtime files are excluded
  • ❌ Commits include generated files under .sanity/runtime; avoid committing generated artifacts to keep PR small
  • ❌ .gitignore now ignores package-lock.json; confirm your package manager and lockfile policy

Commit Messages

  • ✅ Single commit follows conventional commits format: 'feat(routing): implement dynamic routing using sanity cms'
  • ✅ Commit message is descriptive and aligns with the PR title and scope

Notes

Code Correctness & Design Quality

  • 🟠 Using any and await params at app/[slug]/page.tsx:4 weakens type safety and can hide invalid route params causing runtime crashes
  • 🟠 Missing try/catch around client.fetch at app/[slug]/page.tsx:8 could surface Sanity/network failures as 500s instead of controlled errors
  • 🟠 Non-null assertions on env vars at lib/sanity/client.ts:4 can crash at runtime with unclear errors when .env is missing or misconfigured
  • 🟠 slug field lacks required validation at sanity/schemaTypes/page.ts:15 allowing pages without URLs, breaking dynamic routing expectations

Test Quality & Coverage

  • 🟠 No automated tests for dynamic routing and 404 behavior referenced in app/[slug]/page.tsx:11 could let CMS-driven routing regressions ship unnoticed

Code Readability & Maintainability

  • 💬 Inline GROQ string in component at app/[slug]/page.tsx:7 reduces reuse/readability; extracting a named query constant simplifies future changes
  • 💬 Unparenthesized Rule param in validation at sanity/schemaTypes/page.ts:12 slightly hurts readability and consistency with common Sanity examples

Comment thread app/[slug]/page.tsx Outdated
Comment thread lib/sanity/client.ts
Comment thread sanity/schemaTypes/page.ts Outdated
Comment thread app/[slug]/page.tsx Outdated
export default async function Page({ params }: any) {
const { slug } = await params
// GROQ Query
const query = `*[_type == "page" && slug.current == $slug][0]`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: 🟠 Major
Add automated coverage for the new CMS-driven routing (happy path + 404) by extracting fetch logic into a testable function and mocking client.fetch.

Suggested Change:

// Example direction:
// - move `PAGE_BY_SLUG_QUERY` + `client.fetch` into `lib/sanity/queries.ts` as `getPageBySlug(slug)`
// - unit test `getPageBySlug` by mocking `client.fetch`
// - optionally test the page component by asserting it calls `notFound()` when null is returned

@mergemitra

mergemitra Bot commented Jan 29, 2026

Copy link
Copy Markdown

PR Overview

PR Type: Feature

Focus Areas for Architect Review

  • Decide the caching/revalidation strategy for CMS pages, since useCdn: true plus server rendering may serve stale content without an explicit revalidate/preview approach.
  • Confirm the desired behavior for pages without slugs (now preventable via schema validation) and how failures should be surfaced (404 vs error) for Sanity/network outages.
PR Insights

Potential PR Improvements

  • Testing: No automated tests cover routing and 404 behavior.
  • Robustness: Fetch failures and network errors are not handled.
  • Robustness: Environment variables are forced, not validated at runtime.
  • Code Maintainability: Route params and CMS data types are not defined.
  • Best Practices: Avoid using any for server component inputs.

Strengths

  • Description Quality: PR description includes clear manual testing steps.
  • Correctness: Missing CMS pages return a 404 response.
  • Documentation: Sanity schema fields are explicit and easy to understand.
  • Best Practices: Schema validation requires a title for pages.
  • PR Size: Changes are small and focused on one feature.

@mergemitra

mergemitra Bot commented Jan 30, 2026

Copy link
Copy Markdown

Tip

Need another review?

Tag me and say rereview for re-analysis after you have fixed all the issues.

@cw-pr-agent rereview

@vaibhav-cw

Copy link
Copy Markdown
Collaborator

@cw-pr-agent rereview

1 similar comment
@codewalnut-labs

Copy link
Copy Markdown

@cw-pr-agent rereview

@mergemitra

mergemitra Bot commented Jan 30, 2026

Copy link
Copy Markdown

Change Summary

Implements Sanity-driven dynamic routing via the app/[slug] route so Next.js renders CMS-defined pages. Adds and registers a Page schema with required title/slug fields plus description and hero banner content for Studio authors. Strengthens Sanity client setup by validating environment variables and typing configuration to ensure reliable content fetching.

File Changes
File Summary
.gitignore Adds package-lock.json to the ignore list to prevent accidental commits.
.sanity/runtime/app.js Adds auto-generated Sanity runtime script for Studio client rendering.
.sanity/runtime/index.html Adds Sanity-generated HTML shell hosting Studio interface and bootstrap scripts.
app/[slug]/page.tsx Implements dynamic Next.js page that fetches Sanity content by slug.
lib/sanity/client.ts Types environment variables as required for Sanity client configuration.
sanity/lib/client.ts Switches to @sanity/client, validates env vars, and configures API settings.
sanity/schemaTypes/index.ts Registers page schema with Sanity to expose document type in Studio.
sanity/schemaTypes/page.ts Defines Page document schema with slug, title, description, hero banner fields.

Based on de57284...f8711bf

@mergemitra

mergemitra Bot commented Jan 30, 2026

Copy link
Copy Markdown

PR Scorecard

Score

Communication Quality Code Correctness & Design Quality Test Quality & Coverage Code Readability & Maintainability
Scoring Methodology

Communication Scoring Framework

The overall communication score is a weighted average:

Dimension Weight Evaluates
PR Description Quality 60% Title format (conventional commits) + Description clarity (what changed & why)
PR Size & Scope 25% Appropriate sizing, scope cohesion, and justification for size
Commit Messages 15% Conventional commits format, atomic & descriptive changes

Formula: (Description x 0.6) + (PR Size x 0.25) + (Commits x 0.15)

Code Scoring Framework

The scorecard evaluates code using 3 key reviewer questions:

Reviewer Question Category
Is this the right solution, implemented the right way? Code Correctness
Would this catch bugs if the code broke tomorrow? Test Quality
Can someone new understand and safely modify this in 6 months? Maintainability
PR Communication Notes

Description Quality

  • ✅ Now types route params, extracts PAGE_BY_SLUG_QUERY, and adds fetch try/catch in app/[slug]/page.tsx
  • ✅ Sanity client now validates required env vars with explicit errors in sanity/lib/client.ts
  • ❌ PR checklists in the description are still unchecked; mark completed items or note exceptions
  • ❌ Description still says env vars are "strongly typed" but the change is runtime validation; update wording

PR Size & Scope

  • ✅ This update changes 3 files (+56/-28) and stays focused on routing + Sanity integration
  • ✅ No scope creep introduced in the latest delta; changes look like targeted fixes

Commit Messages

  • ✅ New commit 'fix: address pr bot comments' follows conventional commits format and is clearly scoped

Issue Notes

Code Correctness & Design Quality

  • 🟠 [UNRESOLVED] params is typed as a Promise and awaited at app/[slug]/page.tsx:5 which doesn’t match Next.js route props and can break typechecking/confuse future refactors
  • 🟠 Catching all client.fetch errors and returning 404 at app/[slug]/page.tsx:26 can mask Sanity outages/permission issues as “page not found” making real failures hard to detect
  • 🟠 The route imports @/lib/sanity/client at app/[slug]/page.tsx:1 but this PR updates sanity/lib/client.ts, risking a build failure or using an outdated client config if both files exist

Test Quality & Coverage

  • 🟠 [UNRESOLVED] No automated coverage for slug routing + 404 behavior at app/[slug]/page.tsx:16 risks regressions, and the PR description doesn’t explain why tests weren’t added
💬 Minor Issues (Nitpicks)

Code Readability & Maintainability

  • 💬 Rendering an empty <p> when description is null/undefined at app/[slug]/page.tsx:35 adds noisy markup; conditionally render the paragraph
  • 💬 Hardcoding apiVersion at sanity/lib/client.ts:17 makes upgrades easy to miss; consider centralizing it (or reading from a typed env module) for consistency

Based on 6bce809...f8711bf

Comment thread app/[slug]/page.tsx
Comment on lines +13 to +16
const PAGE_BY_SLUG_QUERY =
'*[_type == "page" && slug.current == $slug][0]{title, description}'

export default async function Page({ params }: PageRouteProps) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: 🟠 Major

Add automated tests for CMS-driven routing (happy path + 404) to prevent regressions; simplest path is extracting getPageBySlug(slug) and unit testing it by mocking client.fetch.

Comment thread app/[slug]/page.tsx
Comment on lines +4 to +7
type PageRouteProps = {
params: Promise<{ slug: string }>
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: 🟠 Major

params in Next.js App Router is an object, not a Promise—type it as { slug: string } and drop the await to avoid misleading types.

type PageRouteProps = { params: { slug: string } }
...
const { slug } = params

Comment thread app/[slug]/page.tsx
Comment on lines +24 to +28
try {
page = await client.fetch<PageDoc | null>(PAGE_BY_SLUG_QUERY, { slug })
} catch {
notFound()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: 🟠 Major

Don’t convert fetch/permission/network errors into a 404—reserve notFound() for “no document”, and throw (or log + throw) on real failures so outages surface as 500s.

try {
  page = await client.fetch<PageDoc | null>(PAGE_BY_SLUG_QUERY, { slug })
} catch (err) {
  throw err
}

@mergemitra

mergemitra Bot commented Jan 30, 2026

Copy link
Copy Markdown

PR Overview

PR Type: Feature

Focus Areas for Architect Review

  • Decide the desired behavior for Sanity fetch failures (404 vs 500) and whether errors should be logged/observed instead of being treated as “not found”.
  • Confirm the caching/revalidation strategy for CMS pages (useCdn: true + App Router rendering) to avoid serving unexpectedly stale content.
  • Standardize the Sanity client module location/import path (e.g., @/lib/sanity/client vs sanity/lib/client) to avoid duplicated config and build-time resolution issues.
Rereview Impressions

Progress Since Last Review

  • Improved robustness with runtime env var validation in the Sanity client.
  • Slug is now required in the Sanity schema, preventing unroutable pages.
  • Route query is extracted into a named constant and client.fetch is guarded.

New Issues Introduced (if any)

  • Route params is now typed as a Promise and awaited, which is misleading for Next.js App Router and may cause type-checking confusion.

Remaining Concerns

  • Still no automated tests for CMS-driven routing/404 behavior.
  • Fetch errors are currently mapped to 404s, which can hide real outages/misconfigurations.
PR Insights

Potential PR Improvements

  • Correctness: Route params typed as Promise conflicts with Next.js expectations.
  • Robustness: Catch-all fetch errors return 404, hiding real outages.
  • Code Maintainability: Sanity client file path mismatch risks duplicated configurations.
  • Testing: No automated tests cover slug routing and 404 behavior.
  • Code Maintainability: Hardcoded apiVersion can drift from future project standards.

PR Strengths

  • Description Quality: Description includes clear steps to manually verify routing.
  • Robustness: Environment variables are validated with explicit startup errors.
  • Correctness: Missing pages correctly return notFound() for 404 behavior.
  • Code Maintainability: GROQ query extracted into a named constant for reuse.
  • Correctness: Schema enforces required slug, preventing unroutable CMS pages.

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.

3 participants