<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Raunak Singh | Shopify & Web Dev Notes]]></title><description><![CDATA[Raunak Singh | Shopify & Web Dev Notes]]></description><link>https://raunaksingh.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 08 Nov 2026 09:31:40 GMT</lastBuildDate><atom:link href="https://raunaksingh.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[A Practical Next.js SEO Checklist for Indian Business Websites]]></title><description><![CDATA[Most Next.js sites I audit for Indian businesses have the same problem: they look great, load fast on a developer's laptop, and barely show up on Google…]]></description><link>https://raunaksingh.hashnode.dev/a-practical-next-js-seo-checklist-for-indian-business-websites</link><guid isPermaLink="true">https://raunaksingh.hashnode.dev/a-practical-next-js-seo-checklist-for-indian-business-websites</guid><category><![CDATA[Next.js]]></category><category><![CDATA[SEO]]></category><category><![CDATA[webdev]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Raunak Singh]]></dc:creator><pubDate>Sat, 07 Nov 2026 19:07:56 GMT</pubDate><content:encoded><![CDATA[<p>Most Next.js sites I audit for Indian businesses have the same problem: they look great, load fast on a developer's laptop, and barely show up on Google. The framework isn't the issue. A few defaults get missed, and they add up.</p>
<p>This is the checklist I run through on every Next.js (App Router) build for a clinic, coaching institute, CA firm or local store before it goes live.</p>
<h2>1. Every page has its own title and description</h2>
<p>Set a title template once in the root layout, then give each page its own metadata.</p>
<pre><code class="language-tsx">// app/layout.tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  metadataBase: new URL("https://www.example.in"),
  title: {
    default: "Example Dental Clinic | Dentist in Faridabad",
    template: "%s | Example Dental Clinic",
  },
  description: "Family dental care in Sector 15, Faridabad. Book online or call.",
};
</code></pre>
<pre><code class="language-tsx">// app/services/root-canal/page.tsx
export const metadata = {
  title: "Root Canal Treatment in Faridabad",
  description: "Painless root canal treatment with same-week appointments in Sector 15.",
};
</code></pre>
<p>For dynamic pages (blog posts, products, city pages), use <code>generateMetadata</code> so the title comes from your data, not a hard-coded string.</p>
<p><strong>Check:</strong> view source on three random pages. If the <code>&lt;title&gt;</code> is the same everywhere, Google sees duplicates.</p>
<h2>2. Canonical URLs are set</h2>
<p>With <code>metadataBase</code> in the root layout, you can add a relative canonical on each page:</p>
<pre><code class="language-tsx">export const metadata = {
  alternates: { canonical: "/services/root-canal" },
};
</code></pre>
<p>This matters more than people think. Tracking parameters (<code>?utm_source=...</code>, <code>?fbclid=...</code>) from ads and WhatsApp shares create many URLs for the same page. The canonical tells Google which one counts.</p>
<h2>3. Important content is rendered on the server</h2>
<p>Google can run JavaScript, but it does so later and not always fully. If your service descriptions, prices or FAQs load inside a <code>"use client"</code> component with <code>useEffect</code>, they may not be indexed when you expect.</p>
<p>Keep content in Server Components (the App Router default) and use client components only for the interactive parts: a booking widget, a carousel, a form.</p>
<p><strong>Check:</strong> right-click → View Page Source (not Inspect). If your main text isn't in the raw HTML, fix that first.</p>
<h2>4. sitemap.xml and robots.txt are generated, not forgotten</h2>
<p>Next.js can generate both from files in the <code>app</code> folder:</p>
<pre><code class="language-ts">// app/sitemap.ts
import type { MetadataRoute } from "next";

export default function sitemap(): MetadataRoute.Sitemap {
  const base = "https://www.example.in";
  const pages = ["", "/services", "/services/root-canal", "/contact"];

  return pages.map((path) =&gt; ({
    url: `${base}${path}`,
    lastModified: new Date(),
  }));
}
</code></pre>
<pre><code class="language-ts">// app/robots.ts
import type { MetadataRoute } from "next";

export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: "*", allow: "/" },
    sitemap: "https://www.example.in/sitemap.xml",
  };
}
</code></pre>
<p>Then submit the sitemap in Google Search Console. A surprising number of sites skip this step.</p>
<p><strong>Watch out:</strong> staging sites often ship with <code>disallow: "/"</code> so they stay out of Google. Make sure that rule doesn't follow you to production.</p>
<h2>5. LocalBusiness structured data on the home and contact pages</h2>
<p>For a business that serves a city, <code>LocalBusiness</code> (or a more specific type like <code>Dentist</code> or <code>AccountingService</code>) helps Google connect your site with your Google Business Profile.</p>
<pre><code class="language-tsx">// app/page.tsx
export default function Home() {
  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "Dentist",
    name: "Example Dental Clinic",
    url: "https://www.example.in",
    telephone: "+91-90000-00000",
    address: {
      "@type": "PostalAddress",
      streetAddress: "SCO 12, Sector 15",
      addressLocality: "Faridabad",
      addressRegion: "Haryana",
      postalCode: "121007",
      addressCountry: "IN",
    },
    areaServed: ["Faridabad", "Delhi NCR"],
  };

  return (
    &lt;&gt;
      &lt;script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(jsonLd).replace(/&lt;/g, "\\u003c"),
        }}
      /&gt;
      {/* page content */}
    &lt;/&gt;
  );
}
</code></pre>
<p>The name, address and phone here should match your Google Business Profile exactly, including how you write the sector and the phone number.</p>
<h2>6. The hero image loads first</h2>
<p>Use <code>next/image</code> everywhere, and mark the one above-the-fold image as high priority so it isn't lazy-loaded:</p>
<pre><code class="language-tsx">&lt;Image
  src="/clinic-front.jpg"
  alt="Example Dental Clinic reception, Sector 15 Faridabad"
  width={1200}
  height={630}
  priority
  sizes="100vw"
/&gt;
</code></pre>
<p>Newer Next.js versions rename this prop, so check the <code>next/image</code> docs for your version. The idea stays the same: one image per page gets priority, everything else lazy-loads.</p>
<p>Write real alt text. "image1" helps nobody; a short description of what's in the photo helps both screen readers and image search.</p>
<h2>7. Fonts don't cause layout shift</h2>
<p>Load fonts with <code>next/font</code> instead of a <code>&lt;link&gt;</code> to Google Fonts. It self-hosts the files and sets size fallbacks, which keeps text from jumping when the font arrives.</p>
<pre><code class="language-tsx">import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"], display: "swap" });
</code></pre>
<p>If you have Hindi pages, add the right subset (for example <code>Noto Sans Devanagari</code>) only on those pages, not site-wide.</p>
<h2>8. One URL format, with redirects for the rest</h2>
<p>Decide once: <code>www</code> or not, trailing slash or not. Then redirect everything else. Old URLs from a previous WordPress site also need permanent redirects, or you lose whatever rankings they had.</p>
<pre><code class="language-js">// next.config.js
module.exports = {
  async redirects() {
    return [
      { source: "/our-services", destination: "/services", permanent: true },
      { source: "/blog/:slug.html", destination: "/blog/:slug", permanent: true },
    ];
  },
};
</code></pre>
<h2>9. Hindi or regional pages are linked properly</h2>
<p>If you have the same page in English and Hindi, tell Google they're versions of each other:</p>
<pre><code class="language-tsx">export const metadata = {
  alternates: {
    canonical: "/services/root-canal",
    languages: {
      "en-IN": "/services/root-canal",
      "hi-IN": "/hi/services/root-canal",
    },
  },
};
</code></pre>
<p>Skip this if you only have one language. Don't add <code>hreflang</code> just because it sounds like good SEO.</p>
<h2>10. Test before and after launch</h2>
<ul>
<li><strong>Search Console → URL Inspection</strong> on your main pages: is the page indexed, and does the rendered HTML include your content?</li>
<li><strong>Rich Results Test</strong> for the structured data.</li>
<li><strong>PageSpeed Insights on mobile.</strong> Most Indian traffic is on mid-range Android phones over 4G, so mobile is the number that matters.</li>
</ul>
<h2>Quick checklist</h2>
<ul>
<li><input disabled type="checkbox" /> Unique title and description on every page</li>
<li><input disabled type="checkbox" /> <code>metadataBase</code> + canonical URLs</li>
<li><input disabled type="checkbox" /> Main content in the server-rendered HTML</li>
<li><input disabled type="checkbox" /> <code>sitemap.ts</code> and <code>robots.ts</code>, sitemap submitted in Search Console</li>
<li><input disabled type="checkbox" /> LocalBusiness JSON-LD matching the Google Business Profile</li>
<li><input disabled type="checkbox" /> Hero image prioritised, real alt text everywhere</li>
<li><input disabled type="checkbox" /> Fonts via <code>next/font</code></li>
<li><input disabled type="checkbox" /> One URL format, old URLs redirected</li>
<li><input disabled type="checkbox" /> <code>hreflang</code> only if you really have multiple languages</li>
</ul>
<p>None of this is advanced. It's just easy to skip when the deadline is close, and it's the difference between a site that ranks for "dentist in Faridabad" and one that only shows up when someone searches the clinic's exact name.</p>
<hr />
<p><em>I'm Raunak Singh, a Next.js and Shopify developer based in Faridabad with 7+ years of experience building websites for businesses across Delhi NCR. More at <a href="https://raunaksingh.co.in/nextjs-developer">raunaksingh.co.in</a>.</em></p>
]]></content:encoded></item></channel></rss>