Skip to content

ibanlopez/v0-dynamic-rendering-issue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Next.js Screen Size Detection Solution

A production-ready solution for detecting screen sizes in Next.js applications. This hybrid approach combines the benefits of server-side hints with client-side precision while maintaining optimal performance.

πŸš€ The Problem

Using headers() in Next.js to detect screen sizes causes the entire application to opt into dynamic rendering, which:

  • ❌ Breaks static generation (SSG/ISR)
  • ❌ Disables CDN caching
  • ❌ Reduces performance significantly
  • ❌ Only provides limited device hints

βœ… Our Solution

This repository demonstrates a hybrid approach that:

  • βœ… Maintains static generation - No headers() usage
  • βœ… Excellent performance - Static HTML + progressive enhancement
  • βœ… CDN cacheable - Full static optimization benefits
  • βœ… Exact measurements - Real pixel dimensions + device hints
  • βœ… Server component support - Works with React Server Components
  • βœ… No hydration mismatch - Progressive enhancement prevents issues

πŸ—οΈ How It Works

1. Build Time

  • Static HTML generated with sensible desktop defaults
  • No dynamic APIs used, keeping everything static
  • ISR/SSG works perfectly

2. Runtime Enhancement

  • User-Agent detection for device hints
  • Exact screen measurements via window.innerWidth/innerHeight
  • Real-time updates on window resize

3. Progressive Data Sources

  • Build-time defaults: Available immediately (SSR-safe)
  • Device hints: From User-Agent parsing (after hydration)
  • Exact measurements: Real pixel dimensions (after hydration)

πŸ“¦ Installation

  1. Clone this repository

    git clone https://github.com/your-username/nextjs-screen-size-solution.git
    cd nextjs-screen-size-solution
  2. Install dependencies

    npm install
    # or
    yarn install
    # or
    pnpm install
  3. Run the development server

    npm run dev
    # or
    yarn dev
    # or
    pnpm dev
  4. Open http://localhost:3000 to see the demo

πŸ”§ Usage

Basic Setup

  1. Add the provider to your root layout:
// app/layout.tsx
import { ScreenSizeProvider } from "../components/screen-size-provider";
import { getStaticScreenSizeHint } from "../lib/screen-size-hint";

export default function RootLayout({ children }) {
  const staticHintPromise = getStaticScreenSizeHint();

  return (
    <html lang="en">
      <body>
        <ScreenSizeProvider staticHintPromise={staticHintPromise}>
          {children}
        </ScreenSizeProvider>
      </body>
    </html>
  );
}
  1. Use the hook in your components:
// components/your-component.tsx
"use client";

import { useScreenSize } from "./screen-size-provider";

export function YourComponent() {
  const { buildTimeDefaults, client, serverHint, isHydrated } = useScreenSize();

  // Choose the best data source for your needs
  const currentDevice =
    isHydrated && serverHint ? serverHint : buildTimeDefaults;

  return (
    <div>
      {currentDevice.isMobile ? <MobileLayout /> : <DesktopLayout />}

      <p>Screen width: {client.width}px</p>
      <p>Device type: {currentDevice.deviceType}</p>
    </div>
  );
}

Server Components

Server components can use static hints for conditional rendering:

// components/server-component.tsx
import { getStaticScreenSizeHint } from "../lib/screen-size-hint";

export async function ServerComponent() {
  const hint = await getStaticScreenSizeHint();

  return (
    <div>
      {hint.buildTimeDefaults.isDesktop ? (
        <ComplexDesktopLayout />
      ) : (
        <SimpleMobileLayout />
      )}
    </div>
  );
}

πŸ“Š API Reference

useScreenSize() Hook

Returns an object with the following properties:

interface ScreenSizeContextType {
  // Build-time defaults (available immediately)
  buildTimeDefaults: {
    isMobile: boolean;
    isTablet: boolean;
    isDesktop: boolean;
    deviceType: "desktop";
  };

  // Client measurements (available after hydration)
  client: {
    width: number;
    height: number;
    isMobile: boolean;
    isTablet: boolean;
    isDesktop: boolean;
    breakpoint: "sm" | "md" | "lg" | "xl" | "2xl";
  };

  // Runtime server hint (available after User-Agent detection)
  serverHint: {
    isMobile: boolean;
    isTablet: boolean;
    isDesktop: boolean;
    deviceType: "mobile" | "tablet" | "desktop";
  } | null;

  isHydrated: boolean;
}

Data Source Selection

Choose the appropriate data source based on your needs:

  • buildTimeDefaults: Use for SSR-safe rendering with sensible defaults
  • serverHint: Use for device-type detection after hydration
  • client: Use for exact pixel measurements and responsive behavior

🎯 Key Files

  • lib/screen-size-hint.ts - Static hint generation (no headers)
  • components/screen-size-provider.tsx - Main provider with React's use() hook
  • app/layout.tsx - Root layout setup
  • components/responsive-demo.tsx - Demo component showing all features

πŸ”„ Comparison with Other Approaches

Feature Server-side headers() Client-side Only Our Hybrid Solution
Static Generation ❌ Broken βœ… Works βœ… Works
Performance ❌ Poor βœ… Good βœ… Excellent
Server Components βœ… Yes ❌ No βœ… Yes
Exact Dimensions ❌ No βœ… Yes βœ… Yes
Hydration Issues βœ… None ⚠️ Potential βœ… None

πŸš€ Deployment

Vercel (Recommended)

  1. Push your code to GitHub
  2. Connect your repository to Vercel
  3. Deploy with zero configuration

Other Platforms

This solution works with any platform that supports Next.js:

  • Netlify
  • AWS Amplify
  • Railway
  • DigitalOcean App Platform

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Built with Next.js
  • Uses React's experimental use() hook
  • Inspired by the need for better screen size detection in SSG applications

πŸ“š Learn More


Made with ❀️ for the Next.js community

Releases

No releases published

Packages

No packages published