The problem
Budget dashboards describe spending after it happens. SpendWise explores support at the moment someone is deciding to buy.
A spending confidence concept that gives people a moment to reflect before checkout. The project connects behavioural design, a browser prototype, and a planned serverless insight API.
My role spans product design, frontend development, and cloud architecture. The goal is to explore how a short reflection could support a purchase decision without making the decision for the user.
Budget dashboards describe spending after it happens. SpendWise explores support at the moment someone is deciding to buy.
A brief check asks about mood, planning, and urgency. A reflection follows, with room to buy, wait, or remove the item.
Would people find this useful or intrusive? The case study includes a testing plan and research kit to investigate that question.
Static delivery, a small serverless API, and a deploy pipeline. The backend templates are in the repository; live deployment is a later stage.
The planned deployment uses static files on S3 behind CloudFront and Route 53. The only dynamic part is the Nudge insight in the demo: one Lambda function behind API Gateway. The design goal was a public endpoint that costs close to nothing when idle and cannot become an expensive surprise when it is not.
# .github/workflows/deploy.yml (abridged)
on:
push:
branches: [main]
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
- run: aws s3 sync . s3://$BUCKET --delete \
--exclude ".git/*" --exclude "infrastructure/*"
- run: aws cloudfront create-invalidation \
--distribution-id $DIST --paths "/*"
| Decision | Why | Trade-off |
|---|---|---|
| Serverless API | Nothing runs when nobody is using it, and it scales without configuration. | Cold starts add latency to the first request after idle time. |
| Rule based insight, not a model call | Fast, deterministic, free to run, and no user data goes to a third party. | Less personalised than a generated response. |
| Throttled stage | An unauthenticated public endpoint needs a hard ceiling on request rate to bound cost and abuse. | A genuine traffic spike would be limited too. The limits are parameters. |
| Least privilege role | The function can write logs and nothing else. It touches no data stores. | Any future feature that needs storage needs a deliberate policy change. |
| CORS locked to one origin | Stops other websites from calling the API from a visitor's browser. | Browser only. It does not stop scripts or curl, which is why throttling matters. |
| Preflight handled by the gateway | OPTIONS requests never invoke Lambda, so they cost no compute. | Allowed origin is configured in two places, by one template parameter. |
| 14 day log retention | Logs are available for debugging without accumulating forever. | Older incidents cannot be investigated. |
| Three enumerated answers, no identifiers | Privacy by design. The API receives three multiple choice values and nothing that identifies a person. | No per user history in the demo. |
| Separate artifact bucket | The site sync uses --delete. Deployment packages in the same bucket would be wiped. | One more bucket to manage. |
Cost note: at the throttle ceiling the API can serve roughly 13 million requests a month in the worst case. Check current AWS pricing for that volume and keep an AWS Budgets alert as a second line of defence.
The live demo is the next stage of this project. It will walk through the checkout reflection, optional pause, insight, and purchase choices.