A full-stack serverless application for secure image uploads using AWS Lambda, S3, and DynamoDB with a React frontend.
- Serverless Architecture: Built with AWS Lambda for automatic scaling and cost efficiency
- Secure Uploads: Pre-signed URLs for direct S3 uploads without exposing AWS credentials
- Image Management: Store and retrieve image metadata using DynamoDB
- CORS Enabled: Properly configured for cross-origin requests
- Real-time Preview: Image preview before upload
- Responsive UI: Clean React frontend with image gallery
Frontend (React) β Lambda Function URL β AWS Lambda β S3 + DynamoDB
- Frontend: React application for file selection and upload
- AWS Lambda: Handles API requests and generates pre-signed URLs
- Amazon S3: Stores uploaded images
- DynamoDB: Stores image metadata (filename, upload time, S3 key)
- Lambda Function URL: Direct HTTPS endpoint (no API Gateway needed)
Perfect for blogs, news sites, or documentation platforms where users need to upload images:
Blog Editor β Upload Image β Auto-resize/optimize β Display in article
Enable merchants to upload product images:
Merchant Portal β Product Images β S3 Storage β CDN Distribution
Handle user-generated content uploads:
User Profile β Avatar Upload β Secure Storage β Display across platform
Property managers uploading listing photos:
Property Form β Multiple Images β Organized Storage β Gallery View
Students/teachers uploading assignments or course materials:
Course Materials β Document/Image Upload β Secure Access β Download Links
- React 18 - Modern UI library
- Axios - HTTP client for API calls
- CSS3 - Styling and responsive design
- AWS Lambda - Serverless compute
- Amazon S3 - Object storage
- DynamoDB - NoSQL database
- Lambda Function URLs - Direct HTTPS endpoints
- AWS SDK v3 - Latest AWS JavaScript SDK
- Node.js 18+ and npm
- AWS Account with appropriate permissions
- AWS CLI configured locally
git clone https://github.com/yourusername/serverless-image-uploads.git
cd serverless-image-uploadsnpm installaws s3 mb s3://my-serverless-image-uploads --region us-east-1aws dynamodb create-table \
--table-name ImageUploads \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--region us-east-1# Create deployment package
zip -r function.zip index.mjs
# Create Lambda function
aws lambda create-function \
--function-name ImageUploadFunction \
--runtime nodejs18.x \
--role arn:aws:iam::YOUR_ACCOUNT:role/lambda-execution-role \
--handler index.handler \
--zip-file fileb://function.zip \
--region us-east-1aws lambda create-function-url-config \
--function-name ImageUploadFunction \
--auth-type NONE \
--cors '{
"AllowCredentials": false,
"AllowHeaders": ["content-type", "authorization"],
"AllowMethods": ["*"],
"AllowOrigins": ["*"],
"MaxAge": 86400
}' \
--region us-east-1Update the LAMBDA_URL in src/App.js with your Function URL:
const LAMBDA_URL = 'https://your-function-url.lambda-url.us-east-1.on.aws/';npm startVisit http://localhost:3000 to use the application.
serverless-image-uploads/
βββ src/
β βββ App.js # Main React component
β βββ App.css # Styling
β βββ index.js # React entry point
βββ public/
β βββ index.html # HTML template
βββ lambda/
β βββ index.mjs # Lambda function code
βββ README.md # Project documentation
βββ package.json # Dependencies
βββ .gitignore # Git ignore rules
Your Lambda execution role needs these permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::my-serverless-image-uploads/*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:us-east-1:*:table/ImageUploads"
}
]
}Retrieve all uploaded images
curl https://your-function-url.lambda-url.us-east-1.on.aws/Response:
{
"images": [
{
"id": "uuid",
"filename": "image.jpg",
"s3Key": "uploads/uuid-image.jpg",
"contentType": "image/jpeg",
"uploadedAt": "2025-06-18T00:21:17.000Z",
"status": "pending"
}
]
}Generate pre-signed upload URL
curl -X POST https://your-function-url.lambda-url.us-east-1.on.aws/ \
-H "Content-Type: application/json" \
-d '{"filename":"test.jpg","contentType":"image/jpeg"}'Response:
{
"uploadUrl": "https://s3-presigned-url...",
"imageId": "uuid",
"s3Key": "uploads/uuid-test.jpg"
}- Start the React app:
npm start - Open browser to
http://localhost:3000 - Select an image file
- Click "Upload Image"
- Verify image appears in gallery
# Test GET endpoint
curl https://your-function-url.lambda-url.us-east-1.on.aws/
# Test POST endpoint
curl -X POST https://your-function-url.lambda-url.us-east-1.on.aws/ \
-H "Content-Type: application/json" \
-d '{"filename":"test.jpg","contentType":"image/jpeg"}'-
403 CORS Error
- Ensure Lambda Function URL has CORS configured
- Check AllowOrigins includes your frontend URL
-
DynamoDB Access Denied
- Verify Lambda execution role has DynamoDB permissions
- Check table name matches in code
-
S3 Upload Failed
- Confirm S3 bucket exists and is accessible
- Verify pre-signed URL hasn't expired (5 minutes)
-
Images Not Displaying
- Check S3 bucket public access settings
- Verify S3 key format in image URLs
This serverless architecture is cost-effective:
- Lambda: Pay per request (first 1M requests/month free)
- S3: Storage costs (~$0.023/GB/month)
- DynamoDB: On-demand billing (first 25GB free)
- Data Transfer: Minimal costs for typical usage
Estimated monthly cost for 1,000 image uploads: < $1
- Frontend: Deploy to S3 + CloudFront or Vercel/Netlify
- Lambda: Use AWS SAM or Serverless Framework
- Infrastructure: CloudFormation or Terraform
For production, use environment variables:
const BUCKET_NAME = process.env.S3_BUCKET_NAME;
const TABLE_NAME = process.env.DYNAMODB_TABLE_NAME;- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- AWS SDK team for excellent documentation
- React community for component patterns
- Open source contributors
If you encounter any issues:
- Check the Troubleshooting section
- Review AWS CloudWatch logs for Lambda errors
- Open an issue on GitHub with error details