GOA B2B
Food & Beverage, France
2026
B2B ordering platform & admin console
Overview
GOA brews artisanal kombucha in the Périgord and sells it to a couple of hundred professional customers: bars and restaurants, grocery stores, distributors, festivals.
I designed and developed the platform where those customers now order, and connected it to Easybeer, the ERP GOA already runs its business on — so an order placed on the web becomes an order in the ERP, with no manual step in between.
Project context
Orders used to arrive through a Jotform. Someone at GOA then retyped each one into Easybeer, by hand, between 100 and 150 times a month. The form knew nothing about who was ordering: no customer-specific prices, no discounts, no minimum order, no carrier constraints. Everything was checked afterwards, and mistakes were caught late.
The brief was not to rebuild that ERP, it was to stop duplicating it. The platform reads from Easybeer and writes only orders back to it, which means GOA keeps a single place to manage products, prices and customers — and their customers get an ordering experience that already knows their terms.
How it works
01 Sync — A server-side job pulls the catalogue, per-client prices, discounts and delivery settings from Easybeer and caches them in Firestore.
02 Order — Professional customers browse their own catalogue at their own prices and build a cart that already knows their discounts, minimum and carrier rules.
03 Write back — Validating the cart creates the order directly in Easybeer. Nothing is retyped, and re-saving updates the same order instead of duplicating it.
Selected product decisions
Easybeer stays the source of truth — The platform reads catalogue, prices, discounts, client settings and invoices from the ERP, and writes exactly one thing back: the order. No business data is duplicated, so GOA keeps managing its products and pricing where it always has.
Every price is personal — Prices are never uniform — the same bottle costs a different amount depending on customer type, with custom per-client rates and four levels of discounts layered on top. Every price on screen is resolved for the customer who is logged in, never a default list price.
An opt-in catalogue — The ERP holds dozens of referenced products, but only a handful should be orderable. An override layer lets GOA toggle visibility, rewrite technical labels, attach a photo and flag a product as out of stock — new products stay hidden by default.
Business rules live in the cart — Carrier constraints are enforced while ordering: customers shipped by La Poste order in multiples of 3 for 35 cl and 2 for 1 L so crates stay homogeneous, and the minimum order value is read from each customer record.
Editable, not re-ordered — An order stays editable until the ERP marks it as delivered. Saving again upserts the same order rather than creating a second one, which removes the old “this order cancels the previous one” workaround.
Mobile before desktop — Around 90 % of orders are placed from a phone, often in a bar or a back room. The ordering flow is designed for that context first; the admin side assumes a larger screen.
Technical approach
Frontend — Vue 3, Vite and TypeScript, with shadcn-vue (Reka UI + Tailwind CSS v4) as a single design system across the customer shop and the admin console. TanStack Query for reads, TanStack Table for the admin grids, Zod for validation.
Backend — A Hono server acting as the only door to Easybeer: Basic Auth credentials stay server-side and never reach the browser bundle, alongside admin endpoints, order writes and the scheduled sync job.
Auth & data — Firebase Auth, with no public sign-up at all: an account exists only for a customer GOA already invoices, invited from their ERP record. Firestore holds the platform-side state — the part the ERP does not own — and Firebase Storage the product photos.
Living with a throttled API — The ERP API throttles aggressively, and retrying during a cooldown only makes it worse. A single outbound queue paces every call, a circuit breaker fails locally instead of hammering the API while a cooldown is active, and the cached read model means customer traffic never reaches the ERP at all — only order writes do.
More projects