The challenge
Kukd.com combined restaurant discovery with food ordering, delivery or collection, and table reservations. The checkout was a stateful workflow rather than a single payment form: the basket carried menu items, delivery or collection choice, addresses, delivery cost, timeslots, promotions or vouchers, and the selected payment method through to the Node.js API.
I worked mainly on ordering and payments: integrating Checkout.com, tightening the checkout UI and Redux synchronization, and fixing issues across the Node.js API boundary. The work covered browser payment fields, persisted basket state, customer accounts, and payment and order status handling.
What I built
Checkout.com Frames tokenization
I implemented the web card flow with Checkout.com Frames. The checkout loads the Frames library, initializes it with the public key, renders separate card-number, expiry-date, and CVV fields, validates those fields, and listens for the CARD_TOKENIZED event.
After tokenization, the client carries the token through checkout state, finalizes the basket with billing and order details, and starts the Checkout.com payment. The Node.js API distinguishes a new card token from a stored-card payment. It builds the transaction with the basket amount, GBP currency, order reference, capture setting, and success/failure URLs, then enables 3D Secure. The frontend has a dedicated 3D Secure step and checks the order status for the payment result.
Stored cards and repeat ordering
The checkout supports a real returning-customer path. It loads stored cards from the account API, presents masked card details and expiry in a selectable wallet, collects the selected card’s CVV, and sends the card ID through the stored-card payment path. The new-card flow also carries an explicit opt-in to store the card for future use.
Order history includes an Order Again action. The API rebuilds a basket from a previous order, refreshes item and set-meal prices, and returns missing or changed items so the client can account for differences before adding the new basket contents.
Basket state and checkout recovery
Redux coordinates the basket and checkout state across the ordering pipeline: items and set meals, delivery or collection, address and delivery cost, promotions and vouchers, payment cards, and the current checkout step. The API client queues basket mutations before sending them to the server, which keeps changes made across multiple checkout screens synchronized with the persisted basket.
The checkout explicitly handles stale delivery or collection timeslots, removed promotions or vouchers, restaurant closures, invalid billing addresses, and declined or unauthorised payment responses. All of that sits behind a simple-looking “place order” button.





Technology stack
- Next.js provides page routing and server-side data loading for restaurant discovery, menus, and checkout.
- React.js powers the restaurant, reservation, basket, and multi-step checkout interfaces.
- Redux centralizes basket, checkout, payment-card, and account-session state.
- Node.js runs the backend API and coordinates baskets, accounts, reservations, orders, and Checkout.com payments.
- REST API resource endpoints connect the web client to restaurants, baskets, orders, customer cards, and reservations.
- Checkout.com provides Frames tokenization, card payment initialization, 3D Secure redirects, and payment status notifications.