Next.js Lesson 13 – getServerSideProps | Dataplexa
LESSON 13

getServerSideProps

Build dynamic search pages that fetch fresh article data on every request to keep NewsWave content always current.

Unlike getStaticProps which runs at build time, getServerSideProps executes on every single request. Think of it like a restaurant that cooks each meal fresh when the customer orders, instead of pre-cooking everything in the morning. This approach gives you the freshest data possible, but takes longer because the server must do work before sending the page.

Server-side rendering becomes crucial when your content changes frequently. Imagine building a search page for NewsWave where users look for articles by keyword. The search results must reflect the absolute latest articles in your database. Pre-building every possible search combination would be impossible — there are millions of potential queries.

When Server-Side Rendering Makes Sense

Server-side rendering shines in specific scenarios where freshness trumps speed. Search pages represent the perfect use case — users type "climate change" and expect to see articles published minutes ago, not hours old results from a static build. E-commerce product pages with real-time inventory, social media feeds, and personalized dashboards all benefit from this approach.

The trade-off involves latency. Every visitor waits while your server fetches data, renders HTML, and sends the complete page. Compare this to static generation where the HTML exists ready to serve instantly. But when data accuracy matters more than milliseconds, server-side rendering becomes essential.

Consider NewsWave's breaking news section. When a major story develops, readers expect immediate coverage. Static pages generated hours ago cannot capture breaking developments. Server-side rendering ensures each visitor sees the absolute latest updates, even if they arrive seconds after publication.

// pages/search.js - NewsWave search page with real-time results
export default function SearchPage({ articles, query, totalCount }) {
  return (
    <div>
      <h1>Search Results for "{query}"</h1>
      <p>Found {totalCount} articles</p>
      {articles.map(article => (
        <div key={article.id}>
          <h2>{article.title}</h2>
          <p>Published: {article.publishedAt}</p>
        </div>
      ))}
    </div>
  );
}
localhost:3000/search?q=climate — NewsWave

What just happened?

We built a search results page component that displays articles, query terms, and result counts. The data comes from getServerSideProps which will fetch fresh results on every search request. Try this: Notice how the timestamps show "minutes ago" — this real-time data needs server-side rendering.

How getServerSideProps Works

The getServerSideProps function runs on Next.js servers before sending any HTML to browsers. When someone visits your page, Next.js executes this function first, waits for it to complete, then renders your component with the returned data. The entire process happens server-side — browsers receive fully-formed HTML with data already embedded.

This execution model differs fundamentally from client-side data fetching. Instead of showing loading spinners while JavaScript requests data, users see complete content immediately. The browser receives HTML that already contains article titles, author names, and publication dates. Search engines can index this content because it exists in the initial HTML response.

Request context flows into getServerSideProps through a context object. Query parameters, request headers, cookies, and route parameters become available for processing. NewsWave's search page can read the search query from URL parameters and use it to filter articles accordingly.

// Export async function that runs on every request
export async function getServerSideProps(context) {
  const { query } = context; // Get URL parameters
  const searchTerm = query.q || ''; // Extract search query
  
  // Fetch fresh data from your API or database
  const response = await fetch(`https://newswave.com/api/search?q=${searchTerm}`);
  const data = await response.json();
  
  // Return props object that gets passed to your component
  return {
    props: {
      articles: data.articles,
      query: searchTerm,
      totalCount: data.total
    }
  };
}
Terminal
$ npm run dev
ready - started server on 0.0.0.0:3000
info - Loaded env from .env.local
✓ Ready in 2.1s
GET /search?q=climate - 200 (Server-side rendered)
Executed getServerSideProps in 156ms

What just happened?

Next.js executed our getServerSideProps function when someone visited the search page. The function fetched data, returned props, and Next.js rendered the complete page server-side before sending HTML to the browser. Try this: Visit /search?q=different-term to see the function run again with new parameters.

Context Object and Request Data

The context parameter provides rich information about each incoming request. Query parameters let you handle search terms, filters, and pagination. Request headers reveal user agents, geographic locations, and authentication tokens. Cookies contain user sessions and preferences that personalize content delivery.

Dynamic routes expose their parameters through context as well. A page located at pages/category/[name].js receives the category name through context.params.name. NewsWave can build category pages that fetch articles belonging to specific topics like Technology, World News, or Sports.

Request and response objects provide low-level access when needed. You can read custom headers, examine request methods, or set response headers and status codes. This flexibility enables advanced scenarios like redirects based on user authentication or geolocation-based content filtering.

// pages/category/[name].js - Dynamic category page
export async function getServerSideProps(context) {
  const { params, query, req, res } = context;
  const categoryName = params.name; // From URL path
  const page = query.page || 1; // From query string ?page=2
  const userAgent = req.headers['user-agent']; // Browser info
  
  // Fetch articles for this specific category
  const articles = await fetchArticlesByCategory(categoryName, page);
  
  return {
    props: {
      category: categoryName,
      articles: articles,
      currentPage: page,
      isMobile: userAgent.includes('Mobile')
    }
  };
}
localhost:3000/category/technology?page=1 — NewsWave

What just happened?

Our category page extracted the category name from the URL path, pagination from query parameters, and device type from request headers. All this data gets processed server-side and embedded in the HTML response. Try this: Change the URL to /category/sports?page=3 to see different parameter extraction.

Error Handling and Redirects

Server-side data fetching introduces failure scenarios that need graceful handling. API endpoints might return errors, databases could be temporarily unavailable, or authentication might fail. Your getServerSideProps function should anticipate these issues and provide meaningful responses rather than crashing.

Next.js provides several options for handling errors and edge cases. You can return notFound: true to show a 404 page when content doesn't exist. Redirect objects send users to different URLs — useful for handling authentication or deprecated content. These features let you build robust applications that handle edge cases elegantly.

NewsWave search pages might encounter scenarios where no articles match user queries. Instead of showing empty results, you could redirect to a general news page or display helpful suggestions. Authentication failures could redirect to login pages while preserving the original destination URL for post-login redirects.

// Handle errors and edge cases in getServerSideProps
export async function getServerSideProps(context) {
  const { query } = context;
  const searchTerm = query.q;
  
  // Redirect if no search term provided
  if (!searchTerm) {
    return {
      redirect: {
        destination: '/articles',
        permanent: false // Temporary redirect (307)
      }
    };
  }
  
  try {
    const articles = await searchArticles(searchTerm);
    
    // Show 404 if no results found
    if (articles.length === 0) {
      return { notFound: true };
    }
    
    return { props: { articles, query: searchTerm } };
  } catch (error) {
    // Return empty results on API failure
    return {
      props: {
        articles: [],
        query: searchTerm,
        error: 'Search temporarily unavailable'
      }
    };
  }
}
Terminal
$ curl http://localhost:3000/search
HTTP/1.1 307 Temporary Redirect
Location: /articles
✓ Redirected due to missing search term
$ curl http://localhost:3000/search?q=invalidterm
HTTP/1.1 404 Not Found
✓ Returned 404 for zero results

What just happened?

Our error handling covers three scenarios: redirecting users without search terms, showing 404 pages for empty results, and gracefully degrading when APIs fail. Next.js handles these responses automatically based on the return values. Try this: Visit /search without a query parameter to trigger the redirect behavior.

Performance Considerations

Server-side rendering trades speed for freshness. Every request waits for data fetching and HTML generation before receiving a response. While static pages serve in microseconds, server-rendered pages might take hundreds of milliseconds depending on your data sources. Users notice delays above 200ms, so optimization becomes critical for good experiences.

Database query optimization provides the biggest performance improvements. Indexing frequently-searched columns, limiting result sets, and using connection pooling reduce server processing time. NewsWave search pages should limit results to 20 articles per page rather than fetching thousands. Proper database indexes on title, category, and publication date columns speed up common queries significantly.

Caching strategies help balance freshness with performance. You can cache API responses for short periods — even 30 seconds helps when multiple users search for the same terms. Edge caching through CDNs serves content from locations closer to users. Consider using Incremental Static Regeneration for content that changes occasionally but doesn't require real-time updates.

Rendering Strategy Comparison

Static Generation

Build time rendering. Lightning fast but potentially stale data. Perfect for marketing pages.

Server-Side Rendering

Request time rendering. Slower but always fresh data. Ideal for search and user-specific content.

Real-World Implementation

Building NewsWave's search functionality demonstrates server-side rendering in practice. The search page needs to handle user queries, filter articles by relevance, implement pagination, and provide suggestions when no results appear. Each of these requirements benefits from server-side data processing and HTML generation.

User experience improves when search results appear instantly without loading states. Server-side rendering delivers complete HTML with article titles, excerpts, and metadata embedded. Search engines can index this content for better SEO rankings. Social media platforms show rich previews when users share search result pages.

// pages/search.js - Complete NewsWave search implementation
import { useState } from 'react';

export default function SearchPage({ articles, query, suggestions, totalResults }) {
  const [currentQuery, setCurrentQuery] = useState(query || '');
  
  return (
    <div className="search-page">
      <form action="/search" method="get">
        <input
          name="q"
          value={currentQuery}
          onChange={e => setCurrentQuery(e.target.value)}
          placeholder="Search NewsWave articles..."
        />
        <button type="submit">Search</button>
      </form>
      
      {query && (
        <>
          <h1>Search Results for "{query}"</h1>
          <p>{totalResults} articles found</p>
          
          {articles.map(article => (
            <article key={article.id}>
              <h2>{article.title}</h2>
              <p>{article.excerpt}</p>
              <div>
                <span>{article.category}</span>
                <span>{article.publishedAt}</span>
              </div>
            </article>
          ))}
          
          {articles.length === 0 && (
            <div>
              <p>No articles found for "{query}"</p>
              <h3>Try these suggestions:</h3>
              <ul>
                {suggestions.map(term => (
                  <li key={term}><a href={`/search?q=${term}`}>{term}</a></li>
                ))}
              </ul>
            </div>
          )}
        </>
      )}
    </div>
  );
}

export async function getServerSideProps({ query }) {
  const searchQuery = query.q || '';
  
  if (!searchQuery) {
    return {
      props: {
        articles: [],
        query: '',
        suggestions: ['Technology', 'World News', 'Climate', 'Business'],
        totalResults: 0
      }
    };
  }
  
  // Simulate API call with realistic data
  const mockArticles = [
    {
      id: 1,
      title: `Breaking: ${searchQuery} developments continue`,
      excerpt: `Latest updates on ${searchQuery} from our newsroom team covering the developing story.`,
      category: 'Breaking News',
      publishedAt: new Date().toISOString()
    },
    {
      id: 2,
      title: `Analysis: How ${searchQuery} affects global markets`,
      excerpt: `Economic experts weigh in on the implications of ${searchQuery} for international trade.`,
      category: 'Business',
      publishedAt: new Date(Date.now() - 1800000).toISOString()
    }
  ];
  
  return {
    props: {
      articles: mockArticles,
      query: searchQuery,
      suggestions: ['Technology', 'Climate Change', 'Elections', 'Science'],
      totalResults: mockArticles.length
    }
  };
}
localhost:3000/search?q=technology — NewsWave

What just happened?

We built a complete search page that handles user input, displays results, and provides fallback suggestions. The getServerSideProps function processes search queries and returns relevant articles with real-time data. Try this: The search form uses GET method to ensure URLs remain shareable and bookmarkable.

Quiz

1. NewsWave's search page uses getServerSideProps to handle user queries. What is the main trade-off of this approach?


2. When a NewsWave search returns zero articles, you want to show a 404 page. What should getServerSideProps return?


3. NewsWave has a page at /category/[name].js that handles URLs like /category/technology?page=2. How does getServerSideProps access both the category name and page number?


Up Next: Incremental Static Regeneration

Discover how to get the best of both worlds — static speed with dynamic freshness through automatic page regeneration.