Rebasely Beta: data may be purged

examples/storefront Public

Markdown · 3.3 KiB · at b748afa

storefront

The API behind a small online shop, running on Cloudflare Workers. Products, carts and orders live in D1, the search index in a second D1 database, product images in R2, and payments go through Stripe.

There are three Workers:

  • storefront-api (src/) is the public API and the only Worker that writes to the database.
  • storefront-stripe-webhook (workers/stripe-webhook/) receives Stripe's events and settles orders through storefront-api's OrdersService entrypoint.
  • storefront-fulfilment (workers/fulfilment/) consumes the order-events queue and sends paid orders to the warehouse.

The order fulfilment flow on the Architecture tab follows a payment through all three.

It is a plain fetch handler with a small router, no framework, and the tests run the real SQL migrations on Node's built-in SQLite, so npm test needs nothing but Node 24.

Running it

npm install
npm test
npm run typecheck

To run the API locally with a small seeded catalog:

npm run db:migrate
npm run db:seed
echo 'ADMIN_TOKEN=dev-admin-token' > .dev.vars
npm run dev
curl -X POST localhost:8787/admin/search/rebuild -H 'authorization: Bearer dev-admin-token'

Product images are served from the bucket's custom domain, IMAGES_URL in wrangler.jsonc. Checkout needs Stripe: add STRIPE_SECRET_KEY to .dev.vars with a secret key from your Stripe account's test mode.

The guide in .rebasely/kb/guides/local-dev.md covers the other two Workers and the cron trigger. To add a product and look at the catalog:

curl -X PUT localhost:8787/admin/products/wool-socks \
  -H 'authorization: Bearer dev-admin-token' -H 'content-type: application/json' \
  -d '{"name":"Wool socks","price_cents":1800,"stock":40}'
curl localhost:8787/products

API

Method and path What it does
GET /products Active products by name, a page at a time: ?limit= (1 to 100, default 24) and ?after= the previous page's next
GET /products/:id One active product
GET /search Active products matching ?q=, best match first, up to ?limit=
PUT /admin/products/:id Create or replace a product (admin token)
PUT /admin/products/:id/image Upload the product's image (admin token)
POST /admin/search/rebuild Refill the search index from the catalog (admin token)
POST /carts A new, empty cart
GET /carts/:id A cart with its lines and totals
PUT /carts/:id/items/:product Set a quantity, { "quantity": n }
DELETE /carts/:id/items/:product Remove a line
POST /carts/:id/checkout Create the order and its PaymentIntent, { email, ship_to }
GET /orders/:id An order and its status

Errors are JSON, { "error": "<code>", "message": "..." }, with extra fields where they help (an out_of_stock error says how many are available).

Layout

src/            storefront-api: router, catalog, carts, images, checkout, orders
workers/        the other Workers, each with its own wrangler.jsonc
migrations/     D1 schema, applied in order
search/         the search index's schema (search/migrations/)
test/           node --test suites and the D1 and R2 stand-ins
.rebasely/      architecture map, knowledge base and CI workflow

The knowledge base in .rebasely/kb explains how each part works and why; start at its index.

License

MIT