[GH-ISSUE #299] bug: missing default viewport meta tag when only themeColor is exported #74

Closed
opened 2026-05-06 12:37:00 +02:00 by BreizhHardware · 0 comments

Originally created by @Divkix on GitHub (Mar 6, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/299

Description

When a user exports a viewport config with only themeColor (no width/initialScale), vinext does not render a <meta name="viewport"> tag at all, breaking mobile rendering.

Root Cause

mergeViewport() starts from an empty object {}. When the merged result is truthy (e.g. { themeColor: "#000" }), the ?? fallback at call sites never triggers, so ViewportHead receives no width/initialScale and skips the viewport meta tag entirely.

Next.js seeds with { width: "device-width", initialScale: 1 } via createDefaultViewport(). vinext doesn't.

Reproduction

// layout.tsx
export const viewport = { themeColor: "#000" };

Expected: <meta name="viewport" content="width=device-width, initial-scale=1"> is rendered (matching Next.js behavior).

Actual: No <meta name="viewport"> tag is rendered. Only <meta name="theme-color"> appears.

Bug Flow

User exports: { themeColor: "#000" }
  → mergeViewport returns { themeColor: "#000" } (no width/initialScale)
  → resolvedViewport is NOT null → ?? fallback skipped
  → ViewportHead gets { themeColor: "#000" }
  → parts array is empty → no <meta name="viewport"> tag rendered

Fix

Seed mergeViewport with DEFAULT_VIEWPORT matching Next.js defaults: { width: "device-width", initialScale: 1 }.

Originally created by @Divkix on GitHub (Mar 6, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/299 ## Description When a user exports a viewport config with only `themeColor` (no `width`/`initialScale`), vinext does not render a `<meta name="viewport">` tag at all, breaking mobile rendering. ## Root Cause `mergeViewport()` starts from an empty object `{}`. When the merged result is truthy (e.g. `{ themeColor: "#000" }`), the `??` fallback at call sites never triggers, so `ViewportHead` receives no `width`/`initialScale` and skips the viewport meta tag entirely. Next.js seeds with `{ width: "device-width", initialScale: 1 }` via `createDefaultViewport()`. vinext doesn't. ## Reproduction ```ts // layout.tsx export const viewport = { themeColor: "#000" }; ``` Expected: `<meta name="viewport" content="width=device-width, initial-scale=1">` is rendered (matching Next.js behavior). Actual: No `<meta name="viewport">` tag is rendered. Only `<meta name="theme-color">` appears. ## Bug Flow ``` User exports: { themeColor: "#000" } → mergeViewport returns { themeColor: "#000" } (no width/initialScale) → resolvedViewport is NOT null → ?? fallback skipped → ViewportHead gets { themeColor: "#000" } → parts array is empty → no <meta name="viewport"> tag rendered ``` ## Fix Seed `mergeViewport` with `DEFAULT_VIEWPORT` matching Next.js defaults: `{ width: "device-width", initialScale: 1 }`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#74
No description provided.