https://github.com/anas-farooq8/lightspeed-shopsync
Product sync tool for Lightspeed eCom shops. Sync products across multiple stores with translation, preview, and manual control.
https://github.com/anas-farooq8/lightspeed-shopsync
ecom ecommerce lightspeed multi-store nextjs product-sync react supabase sync-tool translation
Last synced: 2 months ago
JSON representation
Product sync tool for Lightspeed eCom shops. Sync products across multiple stores with translation, preview, and manual control.
- Host: GitHub
- URL: https://github.com/anas-farooq8/lightspeed-shopsync
- Owner: anas-farooq8
- Created: 2026-02-03T10:34:54.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-09T15:47:38.000Z (3 months ago)
- Last Synced: 2026-03-09T20:54:41.787Z (3 months ago)
- Topics: ecom, ecommerce, lightspeed, multi-store, nextjs, product-sync, react, supabase, sync-tool, translation
- Language: TypeScript
- Homepage: https://lightspeed-shopsync.vercel.app
- Size: 728 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Lightspeed ShopSync
> A web-based product sync tool for syncing products between Lightspeed eCom shops using the Lightspeed API. Built for multi-store e-commerce operations with full translation support and manual control over every sync operation.
[](https://vercel.com)
[](https://nextjs.org)
[](https://react.dev)
[](https://supabase.com)
[](https://www.typescriptlang.org)
[](https://tailwindcss.com)
[](https://github.com/features/actions)
[](https://developers.lightspeedhq.com/ecom/introduction/introduction/)
---
## Overview
Lightspeed ShopSync enables seamless product synchronization across multiple Lightspeed eCom storefronts. Designed for businesses operating in multiple regions (e.g., .nl, .de, .be), it provides a manual, user-controlled workflow with preview-before-sync, automatic translation, and intelligent handling of duplicate SKUs.
### Core Philosophy
- **Manual sync only** - Nothing syncs automatically; you decide what to create, update, or skip
- **Source of truth** - One shop (e.g., .nl) is the source; all sync flows from it
- **Product-level sync** - Variants are synced as a unit, preserving product structure
- **Full control** - Edit content, select variants, and choose target shops before any operation
---
## Features
### Sync Operations
| Tab | Purpose |
|-----|---------|
| **CREATE** | Create missing products in target shops from source |
| **EDIT** | Update existing products in target shops with source data |
| **NULL SKU** | Handle products with missing default SKUs (shop-specific edits) |
### Smart Matching & Duplicate Handling
- **Product-level matching** using variant SKU as the key
- **Duplicate detection** in both source and target shops
- **Scenario support**: 1-1, M-1, M-M, 1-M (with source/target selectors)
- **Match type indicators**: Default variant vs non-default variant (structure mismatch)
### Translation System
- **Automatic translation** via Google Cloud Translation API (NL → DE, FR)
- **Identical copy** for same-language targets (e.g., NL → NL on .be)
- **Preview before sync** — All translations visible and editable
- **Manual edit protection** — User edits are never overwritten
- **Re-translate** — Per field or entire language
- **Session-based caching** — Efficient batching by language pair
### Dashboard & UX
- KPI cards per shop with sync status
- Last sync metrics and timestamps
- Tabbed interface with CREATE, EDIT, NULL SKU
- Table and grid view modes
- Server-side pagination, search, sorting, filtering
- URL state management — Filters and navigation preserved
- Responsive design with shadcn/ui components
---
## Tech Stack
- **Framework**: Next.js 16.1, React 19.2
- **Database**: Supabase (PostgreSQL)
- **Auth**: Supabase Auth (email/password, signup disabled)
- **Styling**: Tailwind CSS, shadcn/ui, Radix UI
- **APIs**: Lightspeed eCom API, Google Cloud Translation API
---
## Shops Configuration
The project is **dynamic** and supports multiple shops. Shops are configured in the database and via environment variables (`LIGHTSPEED_API_KEY_{TLD}`, `LIGHTSPEED_API_SECRET_{TLD}`). One shop acts as the source of truth; others are targets. Example setup:
| Shop | Store # | URL | Role | Languages |
|------|----------|-----|------|-----------|
| VerpakkingenXL | #293467 | verpakkingenxl.nl | **SOURCE** | NL |
| VerpackungenXL | #293470 | verpackungenxl.de | TARGET | DE |
| VerpakkingenXL-BE | #343623 | verpakkingenxl.be | TARGET | NL, FR |
---
## Getting Started
### Prerequisites
- Node.js 18+
- Supabase account
- Lightspeed eCom API credentials
- Google Cloud Translation API key (optional, for auto-translation)
### Installation
```bash
# Clone the repository
git clone https://github.com/anas-farooq8/Lightspeed-ShopSync.git
cd Lightspeed-ShopSync
# Install dependencies
npm install
# Set up environment variables (see below)
cp .env.example .env.local
```
### Environment Variables
Copy `.env.example` to `.env.local` and fill in your values:
```env
# Supabase
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url_here
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here
# App URL (optional)
# Local: http://localhost:3000
# Deployment: https://your-app.vercel.app
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Lightspeed eCom API (per shop TLD: NL, DE, BE)
LIGHTSPEED_API_KEY_NL=your_lightspeed_api_key_here
LIGHTSPEED_API_SECRET_NL=your_lightspeed_api_secret_here
LIGHTSPEED_API_KEY_DE=your_lightspeed_api_key_here
LIGHTSPEED_API_SECRET_DE=your_lightspeed_api_secret_here
LIGHTSPEED_API_KEY_BE=your_lightspeed_api_key_here
LIGHTSPEED_API_SECRET_BE=your_lightspeed_api_secret_here
# Google Cloud Translation API (Service Account)
# Grant role: Cloud Translation API User
# Enable: https://console.cloud.google.com/apis/library/translate.googleapis.com
GOOGLE_TYPE=service_account
GOOGLE_PROJECT_ID=project-id
GOOGLE_PRIVATE_KEY_ID=project-private-key-id
GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nyour-private-key\n-----END PRIVATE KEY-----\n"
GOOGLE_CLIENT_EMAIL=service-account-email
GOOGLE_CLIENT_ID=client-id
GOOGLE_AUTH_URI=https://accounts.google.com/o/oauth2/auth
GOOGLE_TOKEN_URI=https://oauth2.googleapis.com/token
GOOGLE_AUTH_PROVIDER_CERT_URL=https://www.googleapis.com/oauth2/v1/certs
GOOGLE_CLIENT_CERT_URL=google-client-cert-url
GOOGLE_UNIVERSE_DOMAIN=googleapis.com
```
### Database Setup
Run the SQL scripts in order (see `scripts/` folder):
1. `01-init-schema.sql` — Tables, indexes, RLS, triggers
2. `02-rpc-functions.sql` — Dashboard KPIs, sync log functions
3. `03-product-sync-view.sql` — Product sync status view
4. `04-sync-operations-rpc.sql` — Sync operations RPC
5. `05-product-details-rpc.sql` — Product details RPC
### Run the App
```bash
# Development
npm run dev
# Production build
npm run build
npm start
```
### Data Sync
**Option 1: Manual (local)**
```bash
# Requires Python 3.11+ and pip install -r requirements.txt
python scripts/sync.py
```
**Option 2: GitHub Actions (automated)**
A scheduled workflow syncs products daily via `.github/workflows/sync-cron.yml`:
- **Schedule:** Runs daily at 00:05 UTC
- **Manual trigger:** Available from the GitHub Actions tab (`workflow_dispatch`)
- **Secrets required:** `NEXT_PUBLIC_SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, and per-shop `LIGHTSPEED_API_KEY_{TLD}`, `LIGHTSPEED_API_SECRET_{TLD}` (e.g. NL, DE, BE)
Configure secrets in **Settings → Secrets and variables → Actions**.
---
## Project Structure
```
├── app/
│ ├── api/ # API routes
│ │ ├── create-product/ # POST - Create product in target shop
│ │ ├── last-product-operation/ # GET - Last 10 product ops (dashboard)
│ │ ├── last-sync/ # GET - Last sync info per shop
│ │ ├── product-details/ # GET - Product by SKU or product ID
│ │ ├── product-images/ # GET - Fetch images from Lightspeed API
│ │ ├── product-operation-logs/ # GET - Paginated create/edit logs
│ │ ├── shops/ # GET - All shops (source + target)
│ │ ├── stats/ # GET - Dashboard KPIs
│ │ ├── sync-logs/ # GET - Paginated sync logs by date
│ │ ├── sync-operations/ # GET - Paginated CREATE/EDIT/NULL SKU
│ │ ├── translate/ # POST - Batch translation (Google)
│ │ └── update-product/ # PUT - Update product in target shop
│ ├── dashboard/ # Protected dashboard pages
│ │ ├── product-sync-logs/ # Product operation logs
│ │ ├── sync-logs/ # Shop sync logs
│ │ └── sync-operations/ # CREATE, EDIT, NULL SKU tabs
│ │ ├── preview-create/[sku]/ # Create flow
│ │ ├── preview-edit/[sku]/ # Edit flow
│ │ ├── product/[productId]/ # Null SKU product view
│ │ └── products/[sku]/ # SKU-based product view
│ ├── login/ # Auth page
│ └── layout.tsx
├── components/
│ ├── sync-operations/ # Tabs, dialogs, product list, panels
│ ├── sync-logs/ # Sync log cards
│ ├── product-sync-logs/ # Product operation logs
│ ├── dashboard/ # Stats, last sync, KPIs
│ ├── shared/ # Shared product operation components
│ └── ui/ # shadcn/ui components
├── lib/
│ ├── services/ # create-product, update-product, translation, lightspeed-api, image-handler
│ ├── supabase/ # Client & server Supabase
│ ├── cache/ # Product images cache
│ ├── constants/ # Product UI constants
│ └── api.ts # API helpers
├── hooks/ # useProductEditor, useProductNavigation
├── types/ # database, product, lightspeed-api
├── scripts/ # SQL schema (01–05), sync.py
├── .github/workflows/
│ └── sync-cron.yml # Daily Lightspeed sync (00:05 UTC)
```
---
## API Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/stats` | Dashboard KPI statistics per shop |
| GET | `/api/last-sync` | Last sync information per shop |
| GET | `/api/shops` | All shops (source + target) |
| GET | `/api/sync-operations` | Paginated sync operations (CREATE/EDIT/NULL SKU) |
| GET | `/api/product-details` | Product details by SKU or product ID |
| GET | `/api/product-images` | Fetch product images from Lightspeed API (link, shopTld) |
| GET | `/api/product-operation-logs` | Paginated create/edit operation logs |
| GET | `/api/last-product-operation` | Last 10 product operations (dashboard) |
| GET | `/api/sync-logs` | Paginated sync logs grouped by date |
| POST | `/api/create-product` | Create product in target shop(s) |
| PUT | `/api/update-product` | Update product in target shop |
| POST | `/api/translate` | Batch translation (Google Cloud Translation API) |
---
## Data Synced
**In scope:** Title, variant title, description, content (HTML), selling price, images, variants
**Out of scope:** Stock levels, delivery info, category structure
---
## License
Private project. All rights reserved.