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.

Close ✕
Sign-in — access is invitation-only: there is no public sign-up, only customers GOA already works with.
[01] Sign-in — access is invitation-only: there is no public sign-up, only customers GOA already works with.

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.

Customer shop — commercial terms, per-client prices, discounts and VAT are computed live while the cart is built.
[02] Customer shop — commercial terms, per-client prices, discounts and VAT are computed live while the cart is built.

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.

Admin dashboard — customers, orders and catalogue in one glance, with the timestamp of the last ERP sync.
[03] Admin dashboard — customers, orders and catalogue in one glance, with the timestamp of the last ERP sync.
Orders — the list that used to be a form inbox, now reading order status, payment state and invoices straight from the ERP.
[04] Orders — the list that used to be a form inbox, now reading order status, payment state and invoices straight from the ERP.
Catalogue — the override layer: display name, price tiers, visibility and availability, product by product.
[05] Catalogue — the override layer: display name, price tiers, visibility and availability, product by product.

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.

Customers — the bridge between an ERP record and a platform account, and where invitations are sent from.
[06] Customers — the bridge between an ERP record and a platform account, and where invitations are sent from.

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

Work with me