Automotive Spare Parts Distribution / B2B & B2C E-commerce
- Location:
- UAE / Turkey
- Type:
- Custom Software — Wholesale E-commerce Platform (Next.js storefront + Laravel API + Filament admin backoffice)
10M+
parts migrated from spreadsheets into one database
~2.8M
reference products reconciled by the scraper pipeline
Server-side
wholesale pricing enforced per customer group
2 apps
storefront + admin, sharing one API
Overview
Client is an automotive spare-parts distributor moving its wholesale operation onto a unified digital platform. The business supplies parts across dozens of categories — engine, suspension, brakes, and more — sourced from 50+ recognized manufacturers, to both individual buyers and wholesale/dealer customers. Before this platform, catalogue and pricing data lived in per-supplier Excel spreadsheets rather than a single system of record, and wholesale customers were served through manual or offline channels rather than a self-service storefront.
The challenge
Client needed to take a catalogue in the 2–3-million-part range — previously tracked in Excel — and turn it into a searchable, price-accurate, self-service platform, without losing the wholesale pricing relationships already negotiated with different customer tiers.
- Catalogue and pricing data spread across per-supplier Excel spreadsheets, with no unified, searchable system of record
- No structured way to compare the client's own inventory against external reference sources to keep pricing and part availability current
- Every customer saw the same price — no mechanism for automatically applying different negotiated wholesale rates per customer group
- Parts identified inconsistently across suppliers (e.g. a part number logged as “3341” in one source and “003341” in another), with no cross-reference or OE-number matching
- Parts with discontinued manufacturer numbers needed their current alternate/replacement part identified and linked
- No public e-commerce channel — customers had no way to search and order directly
- Existing customers from a prior portal needed a clear path onto the new platform
Objectives
- Migrate the client's spreadsheet-based parts catalogue (10M+ SKUs) into a single searchable, indexed database
- Build a comparison/sync pipeline that cross-references external supplier data against the client's own inventory, including alternate/replacement part numbers
- Implement customer-group-based wholesale pricing so every logged-in customer automatically sees their own negotiated price
- Launch a public storefront for direct ordering, alongside a bulk search/export tool for wholesale/dealer customers
- Support OE-number and cross-reference part matching across brands and multi-currency operation
Success criteria
- A scalable architecture capable of holding and searching a 2–3M+ part catalogue
- Optimized search and filtering by part number, OE number, brand, and category
- Secure backend with wholesale pricing tiers enforced server-side, never client-editable
- Milestone-based delivery through architecture, customer management, data sync, product management, cart, order management, and final QA
Our solution
We built Client as two coordinated applications: a Next.js 16 storefront (React 19, App Router) for customers, and a Laravel 12 API paired with a Filament 3 admin backoffice for catalogue, pricing, and order management — connected over a REST API secured by Sanctum tokens. The engineering centerpiece is the data pipeline: turning a 10–12 million row Excel-based catalogue into a live, searchable, per-customer-priced database.
High-Throughput Bulk Import Pipeline
Custom-compiled C++ binaries (built on the xlsxio library) convert massive XLSX exports to CSV far faster than PHP-native parsing, then MySQL's LOAD DATA LOCAL INFILE bulk-loads the data with indexes disabled during the insert, queued and monitored through Laravel Horizon.
Supplier Comparison & Cross-Reference Engine
A scraper pipeline pulls parts data from reference platforms, resolving alternate/replacement part numbers and syncing them against the client's own inventory on a fixed schedule, with a dedicated number-normalization step.
Group-Based Wholesale Pricing
Every customer belongs to a pricing Group carrying its own rate adjustment; live search pricing is computed per request from the logged-in customer's group, with static priced export files pre-generated for wholesale customers.
Meilisearch-Backed Catalogue Search
Parts and products are indexed via Laravel Scout and Meilisearch with queued indexing, keeping search responsive over a multi-million-row catalogue.
Storefront + Dealer Backoffice Split
A public Next.js storefront sits alongside a gated backoffice tool for staff/dealer bulk search and CSV/XLSX export, plus a Filament admin panel with role-based access.
Key capabilities
- OE-number and cross-reference-number matching across brands
- Alternate/replacement part linking for discontinued manufacturer numbers
- Multiple supplier prices tracked per part, with the correct one selected per customer group
- Abandoned-cart tracking, printable and PDF-exportable cart
- Queue-monitored import, indexing, and export jobs via Laravel Horizon
- Google and Facebook OAuth login alongside email/password
Architecture & tech stack
The platform is a modular monolith split across two deployable applications — a Next.js storefront and a Laravel API with an embedded Filament admin panel — backed by MariaDB, Redis, and a dedicated Meilisearch service, with Laravel Horizon monitoring the import, indexing, and export queues.
- Frontend: Next.js 16 (React 19), App Router, Zustand for cart/user state, Bootstrap 5 + styled-jsx
- Backend: Laravel 12, PHP 8.3, Filament 3 admin panel with Filament Shield RBAC
- Database: MariaDB, Redis-backed cache and queue in production
- Search: Laravel Scout + Meilisearch, queued indexing
- Import Pipeline: custom C++ (xlsxio-based) XLSX↔CSV converters, MySQL LOAD DATA LOCAL INFILE
- Queue/Jobs: Laravel Horizon
- Authentication: Laravel Sanctum (API tokens) + NextAuth v4 (JWT) on the frontend
| Frontend | Next.js 16, React 19, App Router, Zustand, Bootstrap 5 |
|---|---|
| Backend | Laravel 12, PHP 8.3 |
| Admin Panel | Filament 3 + Filament Shield (RBAC) |
| Database | MariaDB |
| Cache / Queue | Redis, Laravel Horizon |
| Search | Laravel Scout + Meilisearch |
| Import Pipeline | Custom C++ (xlsxio), MySQL LOAD DATA LOCAL INFILE |
| Authentication | Laravel Sanctum, NextAuth v4, Socialite (Google/Facebook) |
| Testing | Pest 3 (backend), Cypress (frontend e2e) |
Key features
High-Throughput Bulk Import Pipeline
Bringing a 10–12 million row, Excel-based catalogue into a live database ruled out standard PHP-native XLSX parsing on performance grounds, so we built custom C++ binaries on the xlsxio library and bulk-loaded the result with MySQL's LOAD DATA LOCAL INFILE.
Supplier Comparison & Cross-Reference Matching
A scheduled scraper pipeline reconciles external reference data against the client's own inventory, resolving alternate/replacement part numbers with a dedicated normalization step.
Group-Based Wholesale Pricing
Every customer belongs to a pricing group applied server-side at query time, so the price a customer sees is always correct for their tier, with pre-generated per-group export files for bulk download.
Storefront + Dealer Bulk Tooling
Alongside the public storefront, a gated backoffice tool lets staff and dealer accounts search by part key or upload a CSV/XLSX of part numbers and export matched results back to Excel.
Results
The implementation replaced a spreadsheet-based catalogue and manual wholesale pricing with a searchable, self-service platform enforcing pricing automatically per customer.
| Area | Before | After | Improvement |
|---|---|---|---|
| Catalogue Management | Per-supplier Excel spreadsheets, manually reconciled | Centralized, searchable database covering 10M+ parts | 10M+ parts indexed |
| Wholesale Pricing | Same price shown to every customer, applied manually | Automatic per-customer pricing via customer Groups, enforced server-side | Fully automated |
| Part Matching | Manual lookup across differently formatted part/OE numbers | Automated OE and cross-reference matching with number normalization | Automated |
| Catalogue Freshness | No structured way to compare internal data against external listings | Scheduled scraper sync reconciling ~2.8M reference products against inventory | ~2.8M products synced |
| Ordering Channel | Manual/offline ordering only | Self-service storefront plus a dedicated bulk search/export tool for dealers | New self-service channel |
A catalogue that's actually searchable
A 10M+ row catalogue that lived in spreadsheets is now indexed and queryable in real time, instead of requiring a manual lookup per supplier file.
Wholesale pricing enforces itself
Customer-group pricing is computed server-side on every request, removing the risk of manually applying the wrong rate to the wrong customer.
A catalogue that stays current
The scraper pipeline continually reconciles the client's inventory against external reference data, at a measured throughput of roughly 4 products/second across a target of ~2.8M reference products.
A genuine self-service channel
Customers can now search and order directly through the storefront, while wholesale/dealer accounts get a dedicated bulk search and export workflow.
Challenges & how we solved them
- Parsing and importing XLSX files at a 10–12 million row scale, where pure PHP parsing could not keep pace with the client's data volume
- Bulk-loading pricing data without database timeouts or lock contention across millions of rows
- Reconciling part numbers formatted inconsistently across suppliers and scraped sources
- Scoping the scraper against evolving client requirements — which price takes precedence, whether to scrape alternate/discontinued parts, and how far the crawl should extend
For import performance, we stepped outside PHP's native XLSX tooling and built dedicated C++ binaries against the xlsxio library purely for the parsing step, keeping the rest of the pipeline in Laravel. For the database load itself, we used MySQL's LOAD DATA LOCAL INFILE with indexes disabled during the insert and a temp-table join for price linking, rather than ORM-driven row-by-row inserts. Part-number inconsistency was solved with a dedicated normalization column and console command. Requirement ambiguities around the scraper were resolved through direct, documented client Q&A captured against the project plan.
Security & compliance
- Laravel Sanctum token authentication for the customer-facing API, separate from the Filament admin's own session guard
- Spatie Permission + Filament Shield role-based access control on every admin panel resource
- Bulk search/export functionality gated behind dedicated backoffice-access middleware
- Google and Facebook OAuth (Socialite) offered as an alternative to password-based login
Scalability & roadmap
- Frontend search/autocomplete (typeahead, faceted filters) to match the backend's Meilisearch capability
- Multi-language storefront rollout alongside broader multi-currency display
- Online payment gateway integration, moving beyond the current invoice/offline-payment order flow
- Expanding scraper coverage to additional supplier/reference platforms
- A defined migration path for existing customers from the client's prior portal onto Client
Why the client chose us
- Willingness to build custom tooling (C++ parsing binaries, raw bulk-load SQL) when standard framework tooling hits a genuine scale ceiling
- Experience designing tiered B2B pricing logic that's enforced server-side, not bolted on as a display-layer convenience
- Full-stack capability across Next.js, Laravel, and Filament, needed to deliver a storefront, API, and admin backoffice as one coherent platform
- Milestone-based delivery with requirement ambiguities resolved through direct, documented client conversation rather than assumption
- A pragmatic approach to data engineering at scale — chunked concurrency, disabled-key bulk loads, and normalization strategies suited to a 10M+ row catalogue
Client needed to turn a spreadsheet-based, 10–12-million-part catalogue into a searchable, self-service wholesale platform without losing the pricing relationships already negotiated with its customers. Client replaces manual catalogue reconciliation and pricing with an automated pipeline: a purpose-built import path brings the data in at scale, a scheduled scraper keeps it reconciled against external sources, and every customer automatically sees the price that applies to their tier.
