If you run your business on Odoo and you want to sell online, the demo will always work. Someone will connect to your instance, pull a list of products onto a page, and show you a working catalogue inside a day. That demo is real, and it is also the easiest 5% of the job.
We built a consumer storefront and a Flutter mobile app for SG-Mart, one of Egypt's largest nut and dry-goods distributors, running live off their existing Odoo instance — more than 110 product categories, in Arabic and English, across web, iOS and Android. Here is what took the engineering, in the order it hurt.
Tax has to be exactly right on every single line
Not approximately right. Odoo computes tax against tax groups, fiscal positions and rounding rules that were configured for how the business already invoices — and your storefront has to reproduce that answer to the piastre, not approximate it.
The failure mode is quiet. A rounding difference that nobody notices for three weeks becomes a reconciliation problem that takes days to unpick, because by then it is spread across hundreds of orders and the finance team is comparing two systems that disagree by a few pounds per invoice.
The ERP is the authority on tax. The storefront never calculates it independently — it asks, and it displays what it is told.
Prices are not one number
Odoo price lists exist because real businesses do not charge everyone the same. Prices differ by product, by customer type, sometimes by quantity, sometimes by date. A distributor selling both to retail buyers and to trade accounts may have several price lists active at once.
Your storefront has to know which price applies to who, and it has to get that from Odoo rather than from a copy someone maintains by hand. The moment a second copy of pricing exists, it starts drifting — and the day it drifts is the day a customer pays the wrong amount and screenshots it.
Images at catalogue scale are a real problem
A hundred-plus categories means thousands of product images, arriving in whatever size and format they were uploaded in — often full-resolution photographs dropped straight into the ERP by someone who was thinking about accuracy, not page weight.
Serve those raw and your storefront is unusable on a phone on Egyptian mobile data. The work is a pipeline: pull from Odoo, resize, convert to modern formats, cache aggressively, and never ask the ERP for an image on the critical path of a page render.
Stock timing is the one that costs money
There is always a gap between what the warehouse knows and what the storefront shows. You cannot eliminate it. You can only decide how big it is and what happens when it bites.
- How fresh is fresh enough? Real-time stock lookups on every product view will hammer your Odoo instance. Nightly syncs will oversell. The answer is usually somewhere in between, and it differs per category.
- What happens when you oversell? Decide deliberately — cancel, partially fulfil, or substitute — and design the customer communication for it before it happens rather than after.
- Who wins on conflict? If a warehouse adjustment and a web order land in the same second, one of them has to be authoritative. Pick, and write it down.
Payments: card-only checkout fails in this market
A storefront connected to Odoo in Egypt is not the same product as one in Germany. You need cash on delivery, and COD is not a checkbox — it carries a fee that varies, it changes the order lifecycle, and it has to land back in Odoo as something the finance team recognises. Add mobile wallets, Fawry kiosk codes and instalments and the payment layer becomes a genuine subsystem.
Shipping is the same story. We priced delivery per governorate rather than as a flat national rate, because that is how the cost actually behaves.
Arabic is not a translation step
Arabic runs roughly a quarter longer than English and mirrors the entire layout. Retrofitting right-to-left into a finished English product is close to rebuilding the front end. Designing for it from the first screen costs almost nothing. We built SG-Mart bilingual from the first wireframe for exactly this reason.
And the question nobody asks until it happens in production
What does a customer see when Odoo is briefly unreachable, mid-checkout?
If you have not answered that, the answer is usually a broken page and an abandoned order — and the revenue you lose to it never appears in any report, because nobody attributes it to anything. We design for that case first: cached catalogue reads so browsing survives an outage, queued writes so an order is never silently dropped, and an honest message instead of a spinner.
An integration is not judged on the day it works. It is judged on the day one side of it is down.
The question to ask any vendor before you start
The demo pulls a product list. Ask instead what happens on the edges — tax rounding, price lists, stock lag, connection loss — and you will learn in ten minutes whether the team in front of you has shipped one of these before.
If you are weighing up an Odoo-connected storefront, the companion question is whether to buy an off-the-shelf connector or build the integration properly. We wrote about how to decide between the two, and more broadly about how we approach custom software and ERP integration.

