How I Optimized SEO for a Next.js Portfolio Site Without Breaking Build Performance
I walked through the real challenges I faced when I tried to make my Next.js portfolio rank higher in search engines, and how I solved each one without adding load to the build.

How I Optimized SEO for a Next.js Portfolio Site Without Breaking Build Performance
I built a portfolio with Next.js 14 App Router, deployed to Vercel. The first week of traffic was under 10 visits per day. I knew something was wrong with how search engines saw the site. The problem was not a single bug but a set of small misconfigurations that kept my pages from ranking.
Why SEO matters for developer portfolios
Search engines are the first place most potential clients find a freelancer. If a page is missing a title tag, a description, or a structured data snippet, Google will not surface it. I also discovered that duplicate content from static pages and blog posts caused crawl budget waste. Fixing these issues gave me a clear path to more visibility.
Common pitfalls I hit in the first build
Missing meta tags
I had a global layout that did not inject a <title> or <meta name="description">. The result was blank titles in search results and a generic description that did not reflect the page content.
Duplicate content
The blog was built with a static site generator, but I also exposed the same content via API routes for a headless CMS. Search engines indexed both URLs, causing duplicate pages and confusing the indexer.
Slow hydration
The page bundle included heavy third-party scripts that ran on the client. The hydration time pushed the First Contentful Paint (FCP) beyond the recommended 2.5 seconds, and Google penalised the page for performance.
My step-by-step optimization
Use Next.js Head component
I replaced the global layout with a custom Head component that receives props from each page. I set a default title and description, then overrode them where needed. This gave every page a unique snippet without extra code.
Server-side rendering for blog posts
I switched the blog pages from static generation to server-side rendering (SSR). SSR ensures that each request receives fresh meta tags and that the content is available to crawlers before JavaScript runs. I kept static generation for the home page where the content rarely changes.
Image optimization
Next.js’ next/image automatically optimises images. I set priority on hero images and used fill for responsive backgrounds. The image sizes dropped from 2 MB to 400 KB on average, and Lighthouse scores improved.
Structured data
I added JSON-LD for BlogPosting and Person schemas on relevant pages. The code was a simple object that I stringified and inserted into the <Head>. Google recognised my author profile and the blog content, boosting relevance.
Canonical URLs
I added <link rel="canonical" href="https://myportfolio.com/blog/slug" /> to every blog post. This told search engines which URL to index, eliminating duplicate content.
Sitemaps
I generated a sitemap using next-sitemap. The XML file lists all pages and is automatically uploaded to Vercel’s public folder. Google Search Console picks it up on the first crawl.
Performance budgets
I set a maximum bundle size of 200 KB for the home page and 300 KB for other pages. I used next-bundle-analyzer to monitor the size after each commit. When the bundle exceeded the budget, I refactored or removed unnecessary dependencies.
Production debugging
Vercel logs
I enabled VERCEL_LOGS and filtered for 404 and 500 errors. The logs revealed that a mis-named image path caused a 404 on the blog page, which I fixed by adding a fallback.
Lighthouse audits
After each change I ran next build && next export && lighthouse https://myportfolio.com. The audit highlighted improvements in performance, accessibility, and SEO. I tracked the SEO score from 65 to 92 over three iterations.
Real User Monitoring
I added next-analytics to capture real-user metrics. The data showed that the average load time dropped from 4.2 s to 2.8 s after the optimisations. Users stayed longer and clicked through to my contact page.
Result and metrics
Traffic increase
Within a month of deploying the changes, organic traffic grew from 8 visits per day to 45 visits per day. The bounce rate dropped from 70 % to 48 %. These numbers came from Google Analytics and were consistent across devices.
Crawl errors resolved
Google Search Console reported zero crawl errors after the canonical and sitemap fixes. The index coverage report moved from “Excluded” to “Valid” for all blog posts.
Lessons learned
- Start with the basics: Meta tags, canonical URLs, and a sitemap are low-effort fixes that deliver high impact.
- Keep the bundle lean: A small bundle improves both performance and SEO, because faster pages rank higher.
- Test in production: Vercel logs and Lighthouse audits are essential to catch issues that do not appear in local builds.
FAQ
Q: Do I need a dedicated SEO tool? A: Not for a small portfolio. The built-in tools in Next.js and Vercel cover most needs.
Q: How often should I update the sitemap?
A: Every time you add or remove a page. Automating with next-sitemap keeps it up to date.
Q: Can I use a CMS for the blog? A: Yes, but make sure the CMS routes are not duplicated by static pages. Use canonical tags or disable the CMS route for crawlers.
Bottom line
Optimising SEO on a Next.js portfolio is a series of small, repeatable steps. By fixing meta tags, avoiding duplicate content, and monitoring performance, I raised traffic and reduced bounce rate without adding extra build time. The same approach works for any developer site that wants to be found by the right audience.
Sponsored
Ali Hamza is a full-stack developer in Lahore specializing in MERN, Next.js, and AWS serverless.
Free resource: viral packaging checklist · products
Want this built for your product?
Hire me for production Next.js, MERN, and AWS work. Prefer a short call over a long thread.