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 โ choose one of: Singapore (ap-southeast-1), Jakarta (ap-southeast-3), N. Virginia (us-east-1), or Malaysia (ap-southeast-5)
Top right of the console shows a region name. Click it and select "Asia Pacific (Singapore)".
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 (allowed in sandbox) (latest โ best quality and performance)
Optionally also enable Claude 3 Haiku (older alternative) (slightly cheaper alternative)
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" (the latest).
Claude Haiku 4.5 (model ID: anthropic.claude-haiku-4-5-20251001-v1:0) is the recommended default โ launched Feb 2026, 1M token context window. Claude 3 Haiku (older alternative) is a good alternative if you want slightly lower cost.
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.
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.
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.
Add the 3 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
After adding all 3, the "Repository secrets" section shows a list of 3 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
All 3 secrets visible in the repository secrets list
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.
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 โ usually ap-southeast-1
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-1)
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 3 Sonnet is not available, use Amazon Titan Text Express โ update the model ID in your Lambda functions to amazon.titan-text-express-v1.
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. Switch to amazon.titan-text-express-v1 in your Lambda functions.
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-1.amazonaws.com endpoint)
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
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."
IAM โ your Lambda role โ Add permissions โ AmazonDynamoDBFullAccess
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 ~15MB โ Lambda Function URLs support 20MB payloads, and base64 adds ~33% overhead. Most photos, PDFs, DOCX, and CSV files fall well within this limit.
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 2โ3 hours for a complete deployment. The quick path (Steps 0โ8) takes about 2 hours. Adding HTTPS and security hardening (Step 9) adds another 30โ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. Set a billing alarm in Step 8.7 to get an email if any charges appear.
Deployment
My deployment failed. What do I do? +
Click on the failed step in GitHub Actions to see the error message. Check the troubleshooting table in Step 7.4. 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 GitHub secrets matches the one you set in API Gateway (Step 7.5). 2. Check CloudWatch logs (Step 8.6) for error messages. 3. Make sure Bedrock model access is granted (Step 3.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. +
You need to add markdown rendering. Follow Step 5.8 to add marked.js to your frontend.
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 Steps 7.5 (API key) and 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 (Step 10 โ Delete Your App). This removes Lambda, API Gateway, and S3. Also disable your API key in API Gateway to stop any in-flight requests.
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.
My lab doesn't have Claude. What model can I use? +
Check Bedrock โ Model access for models showing "Access granted." Amazon Titan Text Express (amazon.titan-text-express-v1) is usually pre-enabled. 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.6)