Skip to content
Mark Garrigan

Work › stored

stored

Own your store before you've sold a thing.

Soon · Not public yet. Its own site is next.

Role
Owner: product, architecture and review.
Built
2026-05 → now
History
16 commits
Stack
Bun · MySQL · Stripe · EasyPost · Mailgun
[x] Interface[x] API[x] Data[x] Infra[x] Ops

Story

Prebuilt e-commerce is expensive when you have no sales yet. You want to control every cost, and the features you need cost extra on a SaaS plan. Before you've sold a single product, that monthly spend is hard to justify.

stored is the store you own: products, checkout, shipping labels, customer emails and mailing lists, on your own server, with no platform fee.

Its first store will be my wife's self-published book series, from her company Bear Mark Publishing.

Results

  • First store: Bear Mark Publishing's book series.
  • Its own site is next.

System, layer by layer

[x] Interface
A server-rendered admin (Edge templates, Alpine.js partial navigation, Tailwind 4) for the merchant, and a storefront API for any front end.
[x] API
A storefront API with client tokens, customer tokens and HMAC-signed outbound webhooks.
[x] Data
MySQL through Bun.SQL, UUIDv7 ids and money in integer cents.
[x] Infra
Multi-arch Docker images published on version tags, to be deployed with boxx. Stripe, EasyPost and Mailgun integrations.
[x] Ops
An event log with retried webhooks, errors shown in the admin, and tests against fake Stripe, EasyPost and Mailgun servers.

For merchants

▸ Sell before you spend

No platform subscription. It runs on your own server, and you pay only the Stripe, EasyPost and Mailgun accounts you connect.

▸ Your books and your stock, in one place

Stock is checked before payment and taken off when the order commits, so you never oversell without knowing it.

▸ Real shipping prices, one-click labels

Customers pick live carrier rates or your flat rates. After the sale, buy the label from the order page and get tracking.

▸ Emails that look like your brand

Design order confirmations in a block editor and choose which store events send them.

▸ A list that grows with every sale

Paying customers join your mailing list on their own, ready for the next launch.

▸ Your data stays yours

Export the whole store (products, orders, customers, emails, settings) as one bundle, and import it anywhere stored runs.

Screens

Illustration: The Rosebee Family books from Bear Mark Publishing: book page, bag and live shipping rates, on stored.
The Rosebee Family books from Bear Mark Publishing: book page, bag and live shipping rates, on stored.[Illustration]
Illustration: The merchant's admin: orders, payments and shipping labels.
The merchant's admin: orders, payments and shipping labels.[Illustration]

Decisions

  1. 01

    Paid means confirmed

    “An order only exists after Stored confirms the payment with Stripe.”

  2. 02

    Never sell what you don't have

    Stock is decremented atomically, and an oversold order is flagged rather than dropped.

  3. 03

    Ship without breaking the store

    Every step of the launch plan has to deploy “without breaking the live store.” Legacy checkout paths were “deleted, not fixed.”

In the box

  • Products with SKU, price, inventory, dimensions and weight
  • Checkout: address, live shipping rates, Stripe payment
  • Orders with payment and fulfillment status, and buy-label shipping
  • Customers with saved addresses
  • Mailing lists
  • A block email builder with trigger events
  • Webhooks, API clients, users, search, and event and error logs