Product design · JavaScript · AWS

SpendWise

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.

Project status: Design concept and case study. Research figures are illustrative; the live demo and AWS deployment remain in progress.

A pause before purchase

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.

The problem

Budget dashboards describe spending after it happens. SpendWise explores support at the moment someone is deciding to buy.

The approach

A brief check asks about mood, planning, and urgency. A reflection follows, with room to buy, wait, or remove the item.

The next question

Would people find this useful or intrusive? The case study includes a testing plan and research kit to investigate that question.

Cloud Engineering

The architecture

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.

DELIVERY Visitor Route 53 CloudFront S3 bucket REQUEST Demo in browser API Gatewaythrottled, CORS locked Lambdapython3.12, 128 MB CloudWatch Logs14 day retention DEPLOY SITE git push main GitHub Actions S3 sync, then CloudFront invalidation DEPLOY API AWS CLI CloudFormation API Gateway, Lambda, IAM role, log group
The API is deployed by hand from a laptop with CloudFormation. The site deploys automatically from GitHub Actions. Moving the API into the pipeline is on the improvement list below.

The deploy pipeline

01
PushAny push to main triggers the workflow.
02
CheckoutRepository is checked out on a fresh runner.
03
CredentialsAWS access comes from repository secrets, never from code.
04
SyncSite files go to S3. Infrastructure, docs, and markdown are excluded.
05
InvalidateCloudFront cache is cleared so visitors get the new version.
# .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 "/*"

Decisions and their trade-offs

DecisionWhyTrade-off
Serverless APINothing 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 callFast, deterministic, free to run, and no user data goes to a third party.Less personalised than a generated response.
Throttled stageAn 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 roleThe 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 originStops 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 gatewayOPTIONS requests never invoke Lambda, so they cost no compute.Allowed origin is configured in two places, by one template parameter.
14 day log retentionLogs are available for debugging without accumulating forever.Older incidents cannot be investigated.
Three enumerated answers, no identifiersPrivacy by design. The API receives three multiple choice values and nothing that identifies a person.No per user history in the demo.
Separate artifact bucketThe 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.

What I would improve next

  • Replace stored access keys with GitHub OIDC, so the pipeline assumes a short lived role and no long lived credentials sit in repository secrets.
  • Deploy the CloudFormation stack from the pipeline using a narrowly scoped role, so infrastructure changes are reviewed and versioned like code.
  • Add CloudWatch alarms on 5XX errors and throttled requests, plus an AWS Budgets alert.
  • Put the API on its own domain (api.abdullahiomer.com) with a certificate from ACM, instead of the default execute-api URL.

Interactive demo

The live demo is the next stage of this project. It will walk through the checkout reflection, optional pause, insight, and purchase choices.

Demo in progress. Read the core flow and wireframes in the meantime.