# Next.js Integration Guide

> Engineer high-performance UAE property portals. Use Next.js Server Components, ISR, and API route proxying to deliver real-time real estate data securely.

Source: https://uaepropertyapi.com/guides/nextjs

## Introduction

Next.js is the gold standard for building SEO-optimized real estate portals in the UAE. By leveraging Server Components and Incremental Static Regeneration (ISR), you can deliver lightning-fast property listings while keeping your Property Finder APIs and Datasets credentials secure on the server.

This guide explores professional patterns for fetching, caching, and rendering large-scale UAE real estate data (via Property Finder) within the Next.js App Router (v14+).

## Architecture: Server-Side Integrity

In a production PropTech app, you should never expose your RapidAPI key to the client. We recommend centralizing your API logic in a server-only utility layer.

### 1. The Core API client

```typescript
// src/lib/market-api.ts
const BASE_URL = "https://uae-real-estate-property.p.rapidapi.com";

const headers = {
  "x-rapidapi-key": process.env.RAPIDAPI_KEY!,
  "x-rapidapi-host": "uae-real-estate-property.p.rapidapi.com",
};

export async function getMarketListings(params: Record<string, string>) {
  const query = new URLSearchParams(params).toString();
  
  const res = await fetch(`${BASE_URL}/search-buy?${query}`, {
    headers,
    next: { revalidate: 3600 }, // Global cache for 1 hour
  });

  if (!res.ok) throw new Error("Critical Market Data Failure");
  return res.json();
}
```

## Implementation: SEO-Optimized Property Feed

Render thousands of listings with zero client-side JavaScript overhead. This pattern ensures search engines can fully index your properties for maximum SEO ranking.

```typescript
// src/app/dubai-properties/page.tsx
import { getMarketListings } from "@/lib/market-api";

export default async function PropertyPortal({ searchParams }: { searchParams: { page?: string }}) {
  const page = searchParams.page || "1";
  
  // High-performance server-side fetch
  const { data, total_count } = await getMarketListings({
    location_id: "1", // General Dubai ID
    page: page
  });

  return (
    <section className="container py-12">
      <h1 className="text-4xl font-extrabold tracking-tight">Active UAE Inventory</h1>
      <p className="mt-2 text-muted-foreground">{total_count.toLocaleString()} listings verified.</p>
      
      <div className="mt-8 grid md:grid-cols-3 gap-6">
        {data.map((p: any) => (
          <div key={p.property_id} className="group overflow-hidden rounded-xl border bg-card">
            <div className="p-4">
              <h2 className="line-clamp-1 font-bold">{p.title}</h2>
              <p className="text-2xl font-black text-primary mt-2">
                {p.price.currency} {p.price.value.toLocaleString()}
              </p>
              <div className="mt-4 flex gap-4 text-sm text-muted-foreground">
                <span>{p.bedrooms} Beds</span>
                <span>{p.bathrooms} Baths</span>
                <span>{p.size.value} {p.size.unit}</span>
              </div>
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}
```

## Handling Market Volatility: Incremental Static Regeneration

The UAE market moves fast, but not every millisecond. Use ISR to pre-render popular community pages (like "Downtown Dubai" or "Dubai Marina") and refresh them in the background.

```typescript
// src/app/community/[id]/page.tsx

// Re-generate the page at most once every 30 minutes
export const revalidate = 1800; 

export async function generateStaticParams() {
  const topCommunities = ["41", "50", "86"]; // Downtown Dubai, Dubai Marina, Palm Jumeirah
  return topCommunities.map((id) => ({ id }));
}

export default async function CommunityPage({ params }: { params: { id: string } }) {
  const { data } = await getMarketListings({ location_id: params.id });
  // Render high-fidelity community view...
}
```

## Client-Side Interactivity with API Routes

If you need a client-side search or filter without showing your API key, proxy the request through a Next.js API route.

```typescript
// src/app/api/search/route.ts
import { NextResponse } from "next/server";

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const q = searchParams.get("q");

  const res = await fetch(`https://uae-real-estate-property.p.rapidapi.com/autocomplete-location?query=${encodeURIComponent(q ?? "")}`, {
    headers: {
      "x-rapidapi-key": process.env.RAPIDAPI_KEY!,
      "x-rapidapi-host": "uae-real-estate-property.p.rapidapi.com",
    }
  });

  const data = await res.json();
  return NextResponse.json(data);
}
```

## Next Implementation Steps

1.  **UI Library**: Pair this with **Shadcn UI** for stunning property cards.
2.  **State Management**: Use **URL search params** for filters (Price/Beds) to keep your pages shareable and SEO-friendly.
3.  **Visualization**: Check the [Python Guide](/guides/python) if you need to build custom analytical charts for your Next.js dashboard.
