Season complete, offline
A seasonal pre‑order site for Onam sadhya boxes at two grocery shops
Indo Bazaar sold boxed Onam sadhya feasts for collection from its two shops, and needed customers to order and pay before a fixed deadline. We built a single-page pre-order site with card payment. Paid orders went straight into the system that runs the shops' back office, ready for the collection days.
- Client
- Indo Bazaar
- Sector
- Indian and Keralan grocery retail
- Boxes on sale
- 3
- Collection shops
- 2
The challenge
- Onam is a fixed-date festival, so orders had to be taken and paid for before a hard cut-off, with collection on two set days.
- The shop sold three different boxes from two brands, with limited stock, so customers needed to see what was in each box and which ones had sold out.
- Each paid order had to show which shop was holding which box, so staff could get the right boxes ready.
The screens
Pre-order page. The page as it ran while ordering was open, with a countdown to the last order date across the top.
Pre-order page on a phone. The pre-order page at phone width, with the days, hours and minutes left to order under the call to action.
The sadhya leaf. An interactive banana leaf that lays out every dish in the chosen box in serving order; tapping a dish explains it.
Choosing a box. The three boxes side by side with price per head, weight and dish count, one marked sold out.
Order form. The top of the order form: box, quantity, collection shop and collection day.
Order form on a phone. Choosing a box, quantity, shop and day on a phone.
Checkout step. The bottom of the form: contact details, the order summary with total, and the button that hands off to Stripe.
Checkout step on a phone. The order summary and pay-by-card button on a phone.
After the season. The same page after the order window shut: the countdown bar switches to 'Onam 2026 has been and gone'.
What we built
Pre-order page
A single page with a countdown to the order deadline, the three boxes, a side-by-side comparison, how it works, common questions and the order form. Prices, dates, dishes and shops all live in one config file.
Interactive sadhya leaf
A drawn banana leaf that lays out every dish in the chosen box in serving order. Tapping a dish explains it.
Card checkout
A server function creates a Stripe Checkout session. It looks up the price from the catalogue, so the amount charged can't be changed from the browser.
Order recording
A Stripe webhook, not the redirect back from checkout, is what records a paid order. It passes the order to Ente Keralam, the back-office platform the shops run on, where staff handled it at a collection desk.
Hosting
The site was a single, lightweight Node container: the static page plus its API routes, running behind Caddy.
What it does
Built with
- TypeScript
- Vite
- Canvas
- Lenis
- Stripe Checkout (REST API) and webhooks
- Node.js
- Docker
- Caddy
- Vitest
- esbuild
- pnpm
- Countdown and 'order by' lines all driven by one configured date
- Three boxes compared on price per head, weight and dish count
- Sold-out boxes marked on the page
- Collection shop and day chosen when ordering
- Card payment through Stripe Checkout, priced on the server
- Shop, name, phone and quantity attached to each Stripe payment so staff can see them
- Customers could look up their order reference
- WhatsApp reservations as a fallback when card payment is switched off
- Honours reduced-motion settings, and animations pause when off-screen
- Page switches to a closed state once the season has passed
The site ran for the whole ordering window and closed on schedule, with orders collected from both shops on the collection days.
The season is complete. The public site has been taken down, and the order records were exported before the campaign's data was removed from the back office.
Want something like this?
Tell us about your business and what you need. We will reply with honest questions, then a written proposal.
