An inventory app for a family craft business
A family member runs a craft-supply brand and needed a product inventory catalog. I built one weekend project: a public catalog page, an admin page, and just enough backend to keep it cheap.
What was happening
She wanted a simple way to add products, edit them, and have a customer- facing page. Off-the-shelf inventory tools were either too SaaS-heavy or too aimed at retail point-of-sale. The actual requirements fit on a napkin: list of products, photo, price, in-stock flag, an admin to update them.
What I built
One Lambda, one DynamoDB table, two static HTML files. The whole thing fits in a single repo and a single deploy script.
- AWS Lambda (Python 3.12) behind HTTP API Gateway
- DynamoDB table for products
- S3 bucket for product images
index.html— public catalogadmin.html— auth-gated admin UIlambda_function.py— routes + DynamoDB CRUDdeploy.sh— sets up the IAM role, Lambda, API Gateway, and DynamoDB table from scratch, idempotent
No build step, no framework, no SPA. The HTML files include their own CSS and vanilla JS, hit the Lambda's JSON endpoints directly, and that's it.
The deploy script
The thing I'm most happy with is the deploy script. Re-running it is safe — it checks for existing resources and updates rather than recreating. So adding a feature looks like:
# edit lambda_function.py
bash deploy.sh
Total deploy time is under 10 seconds. No CI, no IaC tool, no
CloudFormation YAML. Just a bash script that calls aws CLI in the
right order.
One quirk: the script's URL detection looks for a Lambda function URL and returns NOT_FOUND, because I switched to an HTTP API mid-build. That's expected — the API Gateway URL is the real entrypoint. I left the warning in rather than rewriting the detection because it costs nothing.
What I'd do differently
Pre-signed S3 upload URLs for the admin would have been cleaner than multipart-form-data through Lambda. Lambda has a 6MB payload limit and the admin UI uploads product photos — works fine for the current size, but I'll hit that limit eventually. If I were starting over I'd have the admin request a pre-signed PUT URL and upload direct to S3.
Other than that, it has the shape of what every "this should be simple" side project should look like: one Lambda, one table, one bash script, zero servers.