Complete end-to-end guide for hosting the AI Quiz App on AWS with static site hosting, global CDN, and custom domain.
- Architecture Overview
- Services Used & Why
- Prerequisites
- Step-by-Step Deployment
- S3 Configuration
- CloudFront Setup
- DNS Configuration
- SSL Certificate
- Monitoring
- Cost Analysis
- Troubleshooting
User accesses quiz.obaidinfo.xyz or kwiz.obaidinfo.xyz
β
Route 53 DNS Resolution
β
CloudFront CDN (150+ edge locations)
β
S3 Bucket Static Content
β
βββββββββββββββββββββββββββββββββββ
β Application Files: β
β ββ index.html β
β ββ script.js β
β ββ style.css β
β ββ Assets β
βββββββββββββββββββββββββββββββββββ
β
Google Gemini API (AI Generation)
β
Quiz displayed to user β¨
- Cost: FREE tier (5GB storage)
- Why: Durable, scalable, perfect for static sites
- Features: Static website hosting, versioning, lifecycle policies
- Cost: FREE tier (50GB transfer/month)
- Why: Global distribution, faster load times, DDoS protection
- Features: 150+ edge locations, SSL termination, compression
- Cost: $0.50/month
- Why: Domain management, health checks, failover
- Features: Custom domains, alias records, traffic policies
- Cost: FREE
- Why: Auto-renewing certificates, no management needed
- Features: Wildcard support, DNS validation, auto-renewal
- Cost: FREE (60 requests/minute)
- Why: AI question generation, fast responses
- Features: JSON structured output, streaming, reliable
- AWS Account - aws.amazon.com
- Domain Name - quiz.obaidinfo.xyz, kwiz.obaidinfo.xyz
- Git installed locally
- S3 command line (optional)
# Clone repository
git clone https://github.com/ObaidAbdullah16/Quiz-App.git
cd Quiz-App
# Verify files
ls -la
# Should show: index.html, script.js, style.css, README.md-
Create S3 Bucket
- AWS Console β S3 β Create bucket
- Bucket name:
quiz-app-obaid-production - Region: us-east-1 (for CloudFront)
- Uncheck "Block all public access"
- Create bucket
-
Enable Static Website Hosting
Properties β Static website hosting β Edit Enable Index document: index.html Error document: index.html (for SPA routing) Save -
Upload Files
# Using AWS CLI aws s3 sync ./ s3://quiz-app-obaid-production \ --exclude "README.md" \ --exclude ".git" \ --exclude "node_modules" # Or drag-and-drop in console
-
Set Bucket Policy (Make public)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::quiz-app-obaid-production/*" } ] }
-
Create Distribution
- AWS Console β CloudFront β Create distribution
- Origin domain: Your S3 bucket endpoint
- Origin path: (leave empty)
- Protocol: HTTP only
-
Viewer Protocol Policy
- Select: "Redirect HTTP to HTTPS"
-
Caching Settings
- Cache policy: Default (with compression)
- Compress objects: Yes
- Default root object: index.html
-
Alternate Domain Names
quiz.obaidinfo.xyz kwiz.obaidinfo.xyz -
SSL Certificate
- Select your ACM certificate
- Must be in us-east-1 region
-
Create Distribution (takes 10-15 minutes)
-
In AWS Certificate Manager (us-east-1)
-
Request Certificate
- Public certificate
- Add domain names:
quiz.obaidinfo.xyz kwiz.obaidinfo.xyz
-
DNS Validation
- Choose DNS validation
- Create records in Route 53
- Wait for validation (5-10 minutes)
-
Create Primary A Record (quiz)
Record name: quiz Type: A (Alias) Alias target: Your CloudFront domain Routing: Simple -
Create Secondary A Record (kwiz)
Record name: kwiz Type: A (Alias) Alias target: Your CloudFront domain Routing: Simple -
Test DNS
nslookup quiz.obaidinfo.xyz nslookup kwiz.obaidinfo.xyz # Both should return CloudFront domain
# Test HTTPS connection
curl -I https://quiz.obaidinfo.xyz
# Should show: HTTP/2 200
# Test alternative URL
curl -I https://kwiz.obaidinfo.xyz
# Should also work
# Test application
curl https://quiz.obaidinfo.xyz | grep -i "AI Quiz App"s3://quiz-app-obaid-production/
βββ index.html (Served directly)
βββ script.js (Served directly)
βββ style.css (Served directly)
βββ assets/ (Optional folder)
# For HTML (no cache)
aws s3 cp index.html s3://quiz-app-obaid-production/index.html \
--metadata-directive REPLACE \
--cache-control "no-cache, no-store, must-revalidate"
# For CSS/JS (cache 1 year)
aws s3 cp script.js s3://quiz-app-obaid-production/script.js \
--metadata-directive REPLACE \
--cache-control "public, max-age=31536000"# Enable versioning (automatic backup)
# S3 Console β Bucket β Versioning β Enable
# Allows rollback to previous versionsWhen you update files:
# Option 1: CloudFront Console
# CloudFront β Invalidations β Create invalidation
# Path: /*
# Wait 2-3 minutes for cache clear
# Option 2: AWS CLI
aws cloudfront create-invalidation \
--distribution-id <YOUR_DISTRIBUTION_ID> \
--paths "/*"# View cache statistics
# CloudFront Console β Monitoring
# - Requests: Total requests
# - Data transfer: GB downloaded
# - Cache hit ratio: Aim for 90%+Zone: obaidinfo.xyz
TTL: 300
quiz A Record:
Name: quiz
Type: A (Alias)
Target: CloudFront domain
kwiz A Record:
Name: kwiz
Type: A (Alias)
Target: CloudFront domain
# Check resolution
dig quiz.obaidinfo.xyz
dig kwiz.obaidinfo.xyz
# Should return CloudFront IPCertificate Details:
- Type: Public (Free)
- Domains:
- quiz.obaidinfo.xyz
- kwiz.obaidinfo.xyz
- Issuer: Amazon RSA 2048 M01
- Validation: DNS
- Renewal: Automatic (30 days before expiry)
- Cost: FREE
# View in CloudFront Console β Monitoring
# - Requests per second
# - Data transfer per second
# - 4xx/5xx error rates
# - Cache hit ratio# View in S3 Console β Metrics
# - Number of objects
# - Total storage size
# - Requests made# Enable CloudFront logging
# CloudFront β Logging β Edit
# S3 bucket: Create dedicated bucket
# Wait 30 minutes for logs to appear
# Logs show:
# - Request timestamps
# - Viewer IP addresses
# - Request methods
# - Status codes| Service | Usage | Cost |
|---|---|---|
| S3 Storage | <5GB | FREE* |
| S3 Requests | ~1000/month | FREE* |
| CloudFront | <50GB transfer | FREE* |
| Route 53 | 1 hosted zone | $0.50 |
| SSL Cert | Let's Encrypt | FREE |
| Total | ~$0.50/month |
*After 12 months:
| Service | Cost |
|---|---|
| S3 Storage | $0.023 per GB |
| S3 Requests | $0.0007 per 10k |
| CloudFront | $0.085 per GB |
| Route 53 | $0.50 |
| Total | ~$1-2/month |
# Check bucket policy
# S3 Console β Permissions β Bucket policy
# Verify you can write to bucket
# Or grant via ACL
aws s3api put-bucket-acl --bucket quiz-app-obaid-production --acl private# Clear CloudFront cache
# Option 1: Console β Invalidations β Create
# Option 2: CLI command (see above)
# Or hard refresh browser
# Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac)# Wait 10-15 minutes for CloudFront deployment
# Check certificate is "Issued" in ACM
# Try different browser
# Verify:
openssl s_client -connect quiz.obaidinfo.xyz:443 < /dev/null# Check Route 53 records
# AWS Console β Route 53 β Hosted zones β obaidinfo.xyz
# Verify A records point to CloudFront
# Test resolution
nslookup quiz.obaidinfo.xyz
# Wait 5 minutes for TTL# Check API key in browser console (F12)
# Verify key is valid at Google AI Studio
# Check rate limits (60 requests/minute)
# For debugging:
# Open DevTools β Console tab
# Try generating a quiz manually
# Check error message# Minify CSS
# Minify JavaScript
# Tools:
# - TinyCSS (online)
# - UglifyJS (CLI)
# Keep files small:
# - JavaScript: <50KB
# - CSS: <20KB
# - HTML: <10KB# Set cache headers in S3
# HTML: no-cache (always fresh)
# CSS/JS: 1 year (never changes)
# Images: 1 month# Compression: Enabled (automatic)
# Should be <10KB compressed
# Verify with curl:
curl -H "Accept-Encoding: gzip" -I https://quiz.obaidinfo.xyz
# Check: Content-Encoding: gzip- Website accessible at quiz.obaidinfo.xyz
- Website accessible at kwiz.obaidinfo.xyz
- HTTPS working (green lock)
- Quiz generation working
- Check CloudFront cache hit ratio
- Review error logs
- Test with Google Gemini API
- Review AWS charges
- Check certificate expiry
- Update API configuration if needed
- Review CloudFront metrics
- Optimize slow resources
- Update content/features
- Test disaster recovery
Last Updated: May 27, 2026
Status: β
Production Ready
Cost: ~$0.50/month
Domains: quiz.obaidinfo.xyz, kwiz.obaidinfo.xyz