Scoping a Next.js project before development starts is the single fastest way to avoid mid-build surprises on budget and timeline. Most project overruns I see aren’t caused by hard engineering problems — they’re caused by vague scope that everyone interpreted differently. This post walks through the five things I pin down before quoting or starting any Next.js engagement.
Why next.js project scope breaks down early
A brief that says “we need a marketing site with a blog” could mean a five-page brochure or a 200-URL content hub with filtering, internationalisation, and a video section. Both are buildable. They are not the same price or timeline. The gap between them only becomes visible when someone writes a proper scope — so that’s the starting point.
If you’re also preparing a formal brief to hand to a developer, I cover the document structure in the companion post How to Write a Project Brief for Hiring a Next.js Developer. This post focuses on the discovery thinking that feeds that document.
Step 1: build a page inventory
List every URL the finished site needs to serve. Group them by type:
Page type Example Rendered how Static marketing /about, /pricing Build-time static Blog / article /blog/[slug] ISR or static Dynamic listing /blog, /case-studies ISR with tag revalidation User-specific /dashboard, /account Client-render or edge SSR API / webhook /api/revalidate Route handlerThe rendering column matters because it drives architecture decisions and hosting costs. A site with 50 static pages and a 500-post blog is a different infrastructure problem than one with personalised dashboards. Get this list out of someone’s head and into a spreadsheet on day one.
Also note which pages need:
- Open Graph images generated at build time or on-demand
- Structured data (JSON-LD for articles, products, FAQs)
- Sitemap inclusion and crawl priority
- Redirects from an old URL structure
That last one — redirects — is invisible until a developer asks for it two days before launch and the client needs two weeks to compile the list.
Step 2: make the CMS decision explicit
The choice of CMS is not a detail to defer. It affects schema design, query strategy, editorial workflow, and ongoing hosting cost. For most marketing and content sites I build, Sanity is my default — the free tier covers most small projects, the GROQ query language is precise enough to avoid over-fetching, and the Studio is customisable enough that editors don’t need hand-holding.
But the client’s situation can change that recommendation. Questions I ask:
- How many editors will use this? (Sanity’s Growth plan is $15/month per seat above the free-tier limit.)
- Do you need scheduled publishing, document versioning, or role-based permissions? (These are all Sanity features, but worth confirming before assuming.)
- Is there an existing CMS with content that needs migrating?
- Does the marketing team use a specific tool that needs integration (e.g. HubSpot forms, Marketo)?
A CMS decision that’s left open creates a dependency. Every schema, every GROQ query, every image pipeline decision waits on it.
Step 3: write the integrations list
Every third-party service a Next.js site touches adds surface area for scope creep. I ask clients to confirm each of these categories before I scope:
- Analytics: GA4, Plausible, Vercel Analytics — each has a different implementation cost
- Forms and email: Contact forms, newsletter sign-up (SendGrid, Mailchimp, Loops)
- Search: Is there a search bar? Is it Algolia, a Sanity-powered query, or a basic filter?
- Authentication: Is any part of the site behind a login?
- Video: Embedded YouTube, self-hosted via Mux, or Sanity + Mux managed upload?
- E-commerce: Shopify Storefront API, Stripe checkout, or nothing?
- Cookie consent: Required for GDPR-scoped users, and not trivial to implement without CLS
For each integration, the question isn’t just “does it exist” but “who owns the account, who sets up the credentials, and who tests the happy path plus the failure state.” Unclear ownership is where integrations stall launches.
Step 4: set a performance budget
I include a performance budget in every scope because it prevents design decisions that make Core Web Vitals targets impossible to hit after the fact. The targets I use as defaults:
Metric Target Why LCP ≤ 2.5 s (75th percentile) Google’s “Good” threshold INP ≤ 200 ms Replaces FID since March 2024 CLS ≤ 0.1 Layout shift, especially on image-heavy pages JS bundle (initial load) ≤ 120 kB gzipped Keeps TTI reasonable on mid-range mobileIf the design calls for a full-screen hero video, a parallax animation library, and a live chat widget loading on every page, the budget number tells you which of those to cut or defer before a developer has built anything. Fixing CLS or LCP after launch is always more expensive than designing around them upfront.
Step 5: timeline maths
Once the page inventory, CMS, integrations, and performance requirements are defined, timeline becomes arithmetic rather than guesswork. I use a simple breakdown:
- Discovery and schema design: 3–5 days for a typical marketing site
- Core layout and routing: 3–5 days (navigation, footer, shared components)
- Per page type: 1–3 days depending on complexity
- Each integration: 0.5–2 days depending on the service and whether credentials exist
- Content entry and QA: Usually underestimated by clients — budget at least one week
- Performance audit and fixes: 2–3 days before launch
- Redirects, DNS, staging review: 1–2 days
A 12-page marketing site with Sanity CMS, a contact form via SendGrid, and GA4 is typically 4–6 weeks of focused work. Add internationalisation and it’s 7–9 weeks. Add a full blog with author pages, filtering, and Algolia search and you’re at 10–12 weeks minimum.
Those numbers assume scope is locked. Each undefined requirement that surfaces mid-build is a negotiation about whether it’s in or out. Having this breakdown written down means that conversation is fast rather than contentious.
What good scope looks like in practice
A well-scoped Next.js project lands with: a spreadsheet of every URL, a confirmed CMS with credentials sorted, a named contact responsible for each integration, a written performance target, and a timeline with explicit dependencies called out. That’s not a 50-page document. It’s usually 4–6 pages plus the spreadsheet.
When a developer or agency can’t produce this before quoting, that’s a signal. Vague quotes protect the supplier, not the buyer. A fixed-price engagement with no scope is a budget that will drift.