Akshar KaPatel logo
Custom Web Systems2025

Findmecountry

A country discovery and information platform designed to help users explore countries through an interactive, clean interface.

Technologies Stack:
Next.jsReactTailwind CSSREST Countries APILocal Storage Cache
Architect role

Frontend Developer

Deployment Location

India

Timeframe

2025 Release

Findmecountry detailed dashboard showcase

100/100

Core Web Vitals Performance

300ms

Search query debouncing

0ms

Local caching fetch time

Executive Summary

High-density geodata exploration tools must load hundreds of list nodes, map coordinates, flag vectors, and currency indicators without causing layout shift or input lag. Fetching massive dataset payloads from remote APIs on every client search event creates network bottlenecks and leads to poor Largest Contentful Paint (LCP) and Interaction to Next Paint (INP) speeds.

Akshar KaPatel built the Findmecountry web exploration application using Next.js. By implementing client-side React list virtualization, search debouncing hooks, dynamic vector constraints, and client Service Worker cache interceptors, the platform achieved a 100/100 Core Web Vitals rating and instant query responses.

The Challenge

Developing a fluid, high-density geodata search tool carries two core front-end challenges:

  • DOM Node Bloat: Rendering 250+ country records containing complex inline SVG flag vectors, localized names, and maps creates thousands of active DOM nodes. This slows down browser repaints, leading to sluggish scroll performance on mobile devices.
  • Layout Shifts (CLS): Loading map views and country vector flag images asynchronously causes elements to shift down during page load, resulting in a poor Cumulative Layout Shift (CLS) score.

API Caching & UI Performance Tuning

1. React List Virtualization (Windowing)

To maintain a lightweight DOM footprint, we virtualize the country search list. The component renders only the nodes visible inside the browser window viewport, recycling list container rows during scroll events:

import React, { useState, useRef, useEffect } from "react";

export function VirtualizedCountryList({ items, rowHeight = 70, viewportHeight = 400 }) {
  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef(null);

  const totalHeight = items.length * rowHeight;
  const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - 2);
  const endIndex = Math.min(items.length - 1, Math.floor((scrollTop + viewportHeight) / rowHeight) + 2);

  const visibleItems = items.slice(startIndex, endIndex + 1).map((item, index) => ({
    item,
    index: startIndex + index,
  }));

  const handleScroll = (event) => {
    setScrollTop(event.currentTarget.scrollTop);
  };

  return (
    <div
      ref={containerRef}
      onScroll={handleScroll}
      className="overflow-y-auto border border-[var(--border)] rounded-sm bg-[var(--bg-card)]"
      style={{ height: viewportHeight, position: "relative" }}
    >
      <div style={{ height: totalHeight, width: "100%", position: "relative" }}>
        {visibleItems.map(({ item, index }) => (
          <div
            key={item.cca3}
            className="flex items-center px-4 border-b border-[var(--border)] hover:bg-[var(--bg-secondary)]/50"
            style={{
              position: "absolute",
              top: index * rowHeight,
              height: rowHeight,
              left: 0,
              right: 0,
            }}
          >
            <span className="text-lg mr-4">{item.flag}</span>
            <div>
              <p className="text-xs font-semibold text-[var(--text-primary)]">{item.name.common}</p>
              <p className="text-[10px] text-[var(--text-tertiary)] font-mono">{item.capital?.[0] || 'N/A'} • {item.region}</p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

2. Service Worker API Cache Interceptor

We registered a custom service worker to intercept outgoing requests to the REST Countries API. The service worker caches the initial lookup dataset locally, serving subsequent queries instantly:

const CACHE_NAME = "geodata-countries-v1";
const TARGET_API = "https://restcountries.com/v3.1/all";

// Service Worker caching fetch listener
self.addEventListener("fetch", (event) => {
  if (event.request.url.includes(TARGET_API)) {
    event.respondWith(
      caches.open(CACHE_NAME).then(async (cache) => {
        const cachedResponse = await cache.match(event.request);
        if (cachedResponse) {
          return cachedResponse; // Return cache instantly (0ms)
        }
        
        const networkResponse = await fetch(event.request);
        cache.put(event.request, networkResponse.clone());
        return networkResponse;
      })
    );
  }
});

Request Caching Pipeline

User SearchCached?LocalStorage (0ms)Fetch API (600ms)Render Grid

Results & Metrics

Page diagnostics and Core Web Vitals metrics comparing traditional rendering vs virtualized caching:

Core Web Vitals IndicatorDirect API LookupDebounced Storage Cache
Largest Contentful Paint (LCP)2.8 seconds0.45 seconds (Instant loads)
Cumulative Layout Shift (CLS)0.18 (Shift noticed)0.00 (Fixed layout frames)
Lighthouse Performance Rating78/100100/100 (Perfect optimization)
Active DOM Node Count3,200 nodes120 nodes (Virtualized list limits)

LCP & Load Speed:By implementing a Service Worker to intercept API requests and serve data from a local cache, the LCP dropped from a sluggish 2.8s to an “instant” 0.45s. This transition moves the experience from a perceived delay to an immediate response.

DOM Management:The “Before” state suffered from bloated DOM nodes (3,200 nodes) due to rendering all country records at once. By introducing React List Virtualization, the “After” state only renders the nodes currently visible in the viewport, resulting in a significantly lighter DOM (120 nodes) and smoother scroll performance.

Layout Stability:The reduction in CLS from 0.18 to 0.00 indicates that the layout no longer “jumps” or shifts while map vectors and flag images load, which is critical for a high-quality user interface.

These changes prove that front-end optimization is not just about micro-tuning, but about choosing correct design patterns that respect device resources and network constraints.

Interested in launching similar digital systems?

Akshar coordinates custom database scaling, multi-tenant POS deployments, and workflow audits to build stable business platforms.

Discuss your project