Discover something for your everyday.
Back to blog

ECNext: One Deployment, One Global Store

How ECNext combines a localized B2C storefront, company purchasing, and an operations-focused Admin in a single-store deployment.

Jul 14, 2026ECNext

ECNext is a commerce template for independently deployed stores that serve both retail and business buyers. Each deployment owns one brand, one domain, one PostgreSQL database, and its own provider credentials. PostgreSQL is the only service commerce needs: shared multi-replica rate-limit state lives in a table rather than in a separate cache server.

Why one store per deployment?

A brand can change its storefront, integrations, and operating rules without carrying a runtime tenant router through every catalog, price, inventory, and order decision. Isolation also makes backups, credential rotation, incident response, and brand-specific releases easier to reason about.

What is usable today

  • B2C discovery and purchase — localized catalog, search, filters, product details, variants, and inventory status, over a server-persisted cart. Checkout is completable by a guest or a signed-in buyer: the server re-checks merchandise price, promotion, shipping, and tax, stores immutable order snapshots, and reserves inventory only after payment is verified. Guests get a tokenized order-status page and a printable receipt.
  • B2B purchasing — company memberships, assigned price lists, quantity tiers, quotes, purchase orders, an isolated buyer workspace, and an accounts-receivable ledger: credit decisions, invoices, customer receipts, allocations, credit notes, and invoice aging, with buyer-visible reconciliation on the purchase-order detail page.
  • Post-sale fulfillment — shipment creation and cancellation, a tracking lifecycle whose events are recorded against the shipment (not polled from a carrier API), buyer-initiated returns inside a 30-day post-delivery window the API enforces, warehouse receipt, and settlement as a merchandise refund or a business credit.
  • Operations — Admin workspaces for products, inventory, companies, pricing, procurement, orders, fulfillment, receivables, analytics, RBAC, content, support, and provider settings.
  • Delivery foundation — PostgreSQL with a reviewed migration history, pnpm stack:up (certs → postgres → migrate → app, plus the notification-drain and encrypted-backup workers), secretless image builds, locale-aware SEO routes, and a GHCR publishing workflow.

What still depends on the merchant

These are configuration boundaries, not unwritten code. Each transaction slice below is implemented and covered by tests; each one also needs a value only the store operator can supply.

  • Payment providers. Checkout needs an enabled provider — Stripe, Alipay, or WeChat Pay — configured with the merchant's own credentials in Admin Settings. Until one is enabled, only a verified zero-total order can be placed, and it settles internally without a provider session.
  • Refund execution. The refund record is created either way, but returning money through the provider depends on the adapter: the Stripe, WeChat Pay, and PayPal adapters support it; the Alipay and Creem adapters do not.
  • Tax and shipping rates. Both are quoted at checkout from rules the operator defines — destination tax rules with tax-exclusive pricing, and shipping zones, methods, and rates. Nothing calls a third-party tax engine or a live carrier-rating API, so a destination with no configured rate simply has no quote and the order cannot be placed.
  • Transactional email. Order, shipment, and return notifications are written to an outbox and delivered by the drain worker, which needs the merchant's email-provider credentials before anything leaves the deployment.
  • Published policies and store identity. The shipping, returns, contact, privacy, terms, and cookie pages ship as unreviewed templates and say so on the page. Legal name, address, and at least one anonymous contact channel come from Admin Settings; until they are set, the contact page reports that store contact publication is incomplete.

Two separations are deliberate rather than unfinished: platform billingOrder records (account subscriptions and usage credits) are not merchandise sales orders, and an Admin credit entry is not an approved credit facility.

That boundary discipline is the point: the template shows completed behavior as available, configuration-dependent behavior as configuration-dependent, and does not disguise a static page as a transaction workflow.

Start a development deployment

# pnpm 11.15.0 is pinned by `packageManager` in package.json. Activate it with
# `corepack enable && corepack prepare pnpm@11.15.0 --activate`, or install
# pnpm 11.15.0 standalone.
pnpm install
cp .env.example .env

export COMPOSE_PROJECT_NAME=ecnext-dev
export POSTGRES_PASSWORD="$(openssl rand -hex 32)"
export AUTH_SECRET="$(openssl rand -hex 32)"
export CONFIG_ENCRYPTION_KEY="$(openssl rand -hex 32)"
export DATABASE_URL="postgresql://ecnext:${POSTGRES_PASSWORD}@127.0.0.1:5432/ecnext"

# PostgreSQL is the only service to start; there is no cache service to run.
docker compose -p "$COMPOSE_PROJECT_NAME" up -d --wait postgres
pnpm db:migrate
pnpm dev

pnpm stack:up is the containerized alternative: it generates development credentials into a gitignored .env.local and brings up certs → postgres → migrate → app together with the notification-drain and backup workers.

Keep credentials in the process or a protected secret store. Public brand values such as store name, description, logo, URL, and default locale are build inputs for each independent deployment.

Your privacy choices

Cart and sign-in storage are necessary. With your permission, we also use optional analytics, external services and browsing history. You can change your choice at any time. Cookie notice