<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ENZORA</title>
    <description>The latest articles on DEV Community by ENZORA (@enzora_official).</description>
    <link>https://dev.to/enzora_official</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4216071%2F64693bd2-6a1f-4643-86b5-440d4d14ed48.png</url>
      <title>DEV Community: ENZORA</title>
      <link>https://dev.to/enzora_official</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/enzora_official"/>
    <language>en</language>
    <item>
      <title>Next.js App Router SEO checklist: metadata, sitemap.ts, robots.ts, JSON-LD</title>
      <dc:creator>ENZORA</dc:creator>
      <pubDate>Thu, 29 Oct 2026 22:13:55 +0000</pubDate>
      <link>https://dev.to/enzora_official/nextjs-app-router-seo-checklist-metadata-sitemapts-robotsts-json-ld-2n72</link>
      <guid>https://dev.to/enzora_official/nextjs-app-router-seo-checklist-metadata-sitemapts-robotsts-json-ld-2n72</guid>
      <description>&lt;p&gt;Search engines still reward boring technical hygiene. App Router makes the &lt;em&gt;right&lt;/em&gt; things easier—central metadata, file-based sitemap and robots—but only if you wire them consistently across routes. This checklist reflects how we keep a multi-page agency site indexable on a single Vercel project (&lt;a href="https://enzora.vercel.app" rel="noopener noreferrer"&gt;enzora.vercel.app&lt;/a&gt;), without buying SEO plugins or duplicate WordPress stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. One canonical host
&lt;/h2&gt;

&lt;p&gt;Pick one HTTPS origin and use it everywhere: &lt;code&gt;metadataBase&lt;/code&gt;, canonical tags, JSON-LD &lt;code&gt;url&lt;/code&gt; fields, and &lt;code&gt;sitemap.xml&lt;/code&gt; locs. We read &lt;code&gt;NEXT_PUBLIC_SITE_URL&lt;/code&gt; with a default of &lt;code&gt;https://enzora.vercel.app&lt;/code&gt; so previews can override without forked code.&lt;/p&gt;

&lt;p&gt;Helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;siteUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_SITE_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://enzora.vercel.app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every indexable route should export &lt;code&gt;alternates.canonical&lt;/code&gt; as an &lt;strong&gt;absolute&lt;/strong&gt; URL on that host, not a relative path alone. Relative canonicals break when content is scraped from staging.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Metadata API per route
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Layout defaults
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;app/layout.tsx&lt;/code&gt; sets site-wide &lt;code&gt;title&lt;/code&gt; template, description, Open Graph defaults, icons, and Search Console verification. Keep verification dual-path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML file in &lt;code&gt;/public/google*.html&lt;/code&gt; (legacy but reliable).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metadata.verification.google&lt;/code&gt; fed by &lt;code&gt;NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION&lt;/code&gt; for tag-based verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Page-level overrides
&lt;/h3&gt;

&lt;p&gt;Each marketing route exports &lt;code&gt;metadata&lt;/code&gt; or &lt;code&gt;generateMetadata&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Title&lt;/strong&gt; ~50–60 characters, primary keyword near the front.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt; ~150–160 characters, honest click-worthy copy (no fake guarantees).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;openGraph&lt;/strong&gt; title/description/url aligned with canonical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;twitter&lt;/strong&gt; card set to &lt;code&gt;summary_large_image&lt;/code&gt; when OG images exist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dynamic segments (&lt;code&gt;services/[slug]&lt;/code&gt;, &lt;code&gt;blog/[slug]&lt;/code&gt;) should compute metadata from a single content source—do not hand-edit fifty copies.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Exactly one H1, intentional headings
&lt;/h2&gt;

&lt;p&gt;App Router does not police heading order; designers do. Each page gets one H1 matching search intent. Section titles use H2/H3. Avoid duplicating the site name in every H1 unless the page is the home page.&lt;/p&gt;

&lt;p&gt;For service hubs, pair the H1 with a short intro paragraph that mentions the primary keyword naturally in the first 100 words, then link internally to related hubs (web design → ecommerce → SEO).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;code&gt;sitemap.ts&lt;/code&gt; that mirrors reality
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;app/sitemap.ts&lt;/code&gt;, not a static &lt;code&gt;public/sitemap.xml&lt;/code&gt; that rots. Build locs from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static marketing paths (home, services index, packages, legal).&lt;/li&gt;
&lt;li&gt;All service detail slugs you actually ship (including hub routes like &lt;code&gt;/services/web-design&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Blog posts from your data layer.&lt;/li&gt;
&lt;li&gt;Location/market pages if you have them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set sensible &lt;code&gt;changeFrequency&lt;/code&gt; and &lt;code&gt;priority&lt;/code&gt;, but remember Google largely ignores those fields—they are still useful for your own audits.&lt;/p&gt;

&lt;p&gt;When you add a hub route, add it to the generator the same day. CI can fetch &lt;code&gt;/sitemap.xml&lt;/code&gt; and assert critical URLs exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;robots.ts&lt;/code&gt; with explicit disallows
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;app/robots.ts&lt;/code&gt; should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow &lt;code&gt;/&lt;/code&gt; for normal crawling.&lt;/li&gt;
&lt;li&gt;Point to the absolute sitemap URL on your canonical host.&lt;/li&gt;
&lt;li&gt;Disallow non-content paths: &lt;code&gt;/api/&lt;/code&gt;, &lt;code&gt;/_next/&lt;/code&gt;, preview or demo trees you mark &lt;code&gt;noindex&lt;/code&gt; (we disallow &lt;code&gt;/work&lt;/code&gt; static demos that are intentionally non-indexable).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; block CSS or JS—Google needs assets to render pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Redirects instead of duplicate URLs
&lt;/h2&gt;

&lt;p&gt;When consolidating service slugs (for example &lt;code&gt;/services/online-stores&lt;/code&gt; → &lt;code&gt;/services/ecommerce&lt;/code&gt;), implement &lt;strong&gt;301 redirects&lt;/strong&gt; in &lt;code&gt;next.config.ts&lt;/code&gt;. Update internal links and the sitemap to the canonical slug only. Keep redirects for at least a year; search engines are slow to forget old URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Open Graph images
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;app/opengraph-image.tsx&lt;/code&gt; at the root covers defaults. Dynamic segments can expose &lt;code&gt;opengraph-image.tsx&lt;/code&gt; with &lt;code&gt;generateStaticParams&lt;/code&gt; for high-value routes (services hubs, blog posts). Keep layouts simple—Satori fails on complex nested flex unless every multi-child &lt;code&gt;div&lt;/code&gt; sets &lt;code&gt;display: "flex"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. JSON-LD with stable &lt;code&gt;@id&lt;/code&gt;s
&lt;/h2&gt;

&lt;p&gt;Structured data should match visible content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Organization / ProfessionalService&lt;/strong&gt; sitewide with legal name, phone, email, postal address, and &lt;code&gt;sameAs&lt;/code&gt; social URLs you actually operate—never a similarly named third-party LinkedIn page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAQPage&lt;/strong&gt; generated from the same FAQ array rendered on the page (home FAQ ≠ services FAQ ≠ full FAQ page—each schema matches its visible list).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BlogPosting&lt;/strong&gt; on articles with &lt;code&gt;datePublished&lt;/code&gt;, headline, and publisher linked to the organization &lt;code&gt;@id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BreadcrumbList&lt;/strong&gt; on nested pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid stuffing schema that is not on the page; rich-result spam invites manual actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Internal and outbound links
&lt;/h2&gt;

&lt;p&gt;Internal links carry relevance and crawl paths: services ↔ blog ↔ contact. Outbound links to authoritative docs (Google Search Central, web.dev, MDN) signal E-E-A-T when used sparingly and in context—not as a footer link farm.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Search Console readiness (human step)
&lt;/h2&gt;

&lt;p&gt;Automated agents cannot click “Submit sitemap” for you. Before launch, verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Property for &lt;code&gt;https://enzora.vercel.app&lt;/code&gt; (domain or URL prefix).&lt;/li&gt;
&lt;li&gt;Ownership via HTML file or meta tag env var.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/sitemap.xml&lt;/code&gt; returns 200 with only canonical URLs.&lt;/li&gt;
&lt;li&gt;No accidental &lt;code&gt;noindex&lt;/code&gt; on money pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After deploy, manually submit the sitemap and monitor Coverage for excluded &lt;code&gt;/work&lt;/code&gt; or &lt;code&gt;/api&lt;/code&gt; paths—those should be intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Launch regression checks
&lt;/h2&gt;

&lt;p&gt;Run this on every release candidate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch &lt;code&gt;/robots.txt&lt;/code&gt; and &lt;code&gt;/sitemap.xml&lt;/code&gt; on production.&lt;/li&gt;
&lt;li&gt;Spot-check five random service pages for canonical + H1 + FAQ schema parity.&lt;/li&gt;
&lt;li&gt;Mobile Lighthouse SEO category ≥ 90 (not a ranking factor, but catches missing meta/titles).&lt;/li&gt;
&lt;li&gt;Link crawl script against sitemap locs (we use a small Node fetch loop in CI optional).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;App Router SEO is mostly &lt;strong&gt;routing discipline&lt;/strong&gt;: one hostname, one slug per intent, metadata generated from the same source as the UI, and sitemap/robots that update when routes do. Fancy content strategies fail when &lt;code&gt;/services/old-name&lt;/code&gt; still resolves without a redirect. Fix the plumbing first; the rankings fight happens later, honestly, on the content and product—not on trick metadata.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://enzora.vercel.app/blog/nextjs-app-router-seo-checklist" rel="noopener noreferrer"&gt;ENZORA blog&lt;/a&gt;. ENZORA builds fast Next.js and Shopify sites, SEO and ads for growing businesses: &lt;a href="https://enzora.vercel.app" rel="noopener noreferrer"&gt;enzora.vercel.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>seo</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How we got a Next.js App Router site to green Core Web Vitals on Vercel’s free tier</title>
      <dc:creator>ENZORA</dc:creator>
      <pubDate>Thu, 29 Oct 2026 22:13:54 +0000</pubDate>
      <link>https://dev.to/enzora_official/how-we-got-a-nextjs-app-router-site-to-green-core-web-vitals-on-vercels-free-tier-2o98</link>
      <guid>https://dev.to/enzora_official/how-we-got-a-nextjs-app-router-site-to-green-core-web-vitals-on-vercels-free-tier-2o98</guid>
      <description>&lt;p&gt;Shipping a marketing site that &lt;em&gt;looks&lt;/em&gt; premium is easy. Shipping one that stays fast on mid-range phones, on cold cache, without a performance budget spreadsheet—that takes discipline. We recently tightened &lt;a href="https://enzora.vercel.app" rel="noopener noreferrer"&gt;ENZORA’s public site&lt;/a&gt; on Next.js 15 App Router, hosted on Vercel’s Hobby tier. This article walks through what actually moved Core Web Vitals into the green zone for us, and what we deliberately did &lt;em&gt;not&lt;/em&gt; do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with measurement, not guesses
&lt;/h2&gt;

&lt;p&gt;Before changing code, we ran Lighthouse against a &lt;strong&gt;production build&lt;/strong&gt; (&lt;code&gt;next build&lt;/code&gt; + &lt;code&gt;next start&lt;/code&gt;), not &lt;code&gt;next dev&lt;/code&gt;. Dev mode inflates JavaScript cost and hides image optimisation. Mobile emulation matters: most agency traffic lands on phones.&lt;/p&gt;

&lt;p&gt;We tracked three field-aligned lab signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt; — usually the hero headline block or a large visual above the fold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt; — often from web fonts, late-loading widgets, or images without reserved space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interaction to Next Paint (INP)&lt;/strong&gt; — main-thread work from hydration, analytics, or heavy client components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a metric is red, write down the LCP element name from Lighthouse. That single line saves hours of random bundle trimming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the critical path boring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Static generation where possible
&lt;/h3&gt;

&lt;p&gt;App Router pages that do not need per-request data should be static. Our home, services, legal, and blog index routes prerender at build time. That gives CDN-friendly HTML and predictable TTFB on Vercel.&lt;/p&gt;

&lt;p&gt;Dynamic routes (&lt;code&gt;/blog/[slug]&lt;/code&gt;, &lt;code&gt;/services/[slug]&lt;/code&gt;) use &lt;code&gt;generateStaticParams&lt;/code&gt; so builds emit HTML for known URLs. Avoid &lt;code&gt;force-dynamic&lt;/code&gt; unless you truly need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fonts without layout drama
&lt;/h3&gt;

&lt;p&gt;We load Inter for body copy with &lt;code&gt;display: "swap"&lt;/code&gt; and preload it. A secondary display font loads with &lt;code&gt;preload: false&lt;/code&gt; so it does not compete with LCP. Pair swap with consistent fallback metrics in CSS (&lt;code&gt;size-adjust&lt;/code&gt; or a close system stack) if CLS spikes when the webfont arrives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Images: one pipeline
&lt;/h3&gt;

&lt;p&gt;The React tree should use &lt;code&gt;next/image&lt;/code&gt; for raster assets so AVIF/WebP negotiation and sizing stay automatic. Enable modern formats in config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;formats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/avif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/webp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For decorative portfolio tiles rendered as CSS/SVG mockups, we use explicit aspect-ratio boxes so nothing reflows when lazy sections mount.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defer non-critical client JavaScript
&lt;/h2&gt;

&lt;p&gt;Marketing sites accumulate “nice to haves”: custom cursors, chat widgets, animation libraries. We moved non-essential UI into a client shell loaded &lt;strong&gt;after&lt;/strong&gt; hydration with &lt;code&gt;next/dynamic&lt;/code&gt; and &lt;code&gt;ssr: false&lt;/code&gt;. The hero and primary call-to-action render as server components; the floating chat and cursor do not block first paint.&lt;/p&gt;

&lt;p&gt;Analytics follows the same rule: Google Analytics 4 loads only after explicit cookie consent. Vercel Analytics and Speed Insights are lightweight first-party scripts and stayed enabled—they report vitals without blocking interaction in our tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Third-party scripts are a tax
&lt;/h2&gt;

&lt;p&gt;Every tag manager, chat vendor, or A/B snippet competes with INP. On the free tier you feel this immediately. Our defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No tag manager on launch.&lt;/li&gt;
&lt;li&gt;Chat is optional; a lightweight in-house panel replaces a heavy embed until a vendor is required.&lt;/li&gt;
&lt;li&gt;Consent-gated GA4 with &lt;code&gt;send_page_view&lt;/code&gt; controlled manually on route changes (App Router needs a small client listener).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If marketing insists on a pixel, load it after consent and measure INP again.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS and motion without jank
&lt;/h2&gt;

&lt;p&gt;Tailwind v4 kept our stylesheet lean, but motion still caused jank when tied to scroll on the main thread. We gate expensive scroll-driven effects behind a class added on first user interaction (scroll, pointer, keydown). That avoids animating large layers before the user engages—helpful for INP on low-end devices.&lt;/p&gt;

&lt;p&gt;Reserve space for fixed cookie banners (&lt;code&gt;position: fixed&lt;/code&gt; with a modest height) so accepting cookies does not shove the layout. A small banner beat a full-screen modal for CLS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching and headers
&lt;/h2&gt;

&lt;p&gt;Vercel already sends HSTS and compresses assets. We add long-cache headers for hashed static files in &lt;code&gt;vercel.json&lt;/code&gt; and keep HTML on short cache with revalidation. Do not cache HTML aggressively if you ship content fixes often; do cache &lt;code&gt;/logo/*&lt;/code&gt;, fonts, and media under &lt;code&gt;/public&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What our numbers looked like
&lt;/h2&gt;

&lt;p&gt;On a production build served locally and spot-checked on the deployed preview, mobile Lighthouse reported &lt;strong&gt;LCP around 1.1 s&lt;/strong&gt;, &lt;strong&gt;CLS 0&lt;/strong&gt;, and &lt;strong&gt;INP in the tens of milliseconds&lt;/strong&gt; after the above passes. Scores move with network noise—treat Lighthouse as a regression guard, not a vanity badge.&lt;/p&gt;

&lt;p&gt;Re-run tests after &lt;strong&gt;every&lt;/strong&gt; new script marketing asks for. One embed can undo a week of image optimisation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist you can copy
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Production build + mobile Lighthouse baseline.&lt;/li&gt;
&lt;li&gt;Identify the LCP element; optimise &lt;em&gt;that&lt;/em&gt; first.&lt;/li&gt;
&lt;li&gt;Static-generate marketing routes; static params for slugs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;next/image&lt;/code&gt; + AVIF/WebP; fixed aspect ratios for media.&lt;/li&gt;
&lt;li&gt;Split client bundles; defer chat, cursor, GA4 until needed/consented.&lt;/li&gt;
&lt;li&gt;Gate scroll/motion effects until interaction.&lt;/li&gt;
&lt;li&gt;Re-measure after each third-party add.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Green Core Web Vitals on a free tier is not magic—it is scope control. The site still has rich typography and motion; we just refuse to let optional scripts sit on the critical path. If you are tuning a similar agency site, start with consent-gated analytics and dynamic-imported widgets; the vitals usually follow.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://enzora.vercel.app/blog/nextjs-core-web-vitals-vercel-free-tier" rel="noopener noreferrer"&gt;ENZORA blog&lt;/a&gt;. ENZORA builds fast Next.js and Shopify sites, SEO and ads for growing businesses: &lt;a href="https://enzora.vercel.app" rel="noopener noreferrer"&gt;enzora.vercel.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>performance</category>
      <category>vercel</category>
    </item>
  </channel>
</rss>
