Create your own AWS account. Full control, near-zero cost on free tier.
Start Steps 1โ8 โ
๐งช
AWS Lab / Sandbox Environment
Using AWS Skill Builder, Vocareum, AWS Academy, or an event sandbox? Start here โ no account creation needed.
Sandbox Guide โ
What You Will Build
๐
Real Website
S3 + CloudFront with HTTPS, accessible to anyone
๐ค
AI Backend
Lambda + Bedrock with input protection and retry logic
๐
Secured
API key auth, scoped IAM, WAF rate limiting
๐
Monitored
CloudWatch alarms, billing alerts, logs
๐
Auto Deploy
GitHub Actions โ push code, it deploys itself
โจ
App Planner
Fill in your app details โ get Kiro chat prompt + spec plan instantly
How It All Fits Together
This section explains the real architecture you're building โ every service, what role it plays, and exactly what happens on each request and each deployment. Nothing here is simplified away; it matches precisely what Steps 1โ10 have you do.
Services & Frameworks Used
Service / Tool
Role
Introduced in
Required?
Amazon S3
Object storage. Hosts your static frontend (index.html) as a public website endpoint.
Step 2 (bucket), Step 5 (files)
Required
AWS Lambda
Serverless compute. Runs your backend logic (Python) on-demand โ no server to patch or pay for while idle.
Step 5 (code), Step 7 (deploy)
Required
Amazon API Gateway
Managed REST API front door. Routes HTTP requests to Lambda, enforces the API key, and (optionally) the WAF rate limit.
Step 6 (key), Step 7 (deploy)
Required
Amazon Bedrock
Managed foundation-model inference. Lambda calls Bedrock's API to run the Claude model and get a response โ you never host or fine-tune a model yourself.
Step 3
Required
AWS IAM
Identity and permissions. A dedicated github-deployer user grants GitHub Actions just enough access to deploy โ never broad account access.
Step 2
Required
AWS SAM (Serverless Application Model)
Infrastructure-as-code framework, an extension of CloudFormation. Your infra/template.yaml declares every resource (Lambda, API Gateway, S3) in one file; SAM translates it into a CloudFormation stack and deploys it.
Step 5 (template), Step 7 (deploy)
Required
GitHub + GitHub Actions
Source control and CI/CD. A workflow file (.github/workflows/deploy.yml) runs SAM automatically whenever you push code, using the AWS credentials stored as repository secrets.
Logging and monitoring. Every Lambda invocation writes its output (including errors) to a CloudWatch log group automatically โ no setup needed, it's on by default.
Step 8 (reading logs)
Automatic
Amazon CloudFront
Global CDN. Sits in front of S3 to provide HTTPS, edge caching, and (once configured) the only allowed path into your S3 bucket.
Step 9.1
Recommended
AWS Certificate Manager + Route 53
TLS certificates and DNS. Issues a free HTTPS certificate and points your own domain name at CloudFront.
Step 9.2
Optional
AWS WAF
Web application firewall. A managed rule set plus a custom rate limit, attached to the API Gateway stage, to block bots and abusive traffic.
Step 9.3
Optional
Amazon DynamoDB
Managed NoSQL database. Stores chatbot conversation history keyed by a session ID, with automatic expiry via TTL.
Step 9.4
Chatbot apps only
Kiro
AI coding assistant (not an AWS service). Generates your frontend, Lambda functions, SAM template, and GitHub Actions workflow from your PartyRock widget map โ this is how "no coding required" is actually true.
Throughout
Required
โ Request Lifecycle โ A Visitor Uses Your App
๐ง Visitor's Browser
โ
S3 your website files
โ page loads, then asks the AI something
๐ง Visitor's Browser
โ
API Gateway checks your API key
โ
Lambda your AI logic, from your widgets
โ
Bedrock Claude generates the response
The browser requests index.html and its assets directly from S3 (Steps 1โ8, plain http://) or via CloudFront (Step 9+, https://). Either way these are static files โ no server-side rendering.
The visitor fills in a field and submits. Client-side JavaScript sends a fetch() POST request to your API Gateway URL, with the API key attached as an x-api-key header.
API Gateway validates the key against a usage plan tied to the API_KEY_VALUE you set in Step 6. No match โ the request is rejected with 403 Forbidden before it ever reaches your code. A match โ it's routed to your Lambda function.
Lambda runs your Python handler. On a "cold start" (first call in a while) AWS has to provision a fresh execution environment first โ this is the 10โ15 second delay the FAQ describes; a "warm" container responds in 1โ3 seconds. The handler contains the same prompt/logic each PartyRock widget had.
Lambda calls Bedrock's inference API with that prompt and the chosen Claude model ID. Bedrock runs the model and returns the generated text (or, for a chatbot, continues an existing conversation).
The response flows back: Bedrock โ Lambda โ API Gateway โ browser, where your frontend JavaScript renders it into the page.
๐ Step 9 adds CloudFront in front of S3 and (if you do Step 9.4's "Lock down S3") restricts the bucket so it's only reachable through CloudFront โ direct S3 requests get blocked. This is a manual, one-time console step; GitHub Actions never redeploys it for you.
โก Deployment Lifecycle โ You Update Your Code
๐ง You
โ
GitHub git push
โ
GitHub Actions runs automatically
โ
SAM builds + deploys
โ
CloudFormation creates/updates resources
You (or Kiro, on your instruction) edit a file โ a Lambda prompt, the frontend, or template.yaml โ and upload it to GitHub (or, if working locally, git push).
A GitHub Actions workflow, defined in .github/workflows/deploy.yml, triggers automatically on that push (or on manual "Run workflow" in Step 7). It authenticates to AWS using the AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY secrets from Step 6 โ this is what the github-deployer IAM user from Step 2 is for.
The workflow runs SAM Build, which packages your Lambda code and its dependencies into deployable artifacts, uploading them to the SAM_DEPLOY_BUCKET S3 bucket from Step 2.
It then runs SAM Deploy, which reads infra/template.yaml and hands it to CloudFormation โ AWS's declarative "make reality match this file" engine that SAM is built on top of. CloudFormation diffs your template against what's currently deployed and creates or updates only what changed (Lambda functions, the API Gateway API, IAM roles, the S3 bucket).
Finally the workflow syncs your frontend/ files straight to the S3 bucket (not through CloudFormation โ this is a plain file upload) and prints both the API URL and the Frontend URL.
You never click around the AWS Console to ship a change. This exact sequence is what Step 7 (first deploy) and Step 10 (every update after) both run โ the only difference is CloudFormation has less work to do on an update, since most resources already exist and just get modified in place.
The Steps
โจ
App Planner โ Generate Your Kiro Prompt15 min โ Do this first before anything else
โบ
1
Read Your PartyRock Widgets10 min โ Map out your app's structure
โบ
2
Set Up Your AWS Account15 min โ Account, IAM user, access keys, S3 bucket
โบ
3
Enable Bedrock AI Models5 min โ Turn on Claude, test it in the Playground
โบ
4
Set Up GitHub10 min โ Create account and repository
โบ
5
Upload Your App Code to GitHub10 min โ Frontend, Lambda, template, and workflow files
โบ
6
Add Credentials + API Key to GitHub15 min โ Secrets, region variable, API key
โบ
7
Run the Deployment5 min โ Trigger GitHub Actions, watch it deploy
โบ
8
Visit, Test, and Monitor Your Live App15 min โ Add your API key, test your app, check logs
โบ
9
Make It Production-Ready20โ45 min โ HTTPS (recommended), custom domain, WAF
โบ
10
Update Your App After It's Live5 min โ How to make changes and redeploy
โบ
โ
FAQ
Common questions and answers
๐งช
Lab Sandbox Guide
AWS Skill Builder, Vocareum, Academy
โจ
Start Here โ App Planner
Fill in your PartyRock app details and get a ready-to-paste Kiro prompt + spec plan generated automatically.
โบ
1
Read Your PartyRock Widgets
โฑ 10 min
Before we build anything, we need to understand what your PartyRock app does. Every app is made of "widgets." We need to write down each one.
Amazon Bedrock is the AI service that powers your app. By default, AI models are not enabled โ you have to turn them on. It's free to request.
Open Amazon Bedrock
In the AWS Console search bar, type Bedrock and click it
Check the region in the top right and choose Asia Pacific (Malaysia) โ ap-southeast-5. Use this same region for everything in this tutorial.
Top right of the console shows a region name. Click it and select "Asia Pacific (Malaysia)".
Request Model Access
In the left sidebar, click Model access
Click Manage model access (top right of the table)
Find the Anthropic section
Check the box next to Claude Haiku 4.5 (recommended โ fast, low cost, works in every sandbox account)
Optionally also try Claude Haiku 5.5 or Claude Sonnet 5.5. They are newer and more capable, but AWS enables them per account, so they may answer "not available for this account". If so, stay on Haiku 4.5
Scroll down and click Save changes
A list of model providers. Under "Anthropic" you see checkboxes for different Claude models. Check "Claude Haiku 4.5".
Claude Haiku 4.5 is the recommended default: fast, cost-efficient, and available in every sandbox account. In Malaysia, Claude models are called through a global inference profile, so your code uses the ID global.anthropic.claude-haiku-4-5-20251001-v1:0 (not the plain anthropic.โฆ ID). Other IDs: global.anthropic.claude-haiku-5-5 and global.anthropic.claude-sonnet-5-5 (AWS enables these per account, they may be refused), and global.amazon.nova-2-lite-v1:0 (always works). If you get "Model use case details have not been submitted", your account is new: the one-time Anthropic form is still needed in the Bedrock console (Malaysia region), then wait up to 15 minutes.
Claude Opus models are blocked in sandbox accounts. Claude 3 Haiku and Llama 3 are not offered in Malaysia, and Bedrock image-generation models are not available there either. If your app has an image widget, ask Kiro to call the image model in us-west-2 (Oregon, also allowed in the sandbox) and check it in the Playground first.
Wait for Approval
Refresh the Model access page every few minutes. When the status shows a green checkmark and says Access granted, you're ready. Most requests are approved instantly.
The model row shows a green checkmark icon in the "Access status" column next to Claude Haiku 4.5.
Try the Model in Bedrock Playground
Before building your app, test the model to make sure it works for your use case.
In the left sidebar, click Playgrounds โ Chat
In the model selector (top), choose Claude Haiku 4.5
Type a prompt related to your app idea and click Run
Verify the response is useful for your project
๐ก If the model asks you to submit a use case before access is granted, fill in the form with a brief description of your project (e.g., "Student hackathon project โ building an AI chatbot for environmental awareness"). Approval is usually instant.
โ Checkpoint
Opened Amazon Bedrock in ap-southeast-5 (Malaysia) region
GitHub is where your code lives. Every time you save code there, it automatically deploys to AWS. No technical knowledge needed to use it for this tutorial.
Upload the files Kiro generated for you. No Git commands needed โ just drag and drop in the browser.
If you haven't generated your app code yet, open Kiro, share your widget map from Step 1, and say: "Build me a working AWS app from these PartyRock widgets." Kiro generates all files automatically.
GitHub's web interface does not support dragging an entire folder. You need to upload the files inside each folder, not the folder itself. Use "Create new file" to set the path.
Upload the frontend files
Click Add file โ Upload files
On your computer, open the frontend folder and drag index.html into the upload area
GitHub needs permission to deploy to your AWS account. We add "secrets" โ private values that GitHub keeps hidden and uses automatically. One of these secrets is also what locks down your API, so random strangers can't rack up your AWS bill by calling it directly.
Secrets are encrypted and never visible to anyone after saving โ not even to you. This is safe and the standard way to do this.
Open Repository Secrets
In your GitHub repository, click the Settings tab
In the left sidebar, click Secrets and variables
Click Actions in the submenu
Left sidebar shows "Secrets and variables" which expands to show "Actions". Click Actions.
Make Up an API Key Value
Your API key isn't something AWS generates for you ahead of time โ you pick the value yourself, right now, and your deployment uses that exact value to lock the API. Anyone calling your API without this exact value gets rejected.
Make up a random string at least 20 characters long โ mash your keyboard, or use a free generator like a password generator site (no account needed)
Save it somewhere โ you'll paste this same value into your frontend code in Step 8
Don't use a real password or anything you reuse elsewhere โ this value ends up readable in your frontend's JavaScript, since there's no server to hide it behind. Treat it as a "shared secret between your frontend and your API," not a real password.
Add the 5 Secrets
Click New repository secret for each one:
Secret Name (type exactly)
Value
AWS_ACCESS_KEY_ID
Your Access Key ID from Step 2
AWS_SECRET_ACCESS_KEY
Your Secret Access Key from Step 2
SAM_DEPLOY_BUCKET
Your S3 bucket name from Step 2
AWS_REGION
The same region you enabled Bedrock in during Step 3 (e.g. ap-southeast-5)
API_KEY_VALUE
The random string you just made up above
After adding all 5, the "Repository secrets" section shows a list of 5 secrets with "Updated X minutes ago" next to each. The actual values are hidden โ this is correct.
โ Checkpoint
AWS_ACCESS_KEY_ID secret added
AWS_SECRET_ACCESS_KEY secret added
SAM_DEPLOY_BUCKET secret added
AWS_REGION secret added
API_KEY_VALUE secret added, and the same value saved somewhere for Step 8
All 5 secrets visible in the repository secrets list
The "Print URLs" step shows two lines: "โ API URL: https://..." and "โ Frontend URL: http://...". Copy both.
Add Your API Key to the Frontend
Your app won't work yet โ the frontend doesn't know the API key you chose in Step 6. We paste it in now.
Open Kiro, share your frontend/index.html file
Ask: "Set the API_KEY constant (or equivalent) to [paste your API_KEY_VALUE from Step 6], and set the API URL to [paste your API URL from above]."
Kiro updates the file for you โ review the change, then save it
Upload the updated index.html to GitHub the same way you did in Step 5 โ this triggers an automatic redeploy
Wait for the GitHub Action to finish (watch the Actions tab, same as Step 7)
If you skip this step, every request from your frontend will be rejected with a 403 error โ the API key your browser sends won't match what API Gateway expects.
Open and Test Your App
Paste the Frontend URL into a new browser tab
Fill in the input fields
Click Run All
Wait 5โ10 seconds โ the AI output areas fill with responses
Check Your Logs (If Something's Wrong)
If a request fails or the output looks wrong, your Lambda function's logs usually show exactly why.
In the AWS Console, search for CloudWatch and click it
In the left sidebar, click Log groups
Find the log group named /aws/lambda/your-function-name and click it
Click the most recent log stream โ the entries are your Lambda's output, newest at the bottom
A 403 error in the browser almost always means the API key in your frontend (previous section) doesn't exactly match API_KEY_VALUE from Step 6 โ check for typos or extra spaces.
Share It
Your app URL works for anyone in the world โ no AWS or PartyRock account needed. Just share the link.
Use bit.ly to shorten the long URL into something easy to share.
Before vs. After
PartyRock
Your App
Requires login
โ Yes
โ No
Custom design
โ No
โ Yes
You own it
โ No
โ Yes
Share with anyone
Limited
โ Yes
Custom domain
โ No
โ Yes
๐
You Did It!
Your PartyRock app is now a real, published web application running on AWS. Anyone in the world can use it.
Fill in the details of your PartyRock app below. The vibe prompt on the right updates live as you type โ no AI call needed.
When you're done, click Copy and paste it straight into Kiro chat with your screenshots. Kiro generates everything in one shot.
1. App Info
2. Widgets
Open each widget's โ๏ธ edit panel in PartyRock and copy the details here.
3. Extra Notes (optional)
Live Preview
๐ Kiro Vibe Prompt โ ready to paste into Kiro chat
Fill in the form on the left to build your prompt...
HOW TO USE THIS PROMPT
1Fill in all fields on the left โ prompt updates live
2Click Copy when the prompt looks complete
3Open Kiro โ start a new chat โ paste the prompt
4Drag your PartyRock screenshots into the same message
5Send โ Kiro generates all your app files in one shot
6Follow Steps 2โ8 of this tutorial to deploy to AWS
โ Prompt copied โ what's next?
1. Open Kiro โ start a new chat
2. Paste the prompt (Ctrl+V / Cmd+V)
3. Drag your PartyRock screenshots into the same message
4. Send โ Kiro generates all your app files
This guide is for restricted AWS lab environments โ such as
Innovation Sandbox on AWS (ISB), AWS Skill Builder labs, Vocareum, AWS Academy, or event/workshop sandboxes.
These environments give you temporary AWS credentials with limited permissions.
You do not create an AWS account โ credentials are provided for you.
Your lease expired, or you were given a new sandbox account, and your app stopped working? Follow the Redeploy guide to get it running again in about 20 minutes.
What Kind of Sandbox Do You Have?
Environment
Where credentials appear
Session length
Innovation Sandbox on AWS (ISB)
ISB Web UI โ Lease details โ "Access Account" (SSO) or CLI credentials
Configured by admin (hoursโdays)
AWS Skill Builder (Jam / Lab)
Lab panel โ "AWS Details" button
1โ4 hours
Vocareum (AWS Academy)
"AWS Details" or "Account Details" button
1โ4 hours
AWS Workshop Studio
Left panel โ "Get AWS CLI credentials"
Duration of workshop
Event Engine (re:Invent etc.)
Team dashboard โ "AWS Console" link
Duration of event
Qwiklabs / Google-hosted AWS labs
Left panel โ "Connection Details"
Per-lab timer
Using Innovation Sandbox on AWS (ISB)
Innovation Sandbox on AWS is an AWS Solution that provides managed, temporary sandbox accounts through IAM Identity Center. Your administrator provisions accounts with budget limits and time-based leases. When your lease expires, the account is automatically cleaned up and recycled.
How ISB Works
๐
SSO Login
Access via IAM Identity Center โ no static keys needed
โฑ๏ธ
Time-Limited Lease
Account auto-expires after configured duration
๐ฐ
Budget Controls
Spend limits enforced โ you get alerts before hitting the cap
Request a new lease or use an existing active lease
Once approved, click "Access Account" to open the AWS Console via SSO
For CLI/programmatic access: click your lease โ "Get CLI Credentials"
Copy the three values: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
The ISB web UI shows your active lease with account ID, remaining budget, and time left. Click "Access Account" for console access or use the CLI credentials section for programmatic access.
ISB credentials are temporary (session tokens). They expire when your lease ends or when the SSO session times out. If deployment fails with ExpiredTokenException, get fresh credentials from the ISB UI.
ISB-Specific Considerations
Feature
ISB Behavior
Impact on This Tutorial
IAM Roles
SCPs may restrict role creation
Use the ISB-provided execution role instead of creating github-deployer
Bedrock Access
May need admin to enable via blueprint
Ask your ISB admin to enable Bedrock model access in the sandbox OU SCP
Region
May be restricted by SCP
Deploy in the region allowed by your ISB configuration
Budget
Lease has a spend limit
Bedrock costs ~$0.003/request โ unlikely to hit budget limits for this tutorial
Cleanup
All resources deleted when lease expires
Your app will stop working after lease ends โ export code to GitHub first
Blueprints
Admin can pre-deploy infrastructure
If a Bedrock blueprint exists, your Lambda role may already have permissions
Ask your ISB administrator if they have a Bedrock blueprint registered. If so, your sandbox account may already have the correct IAM roles and Bedrock model access pre-configured โ you can skip Steps 2 and 3 of the main tutorial.
All of these give you the same three values: Access Key ID, Secret Access Key, and sometimes a Session Token. You will need all three.
What Is Restricted in a Sandbox
Sandbox environments intentionally limit what you can do. Here is what that means for this tutorial:
Restriction
Impact
Our workaround
Cannot create IAM users
No github-deployer user
Use the sandbox credentials directly as GitHub secrets
Cannot create IAM roles freely
SAM template may fail on IAM
Use pre-existing LabRole or pass --role-arn to SAM
Session token required
Standard key+secret won't work alone
Add AWS_SESSION_TOKEN as a fourth GitHub secret
Credentials expire
Deployment fails after session ends
Re-run deployment before session expires, or re-enter fresh credentials
Bedrock may not be pre-enabled
Model access request may be blocked
Check if lab pre-enables Bedrock, or use a model that is already available
S3 bucket names may be pre-set
Cannot choose any bucket name
Use the lab-provided bucket name or prefix
Region may be locked
Must deploy to a specific region
Check the lab instructions โ in our sandbox use ap-southeast-5 (Malaysia)
Step-by-Step: Deploy From a Sandbox
1
Get Your Sandbox Credentials
In your lab environment, find the credentials panel. It is usually a button labeled AWS Details, Account Details, or Get CLI credentials.
Copy these three values:
Value
Example format
AWS Access Key ID
ASIA... (starts with ASIA, not AKIA)
AWS Secret Access Key
Long random string
AWS Session Token
Very long string โ copy the entire thing
Session tokens are very long โ make sure you copy the entire value. Missing even one character will cause authentication to fail.
2
Check What Region and Services Are Available
In the AWS Console (opened from your lab panel), check:
The region shown in the top right โ note it down (e.g. ap-southeast-5)
Go to Amazon Bedrock โ Model access โ check if Claude models show Access granted
Go to S3 โ check if you can create buckets, or if one is pre-created for you
Go to IAM โ Roles โ look for a role named LabRole or EMR_EC2_DefaultRole โ copy its ARN
IAM โ Roles page shows a list of roles. Find "LabRole" and click it. The role ARN is shown at the top โ looks like arn:aws:iam::123456789012:role/LabRole. Copy it.
3
Enable Bedrock Model Access (if not pre-enabled)
In the AWS Console โ Amazon Bedrock โ Model access โ Manage model access.
If the lab restricts model access requests, look for models already showing Access granted. Common pre-enabled models in labs:
Amazon Titan Text Express
Claude Instant (older labs)
Claude 3 Sonnet or Haiku (newer labs)
If Claude is not available, use Amazon Nova 2 Lite โ update the model ID in your Lambda functions to global.amazon.nova-2-lite-v1:0.
Leave all other settings as default โ Create bucket
If S3 bucket creation is blocked, check if the lab pre-created a bucket. Look in S3 for any existing buckets โ use one of those and note its name.
5
Update the SAM Template for Sandbox Restrictions
Sandbox environments usually block SAM from creating IAM roles automatically. You need to tell SAM to use the existing LabRole instead.
In your infra/template.yaml, find the LambdaBedrockRole resource and replace it with a reference to the lab role:
# REMOVE the AWS::IAM::Role resource block entirely
# Then update each Lambda function to use the LabRole ARN:
CalorieScannerFunction:
Type: AWS::Serverless::Function
Properties:
Role: arn:aws:iam::YOUR_ACCOUNT_ID:role/LabRole
# ... rest of properties
Find your Account ID in the AWS Console top right โ click your account name, it shows a 12-digit number like 123456789012.
Also update the SAM deploy command in .github/workflows/deploy.yml โ remove CAPABILITY_NAMED_IAM since you are no longer creating IAM resources:
Follow Step 4 to create a GitHub account and repository, and Step 5 to upload your files.
Then in GitHub โ Settings โ Secrets and variables โ Actions, add 4 secrets (sandbox needs the session token too):
Secret Name (type exactly)
Value
AWS_ACCESS_KEY_ID
Access Key ID from your lab panel
AWS_SECRET_ACCESS_KEY
Secret Access Key from your lab panel
AWS_SESSION_TOKEN
Session Token from your lab panel โ the full long string
SAM_DEPLOY_BUCKET
S3 bucket name you created in step 4
Session tokens expire when your lab session ends. If you need to redeploy after the session expires, you must update all 3 credential secrets with fresh values from a new lab session.
7
Update the GitHub Actions Workflow for Session Token
The default deploy.yml does not pass the session token. You need to add it.
In your .github/workflows/deploy.yml, find the Configure AWS credentials step and add the session token line:
Follow Step 7 โ go to the Actions tab in GitHub, click your workflow, click Run workflow.
Watch for these sandbox-specific errors:
Error
Fix
ExpiredTokenException
Your lab session expired. Start a new lab session and update all 3 credential secrets with fresh values.
AccessDenied: iam:CreateRole
Remove the IAM role from template.yaml and use LabRole ARN instead (Step 5 above).
AccessDenied: bedrock:InvokeModel
The LabRole may not have Bedrock permissions. Ask your lab instructor, or check if a different role has Bedrock access.
BucketAlreadyExists
The S3 bucket name is taken. Add more random characters to the bucket name.
No changes to deploy
This is fine โ your stack is already up to date.
Bedrock model not found
The model is not enabled in this lab, or you used a plain model ID. Use the global. ID, for example global.anthropic.claude-haiku-4-5-20251001-v1:0 or global.amazon.nova-2-lite-v1:0.
9
Visit Your Live App
Follow Step 8 โ find the Frontend URL in the GitHub Actions Print URLs step and open it in your browser.
Your app will stop working when the lab session expires because the Lambda functions use temporary credentials. To keep the app running permanently, you need a personal AWS account (follow the main tutorial path).
This step covers important upgrades. CloudFront (HTTPS) is RECOMMENDED for everyone. The rest are optional depending on your app.
9.1 Add HTTPS with CloudFront RECOMMENDED
Right now your app URL starts with http:// โ no padlock. Most browsers show a "Not Secure" warning, and copy buttons only work on HTTPS pages. CloudFront gives you HTTPS for free.
In the AWS Console, search for CloudFront โ Create a CloudFront distribution
For Origin domain, select your frontend S3 bucket (the .s3-website.ap-southeast-5.amazonaws.com endpoint โ note the dot after s3-website in Malaysia)
For Viewer protocol policy, select Redirect HTTP to HTTPS
Leave all other settings as default โ Create distribution
Wait 5โ10 minutes for status to change to Enabled
Copy the Distribution domain name (e.g. d1234abcd.cloudfront.net) โ this is your new HTTPS URL
The distribution appears in the list with status "Deploying", then "Enabled". The Distribution domain name column shows your new URL.
Lock down S3 to CloudFront only
Go to S3 โ your frontend bucket โ Permissions tab โ Edit bucket policy
Ask Kiro: "Generate an S3 bucket policy that only allows access from my CloudFront distribution. My bucket name is [name], my account ID is [ID], my distribution ID is [ID]."
Paste the policy Kiro generates โ Save changes
9.2 Add a Custom Domain (Optional)
Want www.myapp.com instead of a long CloudFront URL? You need to own a domain name first (~$10โ12/year).
AWS Console โ Certificate Manager (must be in us-east-1 for CloudFront) โ Request a certificate
Enter your domain โ DNS validation โ Request
Click Create records in Route 53 โ wait for status Issued
CloudFront โ your distribution โ Edit โ add your domain as Alternate domain name โ select your certificate โ Save
Route 53 โ Hosted zones โ your domain โ Create record โ type A โ Alias โ CloudFront distribution โ Create
Add rules โ Add managed rule groups โ enable AWSManagedRulesCommonRuleSet
Add your own rule โ Rate-based โ limit: 100 per 5 min โ Action: Block
Create web ACL โ then attach to API Gateway: API Gateway โ your API โ Stages โ click your deployed stage (usually named Prod) โ WAF tab โ select your ACL
Open Kiro, share your chatbot Lambda function, ask: "Update this Lambda to store and retrieve conversation history from DynamoDB table my-app-chat-sessions, keyed by session_id. Add a 24-hour TTL."
Open Kiro, share your Lambda's IAM role name, and ask: "Generate an IAM policy that only allows GetItem, PutItem, UpdateItem, and DeleteItem on my DynamoDB table my-app-chat-sessions, not full DynamoDB access." Attach the generated policy via IAM โ your Lambda role โ Add permissions โ Create inline policy
Open Kiro, share index.html, ask: "Generate a unique session_id on page load and include it in every chat API request. Add a Clear Chat button."
Upload updated files to GitHub โ redeploy
DynamoDB โ a database โ stores each conversation. "Partition key" is just the unique ID for each conversation. "TTL" means Time To Live โ old conversations are automatically deleted after 24 hours.
9.5 Large File Uploads (File Upload Apps Only)
Default behaviour: The generated app reads files in the browser using FileReader, converts to base64, and sends directly in the Lambda request body. This works for files up to about 4MB โ a Lambda request can be at most 6MB and base64 adds ~33% overhead. Most photos, PDFs, DOCX, and CSV files fall within this limit; for bigger files, shrink or split them first.
Only needed for files larger than ~15MB:
Open Kiro, share your infra/template.yaml and file-handling Lambda
Ask: "Add a presigned URL upload endpoint. I need a Lambda that generates a presigned S3 PUT URL, and update the frontend to use it for files larger than 15MB. Store uploads in a new S3 bucket called my-app-uploads."
Every time you save a change to GitHub, your app redeploys automatically. No AWS Console needed.
How to Update a Prompt
Open Kiro, share the Lambda file you want to update (e.g. backend/lambda/calorie_scanner.py)
Describe the change: "Update the prompt to also recommend a complementary exercise"
Kiro edits the file
In GitHub, navigate to the file โ click the pencil icon โ select all โ paste the updated content โ Commit changes
GitHub Actions redeploys automatically โ done in 3โ5 minutes
After committing, the Actions tab shows a new deployment running automatically within seconds.
How to Update the Frontend
Open Kiro, share frontend/index.html
Describe the change: "Change the background color to dark blue" or "Make the Run All button larger"
In GitHub, navigate to frontend/index.html โ pencil icon โ select all โ paste โ Commit changes
How to Roll Back a Broken Change
In GitHub, click on the file you changed โ click the History (clock) icon
Click the commit before your broken change โ click <> to view the old version
Copy the old content โ go back to the current file โ edit โ paste โ Commit
If the deployment itself failed (not just a logic error), CloudFormation automatically rolls back to the last working version. Check CloudFormation โ your stack โ Status column.
How to Delete Your App
AWS Console โ CloudFormation โ find your stack โ check the box โ Delete โ confirm
Also manually delete: the SAM artifacts S3 bucket, CloudWatch log groups, and CloudFront distribution (if applicable)
Your GitHub repository and code are NOT deleted โ you can redeploy anytime
No. You use Kiro (an AI assistant) to generate all the code, and GitHub's web interface to upload it. No coding required.
How long does this take? +
About 1.5โ2.25 hours for a complete deployment. Steps 1โ8 (a working app, no custom domain) take about 1.5 hours. Adding HTTPS and security hardening (Step 9) adds another 20โ45 minutes.
How much does it cost? +
For a personal app with low traffic (under 100 requests/day), it costs ~$0 โ covered by the AWS free tier. At 1,000 requests/day, expect ~$1โ3/month. The main cost is Bedrock (Claude) at roughly $0.003 per AI request.
Why do I need a credit card if it's free? +
AWS requires a credit card to verify your identity and prevent abuse. You will not be charged unless you exceed the free tier limits. To get an email if any charges appear: AWS Console โ Billing and Cost Management โ Budgets โ Create budget โ choose a small monthly amount (e.g. $5) โ add your email for alerts.
Deployment
My deployment failed. What do I do? +
Click on the failed step in GitHub Actions to see the error message. Check the "If Something Goes Wrong" troubleshooting table in Step 7. Copy the error message and paste it into Kiro โ it will help diagnose the problem.
The deployment says "No changes to deploy." Is that an error? +
No โ it means your app is already up to date. This is fine.
My app deployed but the URL shows an error. What do I do? +
1. Check that the API key in your frontend matches API_KEY_VALUE from Step 6 (see Step 8's "Add Your API Key to the Frontend"). 2. Check CloudWatch logs (Step 8's "Check Your Logs") for error messages. 3. Make sure Bedrock model access is granted (Step 3).
The App
The first request is very slow (10โ15 seconds). Is something wrong? +
No โ this is called a "cold start." Lambda sleeps when not in use and takes a moment to wake up. Subsequent requests are much faster (1โ3 seconds).
My AI output shows symbols like **bold** instead of formatted text. +
Claude writes in markdown (the **bold** / ## heading style), but a plain web page doesn't render that automatically โ you need a small library to convert it to real HTML. Open Kiro, share your frontend/index.html, and ask: "Add the marked.js library from a CDN, and use it to render the AI output as formatted HTML instead of raw markdown text." Upload the updated file (same as Step 5) to redeploy.
The copy button doesn't work. +
Copy buttons require HTTPS. Add CloudFront (Step 9.1) to get HTTPS, then test again.
Bedrock returned an empty response (no error, just blank). +
Claude sometimes refuses to answer certain types of content due to its safety filters. This is not an error โ it is the model declining to respond. Try rephrasing your prompt to be more specific and less ambiguous.
How do I change what the AI says? +
Edit the prompt in your Lambda function file. See Step 10 for how to update and redeploy.
Security & Cost
Is my app secure? +
After completing Step 6/8 (API key) and Step 9.1 (CloudFront), your app has: API key authentication, HTTPS, input length limits, and scoped IAM permissions. For a personal app, this is solid. For a public app with many users, also add WAF (Step 9.3).
I got an unexpected AWS bill. What happened? +
The most common causes: 1. You left a resource running that is not in the free tier. 2. Your app received much more traffic than expected. 3. You have multiple stacks deployed. Go to AWS Console โ Billing โ Cost Explorer to see which service is charging you.
How do I stop all charges immediately? +
Delete your CloudFormation stack โ see the "Delete Your App" section at the end of Step 10. This removes Lambda, API Gateway, and S3.
Sandbox / Lab
My lab session expired and the app stopped working. What do I do? +
Start a new lab session, copy the new credentials (Key ID + Secret + Session Token), update all 3 credential secrets in GitHub, and redeploy. For the full walkthrough see the Redeploy guide.
My lab doesn't have Claude. What model can I use? +
Check Bedrock โ Model access for models showing "Access granted." Amazon Nova 2 Lite (global.amazon.nova-2-lite-v1:0) is a good low-cost alternative. Update the model ID in your Lambda functions to match.
Still Stuck?
Copy the exact error message and paste it into Kiro โ describe what step you were on
Check the CloudWatch logs for your Lambda function (Step 8's "Check Your Logs")
Re-read the "If Something Goes Wrong" troubleshooting table in Step 7