I've been working on moving my portfolio website from traditional hosting to AWS. This post documents my journey, the challenges I faced, and how I overcame them. I'm sharing this to help others who might face similar issues and to document my own learning process.
What I'm Trying to Accomplish
My goal is to create a scalable, secure hosting solution for my static website using AWS S3 for storage, CloudFront for content delivery, and a custom domain from GoDaddy. This approach should provide better performance while keeping costs down.
Challenge #1: S3 Bucket Permissions
Initially, I couldn't get my S3 bucket to serve files correctly. After uploading my files, I kept getting "Access Denied" errors. I spent hours confused about why my bucket policy wasn't working.
Solution:
I discovered I needed both the correct bucket policy and the right ACL settings. Here's the bucket policy that finally worked:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket-name/*"
}
]
}
Additionally, I needed to disable "Block all public access" settings on the bucket.
What I Learned:
AWS has multiple layers of security, and you need to address all of them. The console doesn't always make it clear which setting is causing a problem. Reading the AWS documentation thoroughly before starting would have saved me time.
Setting Up CloudFront Distribution
Next, I needed to set up a CloudFront distribution to deliver my content with low latency. The AWS console has so many options that it was initially overwhelming.
Challenge #2: SSL Certificate Issues
I wanted to use HTTPS, but kept getting certificate validation errors. The certificate was created but showed as "Pending validation" for hours.
Solution:
I needed to add specific DNS records to GoDaddy to validate my domain ownership. After creating the CNAME records AWS provided and waiting about 30 minutes, the certificate was validated. I also found that you must request certificates in the US East (N. Virginia) region for them to work with CloudFront, regardless of where your S3 bucket is located.
What I Learned:
AWS Certificate Manager is region-specific, and CloudFront has specific requirements. Reading the fine print in documentation is crucial. Also, DNS propagation takes time, so patience is key.
DNS Configuration Troubles
The final step was connecting my GoDaddy domain to the CloudFront distribution.
Challenge #3: Pointing Domain to CloudFront
After updating my DNS records in GoDaddy, my website still wasn't loading. I kept getting directed to GoDaddy's parking page.
Solution:
I needed to create both an A record and a CNAME record. The A record needed to be an "Alias" pointing to my CloudFront distribution, and the CNAME was needed for the "www" subdomain. Also, DNS changes took about 48 hours to fully propagate, much longer than I expected.
What I Learned:
DNS propagation can be frustratingly slow. Using tools like dig or online DNS checkers helps confirm if your changes are propagating correctly. Plan ahead and don't make these changes right before an important deadline.
Building My Portfolio Website: A Journey Through Code and Cloud
Creating a portfolio website seems straightforward until you dive into the details. What began as a simple showcase of my work evolved into a comprehensive learning experience spanning front-end development, cloud hosting, automation, and serverless architecture. Here's how I navigated the challenges and what I learned along the way.
Phase 1: Laying the Foundation
Starting with a clean slate, I designed the website structure using HTML, CSS, and JavaScript. Creating a responsive design was crucial - I wanted the site to look great on any device. I leveraged Claude to help with some of the initial code scaffolding, which accelerated development while giving me time to focus on the overall design and user experience.
Challenge #4: Mobile Responsiveness
The navbar worked perfectly on desktop but became unresponsive on mobile devices. After inspecting the code, I discovered the issue was related to event listeners not properly handling touch events and viewport sizes.
Solution:
I implemented a responsive navbar that collapses into a hamburger menu on smaller screens, ensuring smooth navigation regardless of device. This required restructuring my CSS with media queries and updating JavaScript event handlers to detect both click and touch interactions.
Phase 2: Cloud Hosting & Continuous Deployment
After completing local development, I moved to hosting the site on AWS. I chose Amazon S3 for static site hosting combined with CloudFront for content delivery and HTTPS support.
Challenge #5: Domain Configuration
Connecting my GoDaddy domain to AWS CloudFront initially resulted in SSL certificate errors and DNS resolution issues. The site would intermittently show as unavailable or insecure.
Solution:
I configured AWS Certificate Manager (ACM) to create and validate an SSL certificate for my domain. Then I created CloudFormation templates to properly set up the infrastructure connecting S3, CloudFront, and ACM. This ensured consistent deployment and proper DNS resolution.
Challenge #6: Deployment Automation
Manually uploading files to S3 after each code change quickly became tedious and error-prone.
Solution:
I set up a GitHub Actions workflow to automatically deploy code to my S3 bucket whenever I pushed changes to the master branch. However, this introduced a new challenge...
name: Deploy to S3
on:
push:
branches:
- master # Set the branch to deploy from
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Deploy to S3
run: |
aws s3 sync ./ s3://my-bucket-name/ --delete --exclude ".git/*" --exclude ".github/*"
- name: Invalidate CloudFront
run: |
aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"}
Challenge #7: CloudFront Access Issues
After implementing the GitHub Actions workflow, I encountered 403 Access Denied errors when trying to access my website through my domain or CloudFront.
Solution:
The issue was in my S3 bucket policy. When GitHub Actions uploaded files, it wasn't preserving the necessary settings. I modified my bucket policy to properly allow CloudFront access via Origin Access Control (OAC) and updated my GitHub workflow to maintain the correct content types for different file extensions. This ensured CloudFront could properly serve my static content while keeping the S3 bucket itself secure and private.
Phase 3: Interactive Features & Backend Integration
With the site live, I focused on adding interactive elements to engage visitors and showcase my skills.
Challenge #8: Contact Form Implementation
I wanted to include a contact form without requiring server-side code on my static site. Additionally, I needed to protect my email from spam while ensuring messages would reach me reliably.
Solution:
I implemented a serverless architecture using AWS Lambda and API Gateway. When a visitor submits the form, JavaScript sends the data to an API Gateway endpoint, which triggers a Lambda function. The Lambda function processes the submission and forwards it to my email using Amazon SES (Simple Email Service).
Challenge #9: CORS Configuration
After implementing the contact form, I encountered CORS (Cross-Origin Resource Sharing) errors when testing. The browser would block the form submission with a "No 'Access-Control-Allow-Origin' header" error.
Solution:
I updated the API Gateway configuration to properly handle OPTIONS preflight requests and return the correct CORS headers. I also modified my Lambda function to include appropriate CORS headers in both success and error responses. This ensured browsers would allow the cross-origin requests from my website to my API.
Learning Outcomes & Skills Acquired
This project has significantly expanded my cloud architecture knowledge and DevOps skills. I've gained hands-on experience with:
- Static website optimization techniques
- AWS services including S3, CloudFront, ACM, API Gateway, Lambda, and SES
- CI/CD pipelines using GitHub Actions
- CORS configuration and API security
- Serverless architecture design and implementation
Future Enhancements
Moving forward, I plan to enhance the site with a more robust project filtering system, a dedicated blog section with pagination, and analytics integration to better understand visitor engagement. I'm also exploring adding a dark mode option and multilingual support to improve accessibility.
This portfolio isn't just a showcase of my work—it's a living demonstration of my problem-solving approach and continuous learning mindset. Each challenge I encountered became an opportunity to deepen my understanding and expand my skillset.