Own the shopfront. Keep ERPNext as the truth.
An open-source Vendure shop in front of ERPNext: the shop does what shops are good at (product pages, cart, checkout, promotions) and ERPNext keeps items, prices, stock, customers, orders, invoices and warranties. Nothing is typed in twice and there is no second source of truth to reconcile at month-end.
01 · When to choose it
For consumer brands that want a real store they own outright, with no platform fee and no per-order cut, while stock and pricing stay in ERPNext. When it isn't the right fit, we say so:
| If you… | Build instead |
|---|---|
| sell B2B to logged-in trade customers | ERPNext's own Webshop + Frappe Builder: no sync at all, and customer pricing comes free |
| have a small catalogue and simple promotions | a light custom storefront over the ERPNext API |
| want Shopify's checkout and app store | Shopify, with ERPNext pushing stock and price to it (see the Shopify offer) |
| want the shop, not ERPNext, to own pricing | a full commerce engine (Medusa, Saleor), accepting a two-way sync |
02 · Who owns what
One rule makes the whole thing work: ERPNext is master for everything the business counts. The shop presents it and takes the money.
| Data | Master | In the other system |
|---|---|---|
| Items, sizes, specs | ERPNext | Vendure products, read-only |
| Selling price incl. VAT | ERPNext price list | Vendure price, overwritten on every sync |
| Stock | ERPNext, per warehouse | Vendure stock, plus "3 in Johannesburg · 1 in Cape Town" on the page |
| Cart, checkout, shopper session | Vendure | — |
| Payment | the gateway, via Vendure | ERPNext payment receipt into a gateway clearing account |
| Customer, order, delivery, invoice, warranty | ERPNext | Vendure keeps its order and the ERPNext order number |
03 · What runs where
About 290 MB of memory for the whole shop tier. It runs beside ERPNext on the same server, or on its own small VM.
04 · The ERPNext side
- Prices include VAT. A sales tax template with VAT included in the rate, so the website, the Sales Order and the invoice agree to the cent.
- Sizes are variants. One template, one variant per size; the ERPNext item code is the shop SKU.
- Website fields on Item: publish flag, tagline, spec pills, badge, compare-at price, warranty text. Only published items reach the shop.
- A gateway clearing account. Web payments land there, and gateway payouts reconcile into the bank.
- Serial numbers where there's a warranty: recorded at receipt, picked at delivery, so "who has frame 0004?" is one lookup.
- A narrow API user for the shop: it can read items, prices and stock, and create customers, sales orders and payment receipts. Nothing more.
- Imports done properly: factory orders in USD, a clearing-agent invoice for freight, duty and port charges, and a landed cost voucher that puts them into stock value. The shop's margin is real, not FOB.
All of it is configuration-as-code: scripts that build the setup on a fresh site and check it, so a client's version is a re-run on their data, not a fresh build.
05 · The Vendure side
- Pinned, hardened scaffold: Vendure 3.7 on Postgres in Docker, with South African base data (ZAR, the South Africa zone, VAT 15% and zero-rated) and test mailboxes and debug tools off in production.
- The ERPNext plugin, about 450 lines:
- Pull: published items, VAT-inclusive prices and per-warehouse stock. It runs on start, every five minutes and after every order, and matching on item code means it never duplicates.
- Push: once a payment settles, it finds or creates the customer (with contact and address), creates a submitted Sales Order at the website's prices and a payment receipt against it, then refreshes stock.
- Stock without double counting. A paid order is held in both systems until delivery, so the sync adds Vendure's own allocations back onto ERPNext's free stock.
- The storefront is replaceable. We ship a working store page, and a client build can use the Vendure Next.js starter or their agency's front end. The plugin doesn't care which.
06 · How we prove it
| Check | Result on the demo build |
|---|---|
| Trial balance, stock vs ledger, goods-received and import charges cleared | pass |
| One serial per frame; shelf stock = active serials, size by size | pass 26 of 26 |
| Web price incl. VAT = Sales Order = invoice; VAT = 15/115 | pass |
| Paid web order → ERPNext Sales Order + payment receipt | pass in seconds |
| Delivery picks a frame serial; invoice settled from the web payment; shop stock drops | pass |
Landed cost on the demo range came to R29k–R39k per bike against R39k–R52k retail ex VAT. The demo prices are placeholders, but the arithmetic is the real thing.
07 · From demo to live
What a production build adds to the demo:
- A real payment gateway (PayFast, Yoco, Peach or Paystack), with webhook settlement, fees booked, and payouts reconciled.
- A guaranteed order push: queued with retries and keyed on the shop order number, so a retry never creates a second Sales Order. Failed pushes are visible in the admin.
- Delivery back to the shopper: ERPNext delivery → "shipped" email with tracking; cancellations and refunds in both directions.
- A live price and stock check at checkout, if stock moves faster than every five minutes.
- Go-live hygiene: database migrations, email, nightly backups, monitoring, and POPIA consent at checkout.
08 · Effort and licence
| Stage | Indicative days |
|---|---|
| ERPNext catalogue, prices, stock and import costing on your data | 2–4 |
| Plugin hardening: queue, idempotency, delivery sync, refunds | 3–5 |
| Payment gateway and reconciliation | 2–3 |
| Storefront on your design (starter or agency front end) | 5–10 |
| Go-live: migrations, email, backups, monitoring, handover runbook | 2–3 |
These are indicative ranges, firmed up in the proposal once the catalogue and design are known. Licence: Vendure Core is open source (GPLv3, with an exception that lets plugins carry their own licence). Running your shop is not distribution, so there is no licence fee and no per-order cut. Vendure's paid Platform edition is only needed for its packaged B2B features, which ERPNext already provides here.
09 · What we learned building it
| Snag | Fix |
|---|---|
| ERPNext refuses a price on a template item | Price each size variant |
| The shop user can't read prices or stock | A small read-only role on top of the standard ones, not wider standard roles |
| Orders created through the API arrive without VAT rows | Send the tax rows with the order |
| Serial-number errors on transfers and deliveries | Let ERPNext pick serials first-in-first-out on outward moves; set them only on receipt |
| Shop debug mailbox visible in production | Development-only tools are switched off outside development |
| One bad tunnel rule took every hostname offline | The catch-all rule goes last; validate the config before restarting; health alerts on |