All projects

Freelance2026

3S Auto Parts

A server-rendered Next.js storefront for car parts, with a strict Route → Query → Mapper → UI data architecture.

Rendering
SSR
Data layers
4
i18n
Server-side lang

01Overview

3S Auto Parts is an online store for car parts: categories, promotions, and products listed by brand and by the car make and model they fit.

Its frontend talks to a backend whose JSON shape is not under the frontend's control. The goal: UI components always read stable keys, even when the API changes.

02The problem

When components read raw API fields directly, every backend rename breaks the UI in many places, and components fill up with fallback logic like raw?.name ?? raw?.title ?? "".

03Architecture

Each layer has one responsibility, and only the mapper knows what the backend JSON looks like.

UI

Sections & cards

Read stable keys only - no fallbacks

Route

Server page.jsx

Resolve language, call queries, pass props

Query

*.query.js

Request + extract + map + filter

Mapper

*.mapper.js

Raw JSON → UI shape with defaults

Transport

ApiService

HTTP client

apiRoutes

Endpoint constants

04Components

Mappers

The only place that knows the API shape

  • Start from a defaults object, copy known fields, derive display values (counts, hrefs).

Queries

One function per endpoint

  • Remove repeated request/extract code and drop invalid items before they reach the UI.

Routes

Server-side composition

  • Fetch on the server with the user's language and fall back to an empty list on failure, so a broken endpoint never breaks the page.

05How it works

  1. 1

    Route

    The server page resolves the language and calls a query.

  2. 2

    Query

    Requests the endpoint via ApiService and extracts res.data.data.

  3. 3

    Mapper

    Converts each raw item to the stable UI shape.

  4. 4

    UI

    Receives props and renders cat.name, cat.image, cat.items, cat.href.

06Technical deep dives

A mapper with defaults

If the backend renames orderCount, only this function changes - every component keeps reading items.

src/mappers/popular-category.mapper.jsjs
const PopularCategoryDefaults = {
  id: null, name: "", image: "", items: "(0 Items)", href: "/products",
};

export function mapPopularCategory(raw = {}) {
  return {
    ...PopularCategoryDefaults,
    id: raw?.id ?? PopularCategoryDefaults.id,
    name: raw?.name ?? PopularCategoryDefaults.name,
    image: raw?.image ?? PopularCategoryDefaults.image,
    items: `(${Number(raw?.orderCount ?? 0) || 0} Items)`,
    href: raw?.id != null
      ? `/products?categoryId=${encodeURIComponent(String(raw.id))}`
      : PopularCategoryDefaults.href,
  };
}

07Design decisions

Anti-corruption layer

The mapper isolates the UI from an external API - a classic domain-driven design pattern applied to the frontend.

Fail soft on the server

A failing query returns an empty list; the page still renders.

08Tech stack

Frontend
Next.js (App Router)ReactJavaScriptBootstrap gridSSR

Next case study

Diaspor.org

A multi-tenant publishing platform: a branded news site for every diaspora organisation, and one national feed.