Storefront and back office demo

Two surfaces over one store: catalogue, cart and checkout for the customer, and products, stock, orders and discounts for whoever runs it. It seeds itself the moment you open it, so there is no account to make and nothing to wait for.

Open the demo

Opens storefront.taiphamsolutions.com in a new tab. No account, no signup, and nothing you do in it leaves your browser.

What it does

The storefront is the shopping half: six categories, facet filters, product images, and a cart that survives a reload. The back office is the other half of the same database, reached through a persona switch in the menu.

Checkout is the part that had to be built properly. It runs as one IndexedDB transaction that re-reads stock, refuses to oversell, numbers the order from a counter, writes an inventory ledger entry, and empties the cart. Race two tabs for the last unit and exactly one wins. The loser rolls back completely, order number included.

Stock is a denormalised count with a ledger behind it that explains every movement, and the inventory page sums the ledger and raises a banner if the two ever disagree. Orders snapshot title, SKU and unit price at the moment of sale, so editing a product later cannot rewrite what someone was charged.

Open the back office in a second tab, change a price, and watch the storefront tab repaint without a reload.

Features

24 products across 6 categories, 10 customers, and about 90 days of order history, seeded on first open.

Catalogue and cart

Six categories, facet filters, product images held in the browser, and a cart that survives a reload and a closed tab.

Back office

Products and variants, stock, orders and fulfilment, customers, discount codes, and the inventory ledger that accounts for the count.

Live between tabs

A write on one surface reaches the other with no reload, no websocket of our own, and no cache to invalidate.

Data tools

Export the whole database, product images included, as one JSON file, and restore it in a single all-or-nothing transaction.

The flow it closes, end to end

Every step below happens inside the demo. There is no point in it where the work leaves the browser and comes back.

  1. Browse and filter

    Categories and facets narrow the catalogue. Prices, stock and images all come from the same records the staff side edits.

  2. Cart

    Lines are held against variants rather than titles, so a rename upstream cannot silently change what is in the basket.

  3. Checkout, as one transaction

    Stock is re-read, an oversell is refused, the order takes the next number from a counter, a ledger entry is written, and the cart empties. All of it or none of it.

  4. The order reaches the staff side

    It appears in the back office with its lines snapshotted, and moves through fulfilment from there.

  5. Stock reconciles

    The inventory page sums the ledger against the stored count and says so if they have drifted, rather than quietly trusting the number.

What is real, and what is not

There is no server behind any of this, which decides both columns. The left one is what that constraint made worth building properly. The right one is what it rules out.

Actually handled

  • Overselling under two tabs racing for the last unit
  • Order history that survives editing the product afterwards
  • An inventory count you can audit against its own ledger
  • Cross-tab updates with no reload

Deliberately not real

  • The persona switch is not authentication. With no server there is nothing to authenticate against, and the interface says so
  • Checkout ends at a simulated payment step. No card is collected and no money moves
  • No email is sent, to the shopper or to anyone else
  • Nothing syncs. The data is per browser profile, so a phone gets a fresh copy

How it is built

The write-up sells harder than the application does, so it is on the page rather than in a repository nobody can open.

Stack
Vue 3, Dexie over IndexedDB, Vite. One static bundle, no server behind either surface.
Storage
Every product, order, customer, discount and product image lives in the browser's IndexedDB.
Boundary
Nothing in the storefront, the back office or the stores imports Dexie. Every read and write goes through a repository layer that returns plain objects, so replacing IndexedDB with a real API means rewriting one directory.
Tests
78 unit tests against fake-indexeddb, so transactions, indexes and the upgrade path are exercised for real, plus 4 Playwright tests driving the bundle that actually ships.

Want the version of this with your rules in it?

This one was built to a constraint nobody would choose. Yours would have a server, real accounts, and the parts of the domain that are actually hard. Tell us what the software has to do and we will tell you what it takes.

Bring the messy version of the problem. That is the conversation we enjoy most.

Email us