A full-stack implementation of the personalised upcoming delivery experience. The repository keeps the supplied NestJS backend, adds a responsive React SPA, and shares one runtime-validated API contract between them.
The project supports Node 18 or later and uses Yarn Classic workspaces.
nvm install
corepack enable
corepack prepare yarn@1.22.22 --activate
yarn install --frozen-lockfile
yarn devOpen the example customer at:
http://localhost:5173/welcome/ff535484-6880-4653-b06e-89983ecf4ed5
These URLs cover the main frontend states. If Vite selects a different port, replace 5173 with the port shown in the terminal.
| Case | URL | Expected result |
|---|---|---|
| Free gift | http://localhost:5173/welcome/ff535484-6880-4653-b06e-89983ecf4ed5 | Two active cats, £134 total, and a free gift |
| No free gift | http://localhost:5173/welcome/618f4ed6-1c5b-4993-a149-f64700bf31dd | One active cat, £69 total, and no gift label |
| Multiple cats without a gift | http://localhost:5173/welcome/806a49c0-01d6-48a1-8e83-7790c8af769b | Two active cats, £111 total, and no gift label |
| Three active cats | http://localhost:5173/welcome/ea17433d-7527-45a5-acbc-2e2f78f95c6e | A, B and C name formatting and a free gift |
| Unknown customer | http://localhost:5173/welcome/00000000-0000-4000-8000-000000000000 | No upcoming delivery error state |
| Malformed customer ID | http://localhost:5173/welcome/not-a-customer-id | Invalid welcome link state without an API request |
| Missing customer link | http://localhost:5173/ | No delivery selected state |
To exercise the recoverable network error state, stop the API process while leaving the web app running, then refresh any valid customer URL.
The API runs at http://localhost:3000. Its interactive Scalar reference is available at http://localhost:3000/docs, with the OpenAPI document at http://localhost:3000/openapi.json.
The frontend development server proxies /comms to the local API. When hosting the applications on different origins, set VITE_API_URL to the API origin and set the API's CORS_ORIGIN to the frontend origin. CORS_ORIGIN accepts a comma-separated allowlist.
apps/
api/ NestJS communication API
web/ React and Vite single-page app
packages/
contracts/ Shared ts-rest and Zod contract
docs/
adr/ Architecture decision records
The contract package is the source of truth for request parameters, successful responses, and expected errors. NestJS validates its responses against that contract, React Query infers its client types from it, and the OpenAPI document is generated from it.
The API reads and validates data.json once through a repository. The delivery service works in integer pence, includes only active cats, and uses Intl.ListFormat for customer-facing cat names.
yarn dev
yarn test
yarn typecheck
yarn lint
yarn build
yarn format:check/welcome/:userIdvalidates the customer ID before requesting the API.- Loading, malformed link, missing customer, missing upcoming delivery, and network failure states have dedicated UI.
- The delivery actions remain enabled as shown in the supplied design. They display a toast explaining that their workflows are outside this assessment.
- Delivery actions sit side by side at the supplied mobile viewport and stack on narrower screens so both labels retain comfortable space.
- The free gift label is shown only when the delivery total exceeds £120.
Yarn Classic workspaces provide the small monorepo with shared scripts and dependencies without adding a task runner. Vite and React are sufficient because the requested frontend is an SPA and does not require server rendering.
The project deliberately targets Node 18 compatible versions, including transitive build dependencies verified by a frozen install. With a newer runtime baseline, oRPC would be worth reconsidering for its current integrations. TanStack Start could also be considered for a product that benefits from server functions or rendering, but it would add unnecessary server architecture here.
The frontend uses shadcn components built on Base UI, Tailwind CSS, and a small theme inspired by the supplied design. Tests focus on pricing and personalisation rules, API boundaries, frontend state handling, and the enabled action behaviour.
- Replace the file repository with a durable data source and explicit cache policy.
- Add observability, request correlation, and service health checks.
- Serve the web application and API behind a shared origin, or configure a restricted CORS policy.
- Add visual regression and end-to-end coverage for supported browsers.
- Connect the delivery actions to their product workflows.
The generic cat delivery image was created with OpenAI image generation for this implementation. Its landscape source ratio is close to the supplied desktop design, while the centred subject also supports the circular mobile crop.
The exercise gives a useful balance of backend rules, frontend communication, and product judgement while leaving implementation choices open. Supplying the design tokens and example states alongside the mockups would make the intended visual and edge-case coverage clearer without prescribing the solution.