<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sherif sani</title>
    <description>The latest articles on DEV Community by Sherif sani (@sherif_san).</description>
    <link>https://dev.to/sherif_san</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1442811%2Fa5c49194-efe0-4b8d-9451-200509de9ba6.jpg</url>
      <title>DEV Community: Sherif sani</title>
      <link>https://dev.to/sherif_san</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sherif_san"/>
    <language>en</language>
    <item>
      <title>100 Days of devops</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Thu, 09 Apr 2026 17:02:17 +0000</pubDate>
      <link>https://dev.to/sherif_san/100-days-of-devops-ap0</link>
      <guid>https://dev.to/sherif_san/100-days-of-devops-ap0</guid>
      <description>&lt;h2&gt;
  
  
  Day 1 of 100 Days of DevOps: Securing Service Accounts
&lt;/h2&gt;

&lt;p&gt;So, I’ve officially started the &lt;strong&gt;100 Days of DevOps&lt;/strong&gt; on KodeKloud Engineer.&lt;/p&gt;

&lt;p&gt;My goal is simple:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solidify what I already know
&lt;/li&gt;
&lt;li&gt;Bridge the gaps in what I don’t
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before diving into the technical logs, I want to share a bit about where I’m coming from.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Background
&lt;/h2&gt;

&lt;p&gt;I’m currently a Computer Science student and working as a Software Engineer.  &lt;/p&gt;

&lt;p&gt;For a long time, I’ve had my sights set on becoming a &lt;strong&gt;Solutions Architect&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’m already quite comfortable with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud technologies
&lt;/li&gt;
&lt;li&gt;System architectures
&lt;/li&gt;
&lt;li&gt;The standard DevOps toolkit
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if I’m being honest… I’ve been playing it safe.&lt;/p&gt;

&lt;p&gt;I stayed in my comfort zone instead of fully chasing that goal.&lt;/p&gt;

&lt;p&gt;This challenge is my way of breaking that cycle and intentionally moving toward the career I actually want.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 1: Securing Service Accounts
&lt;/h2&gt;

&lt;p&gt;Today’s task was simple, but very fundamental:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a service user on a remote server &lt;strong&gt;without allowing interactive login&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Scenario
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SSH into a remote instance
&lt;/li&gt;
&lt;li&gt;Create a user called &lt;code&gt;app-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ensure:

&lt;ul&gt;
&lt;li&gt;No home directory
&lt;/li&gt;
&lt;li&gt;No interactive login
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This user is meant for background processes — not humans — so security is key.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ The Solution
&lt;/h2&gt;

&lt;p&gt;After connecting via SSH, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;useradd &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /usr/sbin/nologin app-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breakdown
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;-r&lt;/code&gt; (System User)&lt;br&gt;
Creates a system account with a lower UID.&lt;br&gt;
These accounts are typically hidden from login screens and reserved for services.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-M&lt;/code&gt; (No Home Directory)&lt;br&gt;
No need to create /home/app-service.&lt;br&gt;
This keeps the filesystem clean and reduces risk if the account is compromised.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-s&lt;/code&gt; /usr/sbin/nologin (Non-interactive Shell)&lt;br&gt;
This is the security lock 🔒&lt;br&gt;
Even if someone gets access to this account, they cannot start a shell session.&lt;br&gt;
The system simply denies login attempts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaway
&lt;/h3&gt;

&lt;p&gt;This is a perfect example of the Principle of Least Privilege:&lt;br&gt;
Give a user exactly what they need — and nothing more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing Thoughts
&lt;/h3&gt;

&lt;p&gt;It’s a simple one-liner, but it reinforces a critical DevOps mindset:&lt;br&gt;
security and intentional design at every level.&lt;/p&gt;

&lt;p&gt;Day 1 done. Thank you for reading&lt;/p&gt;

</description>
      <category>devops</category>
      <category>linux</category>
      <category>cli</category>
      <category>aws</category>
    </item>
    <item>
      <title>A tiny Spring Boot 'profile' microservice — Stage‑0 HNG backend</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Wed, 22 Oct 2025 19:46:26 +0000</pubDate>
      <link>https://dev.to/sherif_san/a-tiny-spring-boot-profile-microservice-stage-0-hng-backend-26k1</link>
      <guid>https://dev.to/sherif_san/a-tiny-spring-boot-profile-microservice-stage-0-hng-backend-26k1</guid>
      <description>&lt;p&gt;I built a minimal Spring Boot service for my HNG Stage‑0 backend task that returns a profile object plus a fun cat fact. The goal was to deliver a clear, runnable microservice in a few files so reviewers can quickly run and inspect the code.&lt;/p&gt;

&lt;p&gt;What it does&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exposes GET /me&lt;/li&gt;
&lt;li&gt;Returns a JSON payload with status, a small user profile (name, role, links), a timestamp, and a cat fact fetched from &lt;a href="https://catfact.ninja/fact" rel="noopener noreferrer"&gt;https://catfact.ninja/fact&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Architecture (short)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ProfileController&lt;/code&gt; — handles /me and returns a &lt;code&gt;ProfileResponse&lt;/code&gt; DTO.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProfileService&lt;/code&gt; — builds the profile and fetches the external cat fact using Java HttpClient.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Profile&lt;/code&gt; (domain) and &lt;code&gt;ProfileResponse&lt;/code&gt; (DTO) — simple POJOs for shape and serialization.&lt;/li&gt;
&lt;li&gt;Spring Boot entrypoint and a single minimal unit test to ensure application context loads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why this shape?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimal surface area: reviewers can audit the domain, controller, and service quickly.&lt;/li&gt;
&lt;li&gt;External call isolated in the service so it’s easy to mock or replace.&lt;/li&gt;
&lt;li&gt;Small codebase is ideal for early-stage tasks and focused feedback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to run locally&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From the project root (uses the included Maven wrapper):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then open: &lt;a href="http://localhost:8080/me" rel="noopener noreferrer"&gt;http://localhost:8080/me&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I learned / next steps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep services focused and small for fast review cycles.&lt;/li&gt;
&lt;li&gt;Inject HttpClient (or a wrapper) to make the external API call testable and mockable.&lt;/li&gt;
&lt;li&gt;Add structured error handling and logging for robustness.&lt;/li&gt;
&lt;li&gt;Add unit tests that mock the cat-fact API and an integration test for the controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;check the repository: &lt;a href="https://github.com/Sherifsani/profile" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>Turning My Notes Into Audio with AWS (Serverless + Terraform)</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Sat, 09 Aug 2025 22:26:40 +0000</pubDate>
      <link>https://dev.to/sherif_san/turning-my-notes-into-audio-with-aws-serverless-terraform-572c</link>
      <guid>https://dev.to/sherif_san/turning-my-notes-into-audio-with-aws-serverless-terraform-572c</guid>
      <description>&lt;p&gt;About a month ago, I had this random thought while on the bus to school:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“What if I could just listen to my handwritten notes instead of reading them?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted something &lt;strong&gt;simple&lt;/strong&gt;, &lt;strong&gt;cost-effective&lt;/strong&gt;, and since I already spend a lot of time working with AWS, it made sense to build it there.&lt;/p&gt;

&lt;p&gt;After a bit of brainstorming, I landed on the perfect stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Textract&lt;/strong&gt; → Extract text from my images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Polly&lt;/strong&gt; → Turn that text into natural-sounding speech.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda + API Gateway&lt;/strong&gt; → Keep it serverless and cost-friendly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon S3&lt;/strong&gt; → Store my uploaded images and generated audio files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because I’m all about &lt;strong&gt;infrastructure-as-code&lt;/strong&gt;, I deployed the whole thing with &lt;strong&gt;Terraform&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Here’s a high-level look at how it works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dl6zj25jf7rclxc25rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dl6zj25jf7rclxc25rj.png" alt="Architecture Diagram" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simple, serverless, and cheap to run, which is exactly what I needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why These Services?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon S3&lt;/strong&gt; – Stores images and audio files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Textract&lt;/strong&gt; – Extracts text from scanned or photographed documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Polly&lt;/strong&gt; – Turns text into speech.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda&lt;/strong&gt; – Runs the logic without managing servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Gateway&lt;/strong&gt; – Provides a REST API endpoint for the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt; – Automates the entire setup so it’s reproducible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Provisioning with Terraform
&lt;/h2&gt;

&lt;p&gt;Instead of manually clicking around in the AWS Console, I used Terraform to define everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 buckets for images and audio&lt;/li&gt;
&lt;li&gt;Lambda function with IAM permissions&lt;/li&gt;
&lt;li&gt;API Gateway endpoint&lt;/li&gt;
&lt;li&gt;Access for Textract and Polly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deployment was as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few minutes later, everything was live. No console clicking. No missed resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the App Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The user uploads an image via the API Gateway endpoint.&lt;/li&gt;
&lt;li&gt;The image is stored in S3.&lt;/li&gt;
&lt;li&gt;Textract extracts the text from the image.&lt;/li&gt;
&lt;li&gt;Polly converts the extracted text into an MP3.&lt;/li&gt;
&lt;li&gt;The MP3 is saved to another S3 bucket.&lt;/li&gt;
&lt;li&gt;A pre-signed URL is generated so the user can listen or download it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When I tested it with a snapshot of my lecture notes, I got an audio file back in seconds. The best part? Since it’s all serverless, I only pay for what I use — perfect for a student budget.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This was a fun way to mix &lt;strong&gt;AWS AI services&lt;/strong&gt;, &lt;strong&gt;serverless architecture&lt;/strong&gt;, and &lt;strong&gt;Terraform&lt;/strong&gt; into a single project. Now I can “read” my notes while walking, commuting, or even cooking — and it costs just a few cents per use.&lt;/p&gt;

&lt;p&gt;That said… Polly’s voice still sounds a bit robotic at times. But for this use case, it works well enough, and the build was worth it.&lt;/p&gt;

&lt;p&gt;If you want to try it out or see how it’s built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code &amp;amp; Terraform&lt;/strong&gt; → &lt;a href="https://github.com/Sherifsani/audo-notes-infra" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo&lt;/strong&gt; → &lt;a href="https://audio-notes-client.vercel.app/" rel="noopener noreferrer"&gt;audio-notes-client.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Deploying a Full-Stack App on AWS ECS with Docker: From Code to Cloud</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Wed, 14 May 2025 20:53:28 +0000</pubDate>
      <link>https://dev.to/sherif_san/deploying-a-full-stack-app-on-aws-ecs-with-docker-from-code-to-cloud-1akm</link>
      <guid>https://dev.to/sherif_san/deploying-a-full-stack-app-on-aws-ecs-with-docker-from-code-to-cloud-1akm</guid>
      <description>&lt;p&gt;In the ever-evolving world of web development, one of the most empowering things you can do is take your application from local development all the way to the cloud — and that’s exactly what I did.&lt;/p&gt;

&lt;p&gt;Over the past few days, I built and deployed a full-stack application consisting of a &lt;strong&gt;React frontend&lt;/strong&gt; and an &lt;strong&gt;Express.js backend&lt;/strong&gt;, fully containerized and hosted on &lt;strong&gt;AWS ECS using Fargate&lt;/strong&gt;. Here’s a look behind the scenes of how I transformed lines of code into a cloud-native, production-grade deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React (built with Vite) &lt;a href="https://github.com/sherifsani/doot-frontend" rel="noopener noreferrer"&gt;repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Node.js + Express &lt;a href="https://github.com/sherifsani/doot-backend" rel="noopener noreferrer"&gt;repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerization:&lt;/strong&gt; Docker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Hosting:&lt;/strong&gt; Amazon ECS with Fargate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Registry:&lt;/strong&gt; Amazon ECR&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Building the Application
&lt;/h2&gt;

&lt;p&gt;The architecture was simple but effective: a React frontend communicating with an Express backend. I began by developing both apps locally and testing them with Docker to ensure container compatibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Setup Highlights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built using &lt;strong&gt;Vite&lt;/strong&gt; for lightning-fast bundling&lt;/li&gt;
&lt;li&gt;Dockerized into a lightweight &lt;strong&gt;Nginx container&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Served static files from &lt;code&gt;/usr/share/nginx/html&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Backend Setup Highlights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RESTful API built with Express&lt;/li&gt;
&lt;li&gt;Dockerized using a minimal &lt;strong&gt;Node Alpine&lt;/strong&gt; base image&lt;/li&gt;
&lt;li&gt;Exposed port &lt;code&gt;3000&lt;/code&gt; for requests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dockerization
&lt;/h2&gt;

&lt;p&gt;Each app was placed in its own Docker container with production-ready configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build images&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; doot-frontend &lt;span class="nb"&gt;.&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; doot-backend &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Authenticate to ECR&lt;/span&gt;
aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="se"&gt;\&lt;/span&gt;
  | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &amp;lt;account-id&amp;gt;.dkr.ecr.us-east-1.amazonaws.com

&lt;span class="c"&gt;# Tag and push&lt;/span&gt;
docker tag doot-backend &amp;lt;account-id&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/doot-backend
docker push &amp;lt;account-id&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/doot-backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ☁️ Deploying with Amazon ECS + Fargate
&lt;/h2&gt;

&lt;p&gt;Here’s where the magic happened:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Step 1: Create ECS Cluster
&lt;/h3&gt;

&lt;p&gt;Created a new cluster using &lt;strong&gt;Fargate&lt;/strong&gt; launch type. No EC2 instances needed!&lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Step 2: Task Definitions
&lt;/h3&gt;

&lt;p&gt;Defined a task for both the frontend and backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ECR container image&lt;/li&gt;
&lt;li&gt;Port mappings&lt;/li&gt;
&lt;li&gt;Memory/CPU settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 Step 3: ECS Services
&lt;/h3&gt;

&lt;p&gt;Deployed tasks as &lt;strong&gt;services&lt;/strong&gt;, enabling auto-restarts, load balancing (optional), and easier scaling.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Step 4: Networking &amp;amp; Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Placed tasks in &lt;strong&gt;public subnets&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enabled &lt;strong&gt;auto-assign public IP&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Allowed traffic on ports &lt;code&gt;80&lt;/code&gt; (frontend) and &lt;code&gt;3000&lt;/code&gt; (backend) using &lt;strong&gt;security groups&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Going Live
&lt;/h2&gt;

&lt;p&gt;Once deployed, I could access the React frontend via the public IP of the ECS task. It successfully made API calls to the backend.&lt;/p&gt;

&lt;p&gt;The satisfaction of seeing everything work together — no server to maintain, fully cloud-native — was amazing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fargate&lt;/strong&gt; removes the burden of server management.&lt;/li&gt;
&lt;li&gt;Properly configuring &lt;strong&gt;networking and security groups&lt;/strong&gt; is crucial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dockerizing&lt;/strong&gt; both frontend and backend simplifies deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon ECR&lt;/strong&gt; is a reliable and scalable container registry.&lt;/li&gt;
&lt;li&gt;You don't have to be a cloud expert to get started — just patient and persistent.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This project was more than just deploying an app — it was about leveling up.&lt;/p&gt;

&lt;p&gt;I bridged the gap between development and DevOps, and it deepened my confidence in building, shipping, and scaling full-stack applications in a modern, cloud-native way.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automating NBA Game Results Delivery with AWS Lambda, EventBridge, and SNS</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Sat, 25 Jan 2025 15:59:24 +0000</pubDate>
      <link>https://dev.to/sherif_san/automating-nba-game-results-delivery-with-aws-lambda-eventbridge-and-sns-2fi9</link>
      <guid>https://dev.to/sherif_san/automating-nba-game-results-delivery-with-aws-lambda-eventbridge-and-sns-2fi9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Are you a basketball fan who doesn’t want to miss out on NBA game results? In this blog post, I’ll walk you through how I automated the process of fetching NBA game results using SportsAPI, AWS Lambda, EventBridge, and SNS to deliver the results via email or SMS.&lt;/p&gt;

&lt;p&gt;By the end, you’ll learn how to set up a serverless solution with AWS services and schedule it to run daily.&lt;/p&gt;




&lt;h2&gt;
  
  
  Overview of the Solution
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8p0h6gv085yv08bag9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8p0h6gv085yv08bag9f.png" alt="Solution Architecture" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s how the system works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Source&lt;/strong&gt;: Fetching NBA game results using SportsAPI.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda&lt;/strong&gt;: Running the Python script to fetch data and send notifications.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon EventBridge&lt;/strong&gt;: Scheduling the script to run daily.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon SNS&lt;/strong&gt;: Delivering the results via email/SMS.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;An AWS account with access to Lambda, SNS, and EventBridge.
&lt;/li&gt;
&lt;li&gt;A SportsAPI API key (create one &lt;a href="https://api-sports.io/" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step-by-step Implementation
&lt;/h2&gt;

&lt;p&gt;Login to your AWS Management Console, and let's begin.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Creating the SNS Topic&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigate to SNS, then Topics&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1c5qbz9j7lqfvfd0qi7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1c5qbz9j7lqfvfd0qi7.png" alt="SNS Dashboard" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Topic&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Topic type: Standard
&lt;/li&gt;
&lt;li&gt;Name: Any name of your choice
&lt;/li&gt;
&lt;li&gt;Leave other fields blank or default, and click &lt;strong&gt;Create&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj5o7igbpeqnwjd8ixif.png" alt="Create Topic" width="800" height="382"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Subscription&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the newly created topic and click &lt;strong&gt;Create subscription&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m1myvv3etty2pqt1q54.png" alt="Create Subscription" width="800" height="382"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fill in these details:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Topic ARN: The ARN of the created topic
 Protocol: Email (or SMS)
 Endpoint: Your email address
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyktxuufpu6lqok1yoqc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyktxuufpu6lqok1yoqc0.png" alt="Subscription Details" width="800" height="382"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A confirmation email will be sent. Open it and hit &lt;strong&gt;Confirm&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Creating a Policy and Role for the Lambda Function&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigate to the IAM Dashboard&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wg2hsmarsp6snw1os4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wg2hsmarsp6snw1os4m.png" alt="IAM Dashboard" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Policy&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Policies&lt;/strong&gt; → &lt;strong&gt;Create policy&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7hmolc7yjksbocbjjld.png" alt="Create Policy" width="800" height="382"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Choose &lt;strong&gt;Lambda&lt;/strong&gt; as the service and add the following JSON under &lt;strong&gt;Policy Editor&lt;/strong&gt;. Replace &lt;code&gt;arn:aws:sns:REGION:ACCOUNT_ID:topic-name&lt;/code&gt; with your topic ARN:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sns:Publish"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:sns:REGION:ACCOUNT_ID:topic-name"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n4dy36t109j01eqpxim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n4dy36t109j01eqpxim.png" alt="Policy Editor" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Review, name it (e.g., &lt;code&gt;sns_publish&lt;/code&gt;), and create it.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82g7t8283wtjd2ejwo27.png" alt="Policy Created" width="800" height="382"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a Role&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Roles&lt;/strong&gt; → &lt;strong&gt;Create role&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0c65n3yn6y2ucji3m3d.png" alt="Create Role" width="800" height="382"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;AWS Service&lt;/strong&gt; → &lt;strong&gt;Lambda&lt;/strong&gt; as the trusted entity.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc7exrtynt9pzvl4v3bp0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc7exrtynt9pzvl4v3bp0.png" alt="Trusted Entity" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach the previously created policy (&lt;code&gt;sns_publish&lt;/code&gt;).&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13s5pc6mffhy2g7b178j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13s5pc6mffhy2g7b178j.png" alt="Attach Policy" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Name the role (e.g., &lt;code&gt;nba_function_role&lt;/code&gt;) and create it.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnordnzac2nsu6q2h4cl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnordnzac2nsu6q2h4cl.png" alt="Role Created" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Creating the Lambda Function&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigate to Lambda&lt;/strong&gt; → &lt;strong&gt;Create function&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zx23xjxh9ctgy571i2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zx23xjxh9ctgy571i2u.png" alt="Lambda Dashboard" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Function Details&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;nba_function&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Runtime: Python
&lt;/li&gt;
&lt;li&gt;Execution Role: Select the previously created role (&lt;code&gt;nba_function_role&lt;/code&gt;).
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F999rfumcnf0e49vuyo9c.png" alt="Create Function" width="800" height="382"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add the Code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Replace the default code with the provided Python script.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urllib.request&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;botocore.config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Configure boto3 with shorter timeout
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;connect_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;read_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sns&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Get environment variables
&lt;/span&gt;    &lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SNS_TOPIC_ARN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;today_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetching games for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;api_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://v1.basketball.api-sports.io/games?league=12&amp;amp;season=2024-2025&amp;amp;date=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;v1.basketball.api-sports.io&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Set timeout for the HTTP request
&lt;/span&gt;    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Send the HTTP request with timeout
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Process games more efficiently using list comprehension
&lt;/span&gt;            &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;teams&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;home&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scores&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;home&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) vs &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;teams&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;away&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scores&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;away&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;final_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;TopicArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;final_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Games for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Successfully processed games&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No games found for today&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URLError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;error_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error fetching games: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;error_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HTTP error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;error_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unexpected error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add Environment Variables&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API_KEY: Your SportsAPI key
&lt;/li&gt;
&lt;li&gt;SNS_TOPIC_ARN: The ARN of the created topic
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy the Function&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy&lt;/strong&gt; or use the shortcut &lt;code&gt;Ctrl+Shift+U&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Creating the EventBridge Schedule&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigate to EventBridge&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7s9uhw3mtlywhg03tfyl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7s9uhw3mtlywhg03tfyl.png" alt="EventBridge Dashboard" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Rule&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: Any name of your choice
&lt;/li&gt;
&lt;li&gt;Rule type: Schedule
&lt;/li&gt;
&lt;li&gt;Cron expression: &lt;code&gt;0 * * * ? *&lt;/code&gt; (runs hourly)
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftyeuuy5ysukc5h3bts86.png" alt="Create Rule" width="800" height="378"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Select the Target&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Target type: Lambda Function
&lt;/li&gt;
&lt;li&gt;Lambda function: &lt;code&gt;nba_function&lt;/code&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5a7u9mhg1uknmtvjy3j.png" alt="Select Target" width="800" height="378"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create the Schedule&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;With these steps, your automated solution will fetch NBA game results daily and send them to you via email or SMS!&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrates how AWS services like Lambda, EventBridge, and SNS can work seamlessly together to create a fully automated, serverless solution. By leveraging SportsAPI, we automated the process of fetching NBA game results and delivering them directly to your inbox or phone, saving you time and ensuring you never miss a moment. &lt;/p&gt;

&lt;p&gt;Whether you’re a sports enthusiast or just exploring serverless architectures, this project showcases the versatility of AWS for building practical, real-world applications. I encourage you to try it out, customize it further, and even extend it to other use cases like weather updates or stock market alerts.&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts or ask questions in the comments! Happy coding! 🏀✨&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Weather reports Dashboard with python, S3 and Openweather API</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Sun, 19 Jan 2025 11:56:53 +0000</pubDate>
      <link>https://dev.to/sherif_san/building-a-weather-reports-dashboard-with-python-s3-and-openweather-api-4k62</link>
      <guid>https://dev.to/sherif_san/building-a-weather-reports-dashboard-with-python-s3-and-openweather-api-4k62</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever wanted to build an application that fetches real-time weather data and securely stores it for later use? In this article, I'll walk you through how I developed a weather reporting app using Python, the OpenWeather API, and AWS S3.  &lt;/p&gt;

&lt;p&gt;This app:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetches current weather information for selected cities.
&lt;/li&gt;
&lt;li&gt;Displays the weather data on the console.
&lt;/li&gt;
&lt;li&gt;Stores the data in JSON format in an S3 bucket for archival purposes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my first project in the &lt;strong&gt;30-days DevOps challenge series&lt;/strong&gt;.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.x&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI configured with credentials and permissions&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws configure
   aws s3 mb s3://your_s3_bucket_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;OpenWeather API key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;.env&lt;/code&gt; file to store environment variables:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   OPENWEATHER_API_KEY=your_openweather_api_key  
   AWS_BUCKET_NAME=your_s3_bucket_name  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing Required Libraries
&lt;/h3&gt;

&lt;p&gt;Install the necessary libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;python-dotenv requests boto3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, use a &lt;code&gt;requirements.txt&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;requirements.txt  
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"python-dotenv"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; requirements.txt  
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"requests"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; requirements.txt  
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"boto3"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; requirements.txt  
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The App
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Importing Packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;  
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;  
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;  
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;  
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;  
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Environment Setup
&lt;/h3&gt;

&lt;p&gt;Initialize the app to interact with the API and AWS S3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherDashboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPENWEATHER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS_BUCKET_NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_bucket_if_not_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head_bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bucket &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Creating bucket &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully created bucket &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error creating bucket: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Fetching Weather Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://api.openweathermap.org/data/2.5/weather&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;appid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;units&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imperial&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error fetching weather data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Saving Data to S3
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_to_s3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;  

    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%Y%m%d-%H%M%S&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weather-data/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;  
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
            &lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
            &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
            &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
            &lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;  
        &lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully saved data for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; to S3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error saving to S3: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Main Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;  
    &lt;span class="n"&gt;dashboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WeatherDashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

    &lt;span class="c1"&gt;# Create bucket if needed  
&lt;/span&gt;    &lt;span class="n"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_bucket_if_not_exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

    &lt;span class="n"&gt;cities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Philadelphia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Seattle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Fetching weather for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="n"&gt;weather_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
            &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
            &lt;span class="n"&gt;feels_like&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;feels_like&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
            &lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;humidity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
            &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weather&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  

            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperature: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;°F&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Feels like: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;feels_like&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;°F&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Humidity: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;humidity&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Conditions: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

            &lt;span class="c1"&gt;# Save to S3  
&lt;/span&gt;            &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save_to_s3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Weather data for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; saved to S3!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to fetch weather data for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check your s3 bucket&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;ls &lt;/span&gt;s3://your_s3_bucket_name 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;alternatively, you could use the console to the see the content of your bucket&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a weather reporting app that integrates with AWS S3 demonstrates the power of combining APIs, cloud storage, and Python automation. This project retrieves live weather data using the OpenWeather API, processes it, and securely stores it in S3 for future use.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further Enhancements&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a web interface.
&lt;/li&gt;
&lt;li&gt;Integrate data visualization tools.
&lt;/li&gt;
&lt;li&gt;Set up scheduled updates with AWS Lambda.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is a great way to sharpen your Python skills while exploring cloud technologies. Happy coding!  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Sherifsani/weather-reports" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>From Internal Server Error to Success: Debugging AWS Lambda and API Gateway</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Sat, 23 Nov 2024 17:10:40 +0000</pubDate>
      <link>https://dev.to/sherif_san/from-internal-server-error-to-success-debugging-aws-lambda-and-api-gateway-5bp9</link>
      <guid>https://dev.to/sherif_san/from-internal-server-error-to-success-debugging-aws-lambda-and-api-gateway-5bp9</guid>
      <description>&lt;p&gt;Building a serverless application is exciting—until you hit a roadblock like the dreaded &lt;strong&gt;"Internal Server Error."&lt;/strong&gt; Recently, I encountered this while creating a simple API with &lt;strong&gt;AWS Lambda&lt;/strong&gt; and &lt;strong&gt;API Gateway&lt;/strong&gt; to process query parameters and return a structured response. This post breaks down my debugging journey, what went wrong, and how I fixed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My goal was straightforward:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accept &lt;code&gt;transactionId&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;, and &lt;code&gt;amount&lt;/code&gt; as query parameters.
&lt;/li&gt;
&lt;li&gt;Log the parameters and return them in a JSON response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the Lambda function I wrote initially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;transactionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;queryStringParameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;transactionType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;queryStringParameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;transactionAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;queryStringParameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TransactionId = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transactionId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TransactionType = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transactionType&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TransactionAmount = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transactionAmount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transactionType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transactionAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from lambda land&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when I tested the API through the browser, I kept getting:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;500 Internal Server Error&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CORS errors&lt;/strong&gt; when calling the API from my frontend.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What Went Wrong?&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Missing Query Parameters:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If any query parameter was missing, the code would throw a &lt;code&gt;KeyError&lt;/code&gt;. This caused Lambda to fail and returned a generic error message without any details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Error Handling:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
There was no mechanism to catch and log errors. This made debugging harder because the API Gateway logs only showed "Internal Server Error."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CORS Issues:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The response didn’t include &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;, which is required to enable communication between the frontend and the API Gateway endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Fix&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I rewrote the Lambda function with &lt;strong&gt;robust error handling, validation, and proper CORS configuration.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Extract query string parameters
&lt;/span&gt;        &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;queryStringParameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;transactionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;transactionType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;transactionAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Validate parameters
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;transactionId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;transactionType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;transactionAmount&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Missing required query parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Log parameters
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TransactionId = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transactionId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TransactionType = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transactionType&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TransactionAmount = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transactionAmount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Create response
&lt;/span&gt;        &lt;span class="n"&gt;transactionResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transactionType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transactionAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from lambda land&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Internal Server Error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Key Changes and Why They Work&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Safe Parameter Extraction:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Instead of directly accessing &lt;code&gt;event['queryStringParameters']&lt;/code&gt;, I used &lt;code&gt;.get()&lt;/code&gt; with default values to prevent &lt;code&gt;KeyError&lt;/code&gt; exceptions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validation:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The code now checks if required parameters are missing and raises a &lt;code&gt;ValueError&lt;/code&gt;. This ensures we only process valid inputs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Handling with Try-Except:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Wrapping the logic in &lt;code&gt;try...except&lt;/code&gt; allows us to catch errors and return a detailed response while logging the issue for debugging in CloudWatch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CORS Headers:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Adding &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; enables the frontend to communicate with the API successfully.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Final Test&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;API Request&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"https://&amp;lt;your-api-id&amp;gt;.execute-api.us-east-1.amazonaws.com/test/transactions?transactionId=123&amp;amp;type=credit&amp;amp;amount=1000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Response&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transactionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"credit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from lambda land"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validation is Crucial:&lt;/strong&gt; Always validate inputs to ensure your application works as expected.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling Simplifies Debugging:&lt;/strong&gt; Wrapping your logic in &lt;code&gt;try...except&lt;/code&gt; helps identify issues quickly.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CORS Configuration Matters:&lt;/strong&gt; If your API serves a frontend, always include CORS headers in the response.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs Are Your Friend:&lt;/strong&gt; Use &lt;code&gt;print&lt;/code&gt; statements to log details in CloudWatch and understand what’s happening.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What’s Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that I’ve successfully implemented and tested this API, I’m moving on to integrating it with my S3 bucket for file uploads. This will involve:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating pre-signed URLs in Lambda.
&lt;/li&gt;
&lt;li&gt;Updating the frontend to handle file uploads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you encountered similar challenges while working with serverless applications? Let’s discuss in the comments!  &lt;/p&gt;




</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
      <category>devops</category>
    </item>
    <item>
      <title>Effortlessly Copy Files Between AWS S3 Buckets with a Simple Bash Script</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Thu, 03 Oct 2024 17:53:02 +0000</pubDate>
      <link>https://dev.to/sherif_san/effortlessly-copy-files-between-aws-s3-buckets-with-a-simple-bash-script-b1h</link>
      <guid>https://dev.to/sherif_san/effortlessly-copy-files-between-aws-s3-buckets-with-a-simple-bash-script-b1h</guid>
      <description>&lt;p&gt;In today's cloud-centric world, efficient data management is crucial, especially when working with AWS S3 buckets. AWS S3 is a powerful object storage service that allows you to store and retrieve any amount of data at any time, making it ideal for a variety of use cases such as backups, migrations, and data synchronization. Automating the process of copying files between S3 buckets can save you time and reduce the potential for errors. In this article, I’ll walk you through a straightforward Bash script that facilitates this process while ensuring that AWS credentials are configured correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview of the Project
&lt;/h3&gt;

&lt;p&gt;The goal of this project is to create a Bash script that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts the user to configure their AWS credentials if they are not already set.&lt;/li&gt;
&lt;li&gt;Lists all available S3 buckets.&lt;/li&gt;
&lt;li&gt;Asks the user for the source and destination bucket names.&lt;/li&gt;
&lt;li&gt;Copies files recursively from the source bucket to the destination bucket.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before diving into the script, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Linux machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt; installed and configured on your machine.&lt;/li&gt;
&lt;li&gt;Valid AWS credentials with the necessary permissions to access S3 services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Script
&lt;/h3&gt;

&lt;p&gt;Here’s the complete Bash script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32m---------------COPY FILES BETWEEN S3 BUCKETS-----------------&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;

&lt;span class="c"&gt;# Check if AWS credentials are configured&lt;/span&gt;
aws sts get-caller-identity &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[31mAWS credentials are not configured. Please configure your credentials:&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
  aws configure
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32mAWS credentials are already configured.&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32m---------------Listing all buckets-----------------&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;ls

read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the source bucket name: "&lt;/span&gt; source_bucket
&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the destination bucket name: "&lt;/span&gt; destination_bucket

&lt;span class="c"&gt;# Copy files between the buckets&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp &lt;/span&gt;s3://&lt;span class="nv"&gt;$source_bucket&lt;/span&gt;/ s3://&lt;span class="nv"&gt;$destination_bucket&lt;/span&gt;/ &lt;span class="nt"&gt;--recursive&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32m---------------Files copied successfully-----------------&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[31m---------------An error occurred while copying files-----------------&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Greeting and Instructions&lt;/strong&gt;: The script begins with a greeting and informs the user about the AWS credentials configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Credentials Check&lt;/strong&gt;: It executes the &lt;code&gt;aws sts get-caller-identity&lt;/code&gt; command to verify that the AWS CLI can access the configured credentials. 

&lt;ul&gt;
&lt;li&gt;If credentials are not set up, the script prompts the user to run &lt;code&gt;aws configure&lt;/code&gt; to set them up.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listing S3 Buckets&lt;/strong&gt;: After verifying credentials, the script lists all available S3 buckets using &lt;code&gt;aws s3 ls&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Input for Buckets&lt;/strong&gt;: The script prompts the user for the source and destination bucket names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copying Files&lt;/strong&gt;: It utilizes the &lt;code&gt;aws s3 cp&lt;/code&gt; command with the &lt;code&gt;--recursive&lt;/code&gt; flag to copy all files from the source bucket to the destination bucket. Additionally, it checks the success of the copy operation and provides appropriate feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Completion Message&lt;/strong&gt;: Finally, it confirms whether the files have been copied successfully or if an error occurred.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Benefits of Automation
&lt;/h3&gt;

&lt;p&gt;Automating tasks like copying files between S3 buckets offers several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time-saving&lt;/strong&gt;: Quickly transfer large volumes of data without manual effort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error reduction&lt;/strong&gt;: Minimizes human error in file handling and data migration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: Ensures that the same process is followed every time, enhancing reliability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This simple Bash script demonstrates how to automate the process of copying files between AWS S3 buckets while ensuring your AWS credentials are configured correctly. As you develop more complex AWS solutions, this foundational knowledge will be invaluable in streamlining your workflows.&lt;/p&gt;

&lt;p&gt;As you implement this script, consider enhancing it with features like error handling, logging, or scheduling tasks with cron jobs. Reflecting on what I've learned today, I’m excited to explore more automation possibilities within AWS.&lt;/p&gt;

&lt;p&gt;Thank you for reading! Have you worked on similar projects? Share your experiences in the comments below, and happy scripting!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>bash</category>
      <category>linux</category>
    </item>
    <item>
      <title>My journey into the cloud</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Sat, 14 Sep 2024 15:34:52 +0000</pubDate>
      <link>https://dev.to/sherif_san/my-journey-into-the-cloud-5h9a</link>
      <guid>https://dev.to/sherif_san/my-journey-into-the-cloud-5h9a</guid>
      <description>&lt;h1&gt;
  
  
  My First Week Learning AWS: S3, S3 CLI, and Lambda Integration
&lt;/h1&gt;

&lt;p&gt;Hi there! This is my first time writing an article, so I’m excited to share what I’ve learned this week on my AWS journey. If you're new to AWS like me, I hope this will be helpful, and maybe even inspire you to dive deeper into cloud technologies!&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned This Week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Amazon S3 (Simple Storage Service)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;S3 is AWS’s service for storing and retrieving data in the cloud. I found it incredibly versatile. You can store anything from images to large datasets. It’s like a giant cloud-based storage drive, but with some really cool features like versioning, encryption, and fine-grained permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;S3 CLI (Command Line Interface)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The AWS CLI makes interacting with S3 much easier through the command line. At first, I was a bit intimidated, but after learning the basic commands like &lt;code&gt;aws s3 cp&lt;/code&gt; for copying files, and &lt;code&gt;aws s3 ls&lt;/code&gt; to list content, I realized how powerful and efficient the CLI can be. It makes managing S3 buckets so much faster than using the console.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Integrating S3 with Lambda&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lambda allows you to run code in response to events, without having to manage servers. I spent some time integrating S3 with Lambda to automate tasks, like triggering a Lambda function when a new file is uploaded to an S3 bucket. This opens up so many possibilities, like processing images, validating file uploads, or generating logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;Next week, I’m diving deeper into Lambda! I’ll be learning more advanced features and building an &lt;strong&gt;image-sharing app&lt;/strong&gt; that combines S3 and Lambda. I’m really excited about this project and can’t wait to share what I learn!&lt;/p&gt;




&lt;p&gt;If you're interested in cloud engineering or AWS, stay tuned for more of my learning journey. Feel free to share your own experiences or ask any questions in the comments!&lt;/p&gt;

&lt;p&gt;also, I'd greatly appreciate it if anyone can provide me with a good roadmap to become a cloud engineer.&lt;/p&gt;

&lt;p&gt;thanks for reading 🙏&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Exploring Frontend Technologies: Svelte vs. Alpine.js</title>
      <dc:creator>Sherif sani</dc:creator>
      <pubDate>Thu, 04 Jul 2024 15:43:27 +0000</pubDate>
      <link>https://dev.to/sherif_san/exploring-frontend-technologies-svelte-vs-alpinejs-4il6</link>
      <guid>https://dev.to/sherif_san/exploring-frontend-technologies-svelte-vs-alpinejs-4il6</guid>
      <description>&lt;p&gt;Introduction&lt;/p&gt;

&lt;p&gt;Frontend development has seen a massive evolution over the years, introducing a plethora of frameworks and libraries to enhance user experiences. While giants like ReactJS, Angular, and Vue.js often dominate the conversation, there are some niche players that offer unique advantages. In this article, we'll dive into two such technologies: Svelte and Alpine.js. We'll explore their core principles, use cases, and why they might be better suited for certain projects. Additionally, I'll share my thoughts on using ReactJS during the HNG internship and how I feel about this journey.&lt;/p&gt;

&lt;p&gt;Svelte: The Compiler Approach&lt;/p&gt;

&lt;p&gt;What is Svelte?&lt;/p&gt;

&lt;p&gt;Svelte is a relatively new frontend framework created by Rich Harris. Unlike traditional frameworks that do much of their work in the browser, Svelte shifts that work to compile time. This means that instead of shipping a framework to the client, Svelte applications compile down to highly optimized vanilla JavaScript at build time.&lt;/p&gt;

&lt;p&gt;Key Features of Svelte&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Virtual DOM&lt;/strong&gt;: Svelte eliminates the need for a virtual DOM, which can lead to faster and more efficient updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Truly Reactive&lt;/strong&gt;: With Svelte, reactivity is built into the language itself. You simply declare your state and bindings, and Svelte handles the rest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal Bundle Size&lt;/strong&gt;: Since Svelte compiles components down to minimal JavaScript, the bundle sizes are often significantly smaller compared to other frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use Cases for Svelte&lt;/p&gt;

&lt;p&gt;Svelte is ideal for projects where performance is critical, and bundle size needs to be minimized. It's also great for developers who prefer a more straightforward, less boilerplate-heavy development experience.&lt;/p&gt;

&lt;p&gt;Alpine.js: The Lightweight Contender&lt;/p&gt;

&lt;p&gt;What is Alpine.js?&lt;/p&gt;

&lt;p&gt;Alpine.js is a minimalistic framework designed for adding interactivity to your HTML. It draws inspiration from frameworks like Vue.js but aims to be lightweight and easy to integrate into existing projects without a build step.&lt;/p&gt;

&lt;p&gt;Key Features of Alpine.js&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tiny Footprint&lt;/strong&gt;: With a very small file size, Alpine.js can be included in any project with minimal impact on load times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative Syntax&lt;/strong&gt;: Similar to Vue and Angular, Alpine uses a declarative syntax that makes it easy to understand and write.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Build Process&lt;/strong&gt;: Alpine.js doesn't require a build step, making it perfect for adding interactivity to static sites or enhancing server-rendered pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use Cases for Alpine.js&lt;/p&gt;

&lt;p&gt;Alpine.js shines in scenarios where you need to add a sprinkle of JavaScript interactivity without the overhead of a full-fledged framework. It's perfect for static sites, server-rendered pages, or any project where simplicity and speed are priorities.&lt;/p&gt;

&lt;p&gt;Comparing Svelte and Alpine.js&lt;/p&gt;

&lt;p&gt;Learning Curve&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Svelte&lt;/strong&gt;: Has a moderate learning curve. If you're familiar with modern JavaScript and frameworks, you'll find Svelte's syntax and reactivity straightforward to grasp.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpine.js&lt;/strong&gt;: Very low learning curve. If you know basic HTML, CSS, and JavaScript, you can start using Alpine.js almost immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Performance&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Svelte&lt;/strong&gt;: Offers superior performance due to its compilation approach, making it ideal for high-performance applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpine.js&lt;/strong&gt;: While not as performant as Svelte, Alpine's small size and direct DOM manipulation make it quite efficient for its use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ecosystem and Community&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Svelte&lt;/strong&gt;: Has a growing ecosystem with tools like SvelteKit, and a vibrant, supportive community.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpine.js&lt;/strong&gt;: Smaller ecosystem but rapidly growing. Its simplicity means you can often use it alongside other tools without conflict.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My Journey with ReactJS in the HNG Internship&lt;/p&gt;

&lt;p&gt;During the HNG internship, ReactJS is the primary framework we'll be using. React is a powerful, component-based library that allows developers to build dynamic user interfaces with ease. I'm excited to delve deeper into React, leveraging its rich ecosystem, and state management tools like Redux or Context API.&lt;/p&gt;

&lt;p&gt;React's virtual DOM, component-based architecture, and vast community support make it a versatile tool for building scalable applications. I anticipate working on real-world projects, collaborating with other interns, and honing my skills to become proficient in React development.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;Both Svelte and Alpine.js offer unique advantages depending on the project's requirements. Svelte is perfect for high-performance applications with its compile-time optimization, while Alpine.js excels in simplicity and ease of integration for lightweight interactive components.&lt;/p&gt;

&lt;p&gt;As I embark on my journey with the HNG internship, I'm eager to expand my knowledge and skills in frontend development, particularly with ReactJS. The hands-on experience and mentorship opportunities will undoubtedly be invaluable.&lt;/p&gt;

&lt;p&gt;If you're interested in learning more about the HNG Internship program, check out these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG Internship&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hng.tech/premium" rel="noopener noreferrer"&gt;HNG Premium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
