<?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: Akua Konadu</title>
    <description>The latest articles on DEV Community by Akua Konadu (@adonaitechnologies).</description>
    <link>https://dev.to/adonaitechnologies</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%2F1653391%2F1179df07-38a8-48b8-9781-4d008bd19643.jpg</url>
      <title>DEV Community: Akua Konadu</title>
      <link>https://dev.to/adonaitechnologies</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adonaitechnologies"/>
    <language>en</language>
    <item>
      <title>Next-Level Intranet: OfficeSpace with Dark Mode &amp; Widgets</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Thu, 24 Jul 2025 14:58:53 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/next-level-intranet-officespace-with-dark-mode-widgets-de7</link>
      <guid>https://dev.to/adonaitechnologies/next-level-intranet-officespace-with-dark-mode-widgets-de7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend/axero"&gt;Frontend Challenge: Office Edition sponsored by Axero, Holistic Webdev: Office Space&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;My intranet layout is a modern, responsive dashboard designed to boost engagement and productivity. It features a hero section, team spotlight, upcoming events carousel, quick links, and a sticky sidebar with live widgets (clock, weather, notifications). I aimed to create a dynamic, user-friendly space with personalization (drag-and-drop widgets), dark mode, and smooth animations for an interactive experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://adonai-technologies.github.io/dream-intranet/" rel="noopener noreferrer"&gt;Demo Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/dream-intranet.git" rel="noopener noreferrer"&gt;Repo Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;I started by planning a clean layout that mimics a real company intranet, then built the structure in HTML and styled it for a modern, responsive design with CSS Grid and Flexbox. After that, I added interactivity with JavaScript, including dark mode, an auto-sliding event carousel with swipe support, and a sticky sidebar with real-time widgets (clock, weather, and notifications).&lt;/p&gt;

&lt;p&gt;One of my proudest choices was implementing drag-and-drop widgets in the sidebar with Local Storage, giving users the ability to personalize their dashboard. This feature makes the intranet feel dynamic and user-centric.&lt;/p&gt;

&lt;p&gt;I learned how to combine responsive design, smooth animations, and interactive features in a way that feels like a real digital workspace employees would use daily.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>frontendchallenge</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Inbox Translator: Automatic Email Translation Made Easy</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Sun, 08 Jun 2025 20:48:27 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/inbox-translator-automatic-email-translation-made-easy-2hc7</link>
      <guid>https://dev.to/adonaitechnologies/inbox-translator-automatic-email-translation-made-easy-2hc7</guid>
      <description>&lt;p&gt;This is a submission for the &lt;a href="https://dev.to/challenges/postmark"&gt;Postmark Challenge: Inbox Innovators&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Inbox Translator is an AI-powered email translation app that automatically translates incoming emails into English using OpenRouter’s GPT-3.5-turbo model. Integrated with Postmark’s inbound email parsing, the app listens for emails sent to a dedicated address, translates their content seamlessly, and sends back the translated message to the sender.&lt;/p&gt;

&lt;p&gt;Designed with a sleek, dark-themed, responsive UI, Inbox Translator offers users a simple way to overcome language barriers in email communication without any manual effort. This solution is ideal for professionals, businesses, and anyone who regularly receives emails in different languages and wants fast, reliable translations directly in their inbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://indox-translator.onrender.com/" rel="noopener noreferrer"&gt;Demo link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/indox-translator.git" rel="noopener noreferrer"&gt;Repo Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🛠 Step-by-Step Guide: Building the Inbox Translator App&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1️⃣ Project Setup&lt;br&gt;
Tools: Node.js, Express, EJS, TailwindCSS&lt;/p&gt;

&lt;p&gt;Initialized the project using npm init&lt;/p&gt;

&lt;p&gt;Installed required packages:&lt;br&gt;
 &lt;code&gt;npm install express ejs body-parser dotenv postmark node-fetch&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Set up project folders:&lt;br&gt;
&lt;code&gt;/views        → EJS templates  &lt;br&gt;
/public       → Static CSS (Tailwind)  &lt;br&gt;
index.js      → Main server logic  &lt;br&gt;
.env          → Environment config  &lt;br&gt;
&lt;/code&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%2Fa4g2fwakj9m8fb44qidu.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%2Fa4g2fwakj9m8fb44qidu.png" alt=" " width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2️⃣ Set Up Postmark for Inbound Emails&lt;/strong&gt;&lt;br&gt;
Steps:&lt;br&gt;
Created a Postmark account and set up a new Inbound Stream.&lt;br&gt;
Set your Inbound Webhook URL to your deployed endpoint:&lt;br&gt;
(&lt;a href="https://inbox-translator.onrender.com/inbound-email" rel="noopener noreferrer"&gt;https://inbox-translator.onrender.com/inbound-email&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Verified the domain or used Postmark’s testing domain (inbound.postmarkapp.com)&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%2Fdkp3r3yvwupgs0id6h5h.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%2Fdkp3r3yvwupgs0id6h5h.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3️⃣ Handling Incoming Emails&lt;/strong&gt;&lt;br&gt;
How it works:&lt;br&gt;
The webhook /inbound-email receives incoming email data from Postmark.&lt;br&gt;
It logs the sender and the original message content.&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%2Fbeqi27fk7lwmdcnhviah.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%2Fbeqi27fk7lwmdcnhviah.png" alt=" " width="800" height="265"&gt;&lt;/a&gt;&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%2Fvkw34c4o31egmv4uwy1a.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%2Fvkw34c4o31egmv4uwy1a.png" alt=" " width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4️⃣ Language Detection &amp;amp; Conditional Translation&lt;/strong&gt;&lt;br&gt;
Tools: LibreTranslate + OpenRouter GPT-3.5&lt;/p&gt;

&lt;p&gt;Used LibreTranslate to detect if the email is already in English.&lt;/p&gt;

&lt;p&gt;If not, used OpenRouter (GPT-3.5-turbo) to translate the message to English.&lt;/p&gt;

&lt;p&gt;Example logic:&lt;code&gt;if (language !== 'en') {&lt;br&gt;
  // translate using OpenRouter AI&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;5️⃣ Sending Back the Translated Email&lt;/strong&gt;&lt;br&gt;
Used Postmark’s sendEmail method to reply to the original sender.&lt;/p&gt;

&lt;p&gt;Dynamic subject and body:&lt;code&gt;Subject: "Translated Email (Inbox Translator)"&lt;br&gt;
TextBody:&lt;/code&gt;Here is your translated message:\n\n${translatedText}&lt;code&gt;&lt;br&gt;
&lt;/code&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%2Fdjda66j2hdt80iy4swkl.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%2Fdjda66j2hdt80iy4swkl.png" alt=" " width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6️⃣** Frontend UI — Viewing Translations**&lt;br&gt;
Tools: EJS + Tailwind CSS&lt;/p&gt;

&lt;p&gt;Created a dark-themed interface to display email history.&lt;/p&gt;

&lt;p&gt;Emails are stored in-memory and rendered as responsive cards.&lt;/p&gt;

&lt;p&gt;Added a dark/light toggle and smooth animations.&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%2Fbxbmy5u28m2jphg7ftq9.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%2Fbxbmy5u28m2jphg7ftq9.png" alt=" " width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Summary: Tech Stack&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tool/Service&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Node.js + Express&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;EJS + Tailwind CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email Engine&lt;/td&gt;
&lt;td&gt;Postmark (Inbound + Outbound)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Translation&lt;/td&gt;
&lt;td&gt;GPT-3.5-turbo via OpenRouter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Render.com&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>devchallenge</category>
      <category>postmarkchallenge</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>I joined the alibaba cloud challenge but never got a completion badge</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Mon, 12 May 2025 08:44:52 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/i-joined-the-alibaba-cloud-challenge-but-never-got-a-completion-badge-1hpg</link>
      <guid>https://dev.to/adonaitechnologies/i-joined-the-alibaba-cloud-challenge-but-never-got-a-completion-badge-1hpg</guid>
      <description>&lt;p&gt;Please Can anybody explain to me or tag the moderators for me&lt;/p&gt;

</description>
      <category>alibabachallenge</category>
      <category>discuss</category>
      <category>support</category>
    </item>
    <item>
      <title>RetroMix DJ: An AI-Enhanced Digital Mixing Experience</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Sun, 11 May 2025 08:59:08 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/retromix-dj-an-ai-enhanced-digital-mixing-experience-3bil</link>
      <guid>https://dev.to/adonaitechnologies/retromix-dj-an-ai-enhanced-digital-mixing-experience-3bil</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aws-amazon-q-v2025-04-30"&gt;Amazon Q Developer "Quack The Code" Challenge&lt;/a&gt;: That's Entertainment!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;RetroMix DJ is a browser-based digital DJ application that combines nostalgic retro aesthetics with professional-grade mixing capabilities. It's a complete&lt;br&gt;
virtual DJ console that allows users to mix tracks, apply effects, trigger samples, and create dynamic performances - all within their web browser.&lt;/p&gt;

&lt;p&gt;The application features a vibrant, retro-inspired interface with multiple visual themes (Retro, Modern, Neon, and Minimal) that evoke the nostalgic feel of&lt;br&gt;
classic electronic music equipment while providing modern functionality. The neon colors, pixelated fonts, and vintage-style controls create an immersive&lt;br&gt;
experience that's visually engaging and fun to interact with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Professional DJ Capabilities&lt;/strong&gt;&lt;br&gt;
Despite its playful appearance, RetroMix DJ offers serious mixing capabilities:&lt;br&gt;
• Dual-deck system with independent controls&lt;br&gt;
• Real-time waveform visualization with beat detection&lt;br&gt;
• Loop and hot cue system for precise performance control&lt;br&gt;
• Advanced audio effects (reverb, delay, flanger, distortion)&lt;br&gt;
• Professional compression tools including multiband and sidechain&lt;br&gt;
• Sample pads for triggering one-shot sounds and loops&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-Powered Features&lt;/strong&gt;&lt;br&gt;
The application incorporates innovative AI features that make mixing more accessible and creative:&lt;br&gt;
• Auto DJ functionality that automatically selects and mixes compatible tracks&lt;br&gt;
• Smart track recommendations based on BPM, key, and style&lt;br&gt;
• Vocal isolation for creative acapella mixing&lt;br&gt;
• Style-based track matching for cohesive sets&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%2Fs8lkd47pei5cf31dh7ts.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%2Fs8lkd47pei5cf31dh7ts.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interactive Learning Experience&lt;/strong&gt;&lt;br&gt;
  RetroMix DJ serves as both entertainment and an educational tool:&lt;br&gt;
• Users can learn DJ techniques in a fun, low-pressure environment&lt;br&gt;
• Visual feedback helps understand concepts like beat matching and EQ&lt;br&gt;
• The interface mimics professional equipment, building transferable skills&lt;br&gt;
• Real-time audio visualizers demonstrate how sound changes with different &lt;br&gt;
 effects&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creative Freedom&lt;/strong&gt;&lt;br&gt;
  The application encourages experimentation and creativity:&lt;br&gt;
• Customizable sample pads let users add their own sounds&lt;br&gt;
• Multiple effect combinations create unique sonic textures&lt;br&gt;
• Track management system helps organize music by style and mood&lt;br&gt;
• Drag-and-drop functionality makes library management intuitive&lt;/p&gt;

&lt;p&gt;RetroMix DJ transforms the technical complexity of DJing into an accessible, entertaining experience that appeals to both beginners and experienced DJs. It&lt;br&gt;
balances nostalgic design with modern functionality, creating a unique platform where users can learn, create, and perform music in an engaging and visually&lt;br&gt;
stimulating environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;



&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/pA6veAkAJ6s"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gregarious-sorbet-48860e.netlify.app/" rel="noopener noreferrer"&gt;Deployed Project Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/retromix-DJ" rel="noopener noreferrer"&gt;Repository Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Amazon Q Developer
&lt;/h2&gt;

&lt;p&gt;Amazon Q Developer was instrumental throughout the entire development process of RetroMix DJ, serving as both a coding partner and technical advisor. Here's&lt;br&gt;
how I leveraged this powerful tool to create a comprehensive DJ application:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Initial Architecture and Core Functionality&lt;/strong&gt;&lt;br&gt;
     I started by describing my vision for a browser-based DJ application &lt;br&gt;
     with retro aesthetics to Amazon Q. It helped me:&lt;/p&gt;

&lt;p&gt;• Design the overall architecture using the Web Audio API&lt;br&gt;
• Generate the HTML structure for the dual-deck interface&lt;br&gt;
• Create the CSS styling for the retro visual themes&lt;br&gt;
• Implement core audio processing functionality&lt;/p&gt;

&lt;p&gt;Amazon Q was particularly helpful in explaining complex Web Audio API concepts and generating the necessary code for audio routing, gain staging, and EQ&lt;br&gt;
implementation.&lt;/p&gt;

&lt;p&gt;2.&lt;strong&gt;Iterative Feature Development&lt;/strong&gt;&lt;br&gt;
As development progressed, I used Amazon Q to iteratively add more sophisticated features:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Loop and Hot Cue System: When I needed precise beat control, Amazon Q helped implement a complete looping system with beat detection and quantization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Sample Pad Integration: Amazon Q generated code for the sample trigger system, including loading, processing, and playing audio samples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Track Management System: When I wanted to add library management, Amazon Q created a comprehensive system with metadata extraction, playlist management,&lt;br&gt;
and smart recommendations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Advanced Audio Processing: For professional-grade effects, Amazon Q implemented reverb, delay, flanger, and distortion algorithms, plus multiband&lt;br&gt;
compression and sidechain processing.&lt;/p&gt;

&lt;p&gt;3.&lt;strong&gt;Problem Solving and Debugging&lt;/strong&gt;&lt;br&gt;
 Amazon Q excelled at helping me troubleshoot issues:&lt;/p&gt;

&lt;p&gt;• When the theme switching wasn't working, Amazon Q identified the missing event connections&lt;br&gt;
• When audio processing caused performance issues, it suggested optimizations&lt;br&gt;
• When UI elements weren't responsive, it provided CSS fixes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tips and Insights for Using Amazon Q Developer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Based on my experience, here are some valuable insights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Start with a Clear Vision: Providing Amazon Q with a detailed description of what you want to build yields better initial results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Iterative Refinement: Rather than asking for everything at once, build features incrementally and refine them with Amazon Q's help.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain Technical Context: When facing issues, providing Amazon Q with error messages and relevant code snippets leads to more accurate solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn Through Collaboration: Ask Amazon Q to explain complex concepts in the generated code—I learned a tremendous amount about audio processing this way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Combine Generated Code with Your Ideas: Some of the best features came from my high-level ideas that Amazon Q helped implement technically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request Optimizations: After getting working code, ask Amazon Q for performance improvements—it often suggested more efficient approaches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain File Organization: As the project grew, Amazon Q helped maintain a clean architecture by suggesting proper file organization.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amazon Q Developer transformed the development process from what would have been weeks of research and coding into a collaborative experience where I could&lt;br&gt;
focus on creative direction while it handled technical implementation. The result is a feature-rich application that would have been significantly more&lt;br&gt;
challenging to build without this powerful AI assistant.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>awschallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AI Summary Manager with Role-Based Access Control</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Sat, 03 May 2025 22:11:16 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/ai-summary-manager-with-role-based-access-control-4nch</link>
      <guid>https://dev.to/adonaitechnologies/ai-summary-manager-with-role-based-access-control-4nch</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/permit_io"&gt;Permit.io Authorization Challenge&lt;/a&gt;: AI Access Control&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built an &lt;strong&gt;AI Content Assistant&lt;/strong&gt;, is an AI-powered content summarization tool enhanced with fine-grained access control using Permit.io. It allows users to submit content for summarization using AI (mocked in this version), while only authorized roles such as admins can review and publish the generated summaries. The goal is to demonstrate how externalized authorization can be used to secure AI-driven workflows in a real-world application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem It Solves:&lt;/strong&gt;&lt;br&gt;
In many content-heavy environments—like media companies, knowledge bases, or educational platforms—AI can streamline the summarization process. However, there’s often a need to ensure that only approved personnel can review or publish AI-generated output. This project solves that by integrating Permit.io to manage access control declaratively and securely, ensuring users only perform actions they're authorized for. It helps prevent unauthorized publishing of unreviewed AI content while maintaining a seamless workflow between users and reviewers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ai-content-assistant-xi.vercel.app/" rel="noopener noreferrer"&gt;Demo Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ai-content-assistant-xi.vercel.app/" rel="noopener noreferrer"&gt;Repo Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Process &amp;amp; Challenges:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My process began by outlining the core functionality of the AI Content Assistant: allowing users to submit text content for summarization using AI, and enforcing fine-grained authorization through Permit.io. The goal was to build two distinct experiences—one for content users, and another for admins/reviewers who manage approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key steps I followed:&lt;/strong&gt;&lt;br&gt;
  &lt;strong&gt;Project Setup&lt;/strong&gt; &lt;br&gt;
  I initialized a modern frontend with Vite, React, TypeScript, and &lt;br&gt;
  TailwindCSS, and used Node.js with Express for the backend. I chose &lt;br&gt;
  Render for backend deployment and Vercel for the frontend for quick and &lt;br&gt;
  cost-effective hosting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Permit.io Authorization Integration&lt;/strong&gt;&lt;br&gt;
Using Permit.io’s SDK, we created roles (user, admin) and enforced permissions through declarative permit.check() calls. For example, users could only summarize content, while admins were the only ones authorized to review or publish.&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%2Fn867xbo3tntne9vyhk0z.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%2Fn867xbo3tntne9vyhk0z.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Integration &amp;amp; Challenge Mitigation&lt;/strong&gt;&lt;br&gt;
  Initially, I planned to use OpenAI's API for summarization, but ran into &lt;br&gt;
  quota limitations and couldn’t afford a paid plan. To overcome this, I &lt;br&gt;
  mocked the AI responses in a realistic way, allowing the core flow of &lt;br&gt;
  the app to remain intact and testable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrating Fine-Grained Authorization with Permit.io&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used &lt;strong&gt;permit.check()&lt;/strong&gt; to enforce who can:&lt;br&gt;
Submit content (&lt;em&gt;user&lt;/em&gt;)&lt;br&gt;
Review and publish summaries (&lt;em&gt;admin&lt;/em&gt;)&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%2Fk3f7wd78lqrh0u1qzx4m.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%2Fk3f7wd78lqrh0u1qzx4m.png" alt=" " width="800" height="321"&gt;&lt;/a&gt;&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%2Fese8qi9kwkmaf6lw8g8q.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%2Fese8qi9kwkmaf6lw8g8q.png" alt=" " width="800" height="286"&gt;&lt;/a&gt;&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%2F5ipd9w1l0gix37ndhbni.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%2F5ipd9w1l0gix37ndhbni.png" alt=" " width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User &amp;amp; Admin Interfaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I built:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A **User Dashboard **where content can be submitted and feedback is received on submission.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;Admin Dashboard&lt;/strong&gt; where pending summaries are listed with options to approve or reject.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UI Feedback and UX Polish&lt;/strong&gt;&lt;br&gt;
We implemented alerts to notify users when submissions were successful or when errors occurred, improving usability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing Authorization Paths&lt;/strong&gt;&lt;br&gt;
A big part of the challenge was validating that Permit.io’s rules were correctly enforced. We tested each API endpoint with both roles to confirm that unauthorized actions were blocked as expected.&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%2Fkv5lipf67e8udb44qbbu.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%2Fkv5lipf67e8udb44qbbu.png" alt=" " width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚧 Challenges Faced &amp;amp; How We Solved Them&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;API Quota Exceeded (OpenAI):&lt;/strong&gt;&lt;br&gt;
Once our OpenAI usage quota was exceeded, the backend returned 429 errors. Rather than halting progress, we mocked the summarization logic to simulate AI behavior, keeping the project on track.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role-Based Access Control Logic:&lt;/strong&gt;&lt;br&gt;
Ensuring that authorization checks were properly scoped to each endpoint required close coordination between frontend logic and Permit.io policy definitions. Debugging was made easier using Permit.io’s activity logs and Policy Studio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Feedback on Submission:&lt;/strong&gt;&lt;br&gt;
Initially, users had no confirmation that their content had been processed. We resolved this by adding alert modals and real-time UI updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization for AI Applications with Permit.io
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🔐 How We Built Authorization Controls Specifically for AI-Based Tools or Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;AI Content Assistant&lt;/strong&gt;, I applied fine-grained access control using Permit.io to ensure that AI-powered features like content summarization and publishing could only be accessed by authorized roles. Here's how we structured and implemented the authorization:&lt;/p&gt;

&lt;p&gt;🧩 &lt;strong&gt;Roles and Permissions Design&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  I defined two roles within the Permit.io Policy Editor:
  **User:**
    Has permission to summarize content using the AI feature.

  Cannot view, approve, or publish summaries.

 **Admin:**
  Can access the /review and /review/:id endpoints.

  Has permissions to review, approve, or reject AI-generated 
  summaries.

  Can view published content.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;🧠 AI Feature Protection with **permit.check()&lt;/strong&gt;**&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    At every backend route related to AI operations, we wrapped access 
    in _permit.check()_ calls. For example:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     ```
      const allowed = await permit.check(user, "summarize", 
      "content");
      if (!allowed) return res.status(403).json({ error: "Not 
      authorized to summarize content" });

     ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that even if a user tries to access a protected route manually (e.g., via Postman or dev tools), they’ll be denied unless their role explicitly allows it.&lt;/p&gt;

&lt;p&gt;I used this same pattern for:&lt;/p&gt;

&lt;p&gt;_/ai/summarize _→ to protect the AI summarization endpoint.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/review and /review/:id&lt;/em&gt; → to ensure only admins can review and manage content.&lt;/p&gt;

&lt;p&gt;_/published _→ to restrict access to approved summaries only to authorized roles&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔍 Why Externalized Authorization Was Critical&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of hardcoding access rules into the application logic, Permit.io allowed us to &lt;strong&gt;declaratively manage permissions&lt;/strong&gt;. This gave us several benefits:&lt;/p&gt;

&lt;p&gt;We could easily &lt;em&gt;update or test roles&lt;/em&gt; without changing the backend code.&lt;/p&gt;

&lt;p&gt;Authorization logic was &lt;strong&gt;consistent and transparent&lt;/strong&gt; across the app.&lt;/p&gt;

&lt;p&gt;It helped demonstrate real-world, &lt;strong&gt;secure handling of AI tools&lt;/strong&gt;, which is especially important for tools that can influence published content or decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Permit.io for authorization allowed us to:&lt;/p&gt;

&lt;p&gt;Secure our AI-powered routes without writing complex custom middleware.&lt;/p&gt;

&lt;p&gt;Enforce least-privilege access.&lt;/p&gt;

&lt;p&gt;Easily scale the permission system as we add more roles or features.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>permitchallenge</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Permit-Powered Task Manager: API-First Access Control in Action</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Fri, 02 May 2025 15:54:16 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/permit-powered-task-manager-api-first-access-control-in-action-55d</link>
      <guid>https://dev.to/adonaitechnologies/permit-powered-task-manager-api-first-access-control-in-action-55d</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/permit_io"&gt;Permit.io Authorization Challenge&lt;/a&gt;: API-First Authorization Reimagined&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a &lt;strong&gt;Task Manager API&lt;/strong&gt; — think of it like a digital notebook where people can create, update, or delete their to-dos (we call them “tasks”). But here’s the cool part: not everyone is allowed to do everything. Some people (admins) can add and remove tasks, while others (users) can only view them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem does it solve?&lt;/strong&gt;&lt;br&gt;
In many apps, rules about who can do what (called authorization) are written deep inside the code. That’s like building a house where the doors are nailed shut — hard to open, hard to change. If you want to update who can come in or out, you need to tear the walls apart!&lt;/p&gt;

&lt;p&gt;Instead, the app uses a tool called Permit.io to handle those rules outside the code, like having a smart security guard at the door. We tell Permit.io who the admins are, who the users are, and what each can do — and Permit makes sure those rules are followed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is that awesome?&lt;/strong&gt;&lt;br&gt;
🧩 Easy to change rules without breaking anything&lt;/p&gt;

&lt;p&gt;🔐 Super safe — users only see or do what they’re allowed to&lt;/p&gt;

&lt;p&gt;🧼 Clean code — no messy “if admin do this” scattered everywhere&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-life example&lt;/strong&gt;:&lt;br&gt;
Let’s say this app was used by schools. The headteacher (admin) can create homework, and the students (users) can only view it. Using Permit.io, we can control all this easily — even if we have 1,000 schools with their own teachers and students!&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You can test the live Task Manager API here:&lt;/strong&gt;&lt;br&gt;
👉 &lt;a href="https://task-manager-t318.onrender.com" rel="noopener noreferrer"&gt;https://task-manager-t318.onrender.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;: This is a backend API. You’ll need a tool like Postman to interact with it.&lt;/p&gt;

&lt;p&gt;🧪 &lt;strong&gt;Test Credentials&lt;/strong&gt;&lt;br&gt;
✅ Admin&lt;br&gt;
&lt;strong&gt;Username&lt;/strong&gt;: &lt;em&gt;admin&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Password&lt;/strong&gt;: &lt;em&gt;2025DEVChallenge&lt;/em&gt;&lt;br&gt;
👤 User&lt;br&gt;
&lt;strong&gt;Username&lt;/strong&gt;: &lt;em&gt;newuser&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Password&lt;/strong&gt;: &lt;em&gt;2025DEVChallenge&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🔌 &lt;strong&gt;Available API Routes&lt;/strong&gt;&lt;br&gt;
Here are the main API routes:&lt;/p&gt;

&lt;p&gt;👤 &lt;strong&gt;Authentication&lt;/strong&gt;&lt;br&gt;
  POST    /api/auth/login – Get a token&lt;/p&gt;

&lt;p&gt;🧾 Task Routes (Protected by Permit.io)&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;GET *&lt;/em&gt; /api/tenants/:tenantId/tasks – Read tasks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; /api/tenants/:tenantId/tasks – Create task&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PUT&lt;/strong&gt; /api/tenants/:tenantId/tasks/:taskId – Update task&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DELETE&lt;/strong&gt; /api/tenants/:tenantId/tasks/:taskId – Delete task&lt;/p&gt;

&lt;p&gt;Use global as the :tenantId when testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/task-manager.git" rel="noopener noreferrer"&gt;Repo Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;p&gt;This project was built to demonstrate how externalized authorization (using Permit.io) can be used to control &lt;strong&gt;who can do what&lt;/strong&gt; in a real-world API. Below is a breakdown of the process, the challenges I faced, how I solved them, and the key lessons I learned.&lt;/p&gt;

&lt;p&gt;🔨 &lt;strong&gt;Step-by-Step Process&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Set up the project structure&lt;br&gt;
Created a backend folder with routes, middleware, and utils subfolders.&lt;/p&gt;

&lt;p&gt;Initialized the project using &lt;strong&gt;npm init&lt;/strong&gt; and installed dependencies like Express, &lt;strong&gt;jsonwebtoken&lt;/strong&gt;, &lt;strong&gt;dotenv&lt;/strong&gt;, and &lt;strong&gt;permitio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; &lt;strong&gt;Built the core API&lt;/strong&gt;&lt;br&gt;
Created basic routes for authentication (/api/auth/login) and task management (/api/tenants/:tenantId/tasks).&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%2Fmkitvde5wj87wubn2n8h.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%2Fmkitvde5wj87wubn2n8h.png" alt=" " width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enabled JWT-based authentication and stored roles (admin, user) in the token.&lt;br&gt;
Used middleware to validate tokens before accessing protected routes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Integrated Permit.io&lt;/strong&gt;
Created a Permit.io account and configured resources, roles, and permissions:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Defined the task resource and CRUD actions (read, create, update, delete).&lt;/p&gt;

&lt;p&gt;Assigned permissions to roles like admin and user.&lt;/p&gt;

&lt;p&gt;Used the permit.check() method in middleware to verify permissions before allowing access.&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%2F2b7nn5nmkjcwtzgslga0.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%2F2b7nn5nmkjcwtzgslga0.png" alt=" " width="800" height="271"&gt;&lt;/a&gt;&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%2Fnzp60ssukat1p1b6r4pk.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%2Fnzp60ssukat1p1b6r4pk.png" width="800" height="296"&gt;&lt;/a&gt;&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%2Fne8jijlaj2gb9jeqep2t.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%2Fne8jijlaj2gb9jeqep2t.png" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deployed the app&lt;/strong&gt;
Deployed the backend using Render.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Made sure the .env file and node_modules were excluded via .gitignore.&lt;/p&gt;

&lt;p&gt;Verified the deployed API worked using Postman.&lt;/p&gt;

&lt;p&gt;🚧 &lt;strong&gt;Challenges Faced &amp;amp; How I Solved Them&lt;br&gt;
**&lt;br&gt;
🔐 **Permit denying access even with correct token&lt;/strong&gt;: Realized I needed to match tenant, user, and role exactly as defined in the Permit.io UI&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%2Fzsj4o5sv4lrp1m59a9t5.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%2Fzsj4o5sv4lrp1m59a9t5.png" alt=" " width="800" height="387"&gt;&lt;/a&gt;&lt;br&gt;
🚨 &lt;br&gt;
"&lt;strong&gt;secretOrPrivateKey must have a value" error&lt;/strong&gt;:   Forgot to set JWT_SECRET in the .env file during deployment — added it and redeployed&lt;/p&gt;

&lt;p&gt;🔒 &lt;strong&gt;Confusing PDP &amp;amp; API key configuration&lt;/strong&gt;: Used Permit.io docs and examples to set up pdp: "&lt;a href="https://cloudpdp.api.permit.io" rel="noopener noreferrer"&gt;https://cloudpdp.api.permit.io&lt;/a&gt;" and the correct token&lt;/p&gt;

&lt;p&gt;🔍 Understanding how roles map to actions:    Explored Permit’s visual UI to assign the right permissions to admin and user roles and test them properly&lt;/p&gt;

&lt;p&gt;📘 &lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization should not be hardcoded&lt;/strong&gt;. Using Permit.io made it easy to manage permissions without constantly editing my code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separation of concerns is powerful&lt;/strong&gt;. By keeping permissions outside the core API logic, the system is easier to update and more secure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API-first means thinking about security upfront&lt;/strong&gt;. I had to carefully design endpoints with authorization in mind from the very beginning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation and testing are critical&lt;/strong&gt;. It was much easier to validate my work because I documented everything clearly and used consistent test users.&lt;/p&gt;

&lt;h2&gt;
  
  
  API-First Authorization
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Step-by-Step Integration with Permit.io&lt;br&gt;
**&lt;br&gt;
**1. Created a Permit.io Project&lt;/strong&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%2Freybcbhtjkkbsj0qizch.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%2Freybcbhtjkkbsj0qizch.png" alt=" " width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started by creating a free account on Permit.io and setting up a new project. This gave us access to the Policy Decision Point (PDP), where all access decisions would be made.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Defined Resources and Actions&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%2Fo7x7mtcfif7icmwy5vub.png" width="800" height="347"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I defined the main resource in our app:&lt;br&gt;
task — the object we wanted to control (e.g., &lt;strong&gt;view&lt;/strong&gt;, &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt;, &lt;strong&gt;delete&lt;/strong&gt;).&lt;br&gt;
Then I listed actions users might perform on a task:&lt;br&gt;
&lt;strong&gt;read&lt;/strong&gt;, &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt;, &lt;strong&gt;delete&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Set Up Roles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;admin&lt;/strong&gt; — full access to all actions on tasks&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%2F2iah0gbavkgq7i1slj80.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%2F2iah0gbavkgq7i1slj80.png" alt=" " width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;user&lt;/strong&gt; — limited access (e.g., read-only)&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%2Fhryckxld5ne02k0c6o4c.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%2Fhryckxld5ne02k0c6o4c.png" alt=" " width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IF YOU DONT UNDERSTAND ANYTHING REFER TO THE Permit.io Docs &lt;a href="https://docs.permit.io/" rel="noopener noreferrer"&gt;from here&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Created Declarative Policies&lt;/strong&gt;
Using Permit’s visual editor, I assigned permissions based on roles:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Admins can read, create, update, and delete tasks.&lt;/p&gt;

&lt;p&gt;Users can only read tasks.&lt;br&gt;
This gave us fine-grained control over who could do what — without changing our code every time.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Integrated the Permit SDK&lt;/strong&gt;
In our Express.js backend:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I installed Permit’s Node SDK: &lt;strong&gt;npm install permitio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Configured the SDK with our API key and PDP URL from the dashboard&lt;br&gt;
Connected Permit inside our middleware to check permissions for every request&lt;br&gt;
&lt;code&gt;const { Permit } = require("permitio");&lt;br&gt;
const permit = new Permit({&lt;br&gt;
  token: process.env.PERMIT_API_KEY,&lt;br&gt;
  pdp: "https://cloudpdp.api.permit.io",&lt;br&gt;
});&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Protected Routes with Middleware&lt;/strong&gt;
We created a custom middleware &lt;strong&gt;checkPermission&lt;/strong&gt;(action, resource) that:
Extracts the user's role and tenant from their JWT
Calls &lt;strong&gt;permit.check&lt;/strong&gt;() to ask Permit.io if the action is allowed
Grants or denies access accordingly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;await permit.check({&lt;br&gt;
  user: req.user.id,&lt;br&gt;
  action: 'read',&lt;br&gt;
  resource: 'task',&lt;br&gt;
  tenant: req.user.tenant,&lt;br&gt;
});&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
🚀 &lt;strong&gt;What Makes It API-First?&lt;/strong&gt;&lt;br&gt;
Authorization is treated as part of the API design, not an afterthought.&lt;/p&gt;

&lt;p&gt;Each API route was designed with a specific permission in mind.&lt;/p&gt;

&lt;p&gt;I used middleware to enforce authorization consistently across routes.&lt;/p&gt;

&lt;p&gt;The logic is clean and externalized, so we can change permissions without touching our backend code.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>permitchallenge</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Robot Invaders Game</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Sat, 26 Apr 2025 12:50:11 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/robot-invaders-game-5f22</link>
      <guid>https://dev.to/adonaitechnologies/robot-invaders-game-5f22</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://int.alibabacloud.com/m/1000402443/" rel="noopener noreferrer"&gt;Alibaba Cloud&lt;/a&gt; Challenge: &lt;a href="https://dev.to/challenges/alibaba"&gt;Build a Web Game&lt;/a&gt;.&lt;/em&gt;*&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;My project is called "Robo Invaders", a robot-themed web shooter game built using HTML, CSS, and JavaScript. In the game, players control a robot that defends its base by shooting waves of enemy robots. The gameplay includes different types of enemy robots, animated movements, score tracking, player health, and boss battles for added challenge.The game is designed to deliver a fun, polished experience with smooth controls and exciting robot-themed action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/robotInvaders.git" rel="noopener noreferrer"&gt;Repo Link&lt;/a&gt;&lt;br&gt;
&lt;a href="https://adonai-technologies.github.io/robotInvaders/" rel="noopener noreferrer"&gt;click here to Play&lt;/a&gt;&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%2Fjowhw0o0nbt227057et0.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%2Fjowhw0o0nbt227057et0.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[This is the default url when depoyed on Alibaba it will download the files into your system .. You can also play the game directly from your system](&lt;a href="https://roboinvadersgamestatic.oss-eu-west-1.aliyuncs.com/index.html" rel="noopener noreferrer"&gt;https://roboinvadersgamestatic.oss-eu-west-1.aliyuncs.com/index.html&lt;/a&gt;&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%2Fkgnlr39sxpzu6d7zewex.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%2Fkgnlr39sxpzu6d7zewex.png" alt=" " width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Alibaba Cloud Services Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Function Compute&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Why I chose it&lt;/strong&gt;: I needed a lightweight, scalable backend service to handle HTTP requests from my game without setting up or maintaining servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I integrated it&lt;/strong&gt;: I used Function Compute to create an Express.js server that receives high scores from the game and stores them in ApsaraDB (MongoDB). It listens for both POST and GET requests to manage scores dynamically during gameplay.&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%2F1e2edwqy19qeqj020nci.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%2F1e2edwqy19qeqj020nci.png" alt=" " width="800" height="327"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Experience&lt;/strong&gt;: The integration was smooth once I set up the right function permissions and environment. The ability to quickly deploy updates without worrying about infrastructure was a big advantage. A small challenge was understanding how to configure the public endpoint access correctly for communication with the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ApsaraDB for MongoDB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I chose it&lt;/strong&gt;: I needed a reliable, scalable database to store player high scores and game statistics. ApsaraDB for MongoDB offered a fully managed, high-availability solution that matched my game’s needs.&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%2Flgpenepwkcbpgu344jk6.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%2Flgpenepwkcbpgu344jk6.png" alt="AsparaDb for MongoDB Instance Performance" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I integrated it&lt;/strong&gt;: I connected the Function Compute server to ApsaraDB using a MongoDB connection string. Every time a player finishes a game, their score is sent to the server, which checks if it’s a new high score and saves it if necessary.&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%2F09j4b3ck1012vczqg6ro.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%2F09j4b3ck1012vczqg6ro.png" width="800" height="283"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Experience:&lt;/strong&gt; Setting up the database and IP whitelist was straightforward, and the replica set provided built-in reliability. The challenge was ensuring the connection string was correctly formatted (escaping special characters like @ in the password) and managing IP whitelisting securely without exposing public access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object Storage Service (OSS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I chose it&lt;/strong&gt;: I needed a reliable place to host and serve my static web game assets, including HTML, CSS, JavaScript, and images.&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%2F22y60soueggbpwm9fd4i.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%2F22y60soueggbpwm9fd4i.png" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I integrated it&lt;/strong&gt;: I uploaded the entire game folder to an OSS bucket and configured it as a static website, enabling direct access through a public URL.&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%2Fi6owtyifbg31q6rex64o.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%2Fi6owtyifbg31q6rex64o.png" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experience&lt;/strong&gt;: OSS made hosting super easy, and performance was excellent. Setting proper CORS rules to allow communication between the front end and backend services took a bit of testing, but documentation helped a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Game Development Highlights
&lt;/h2&gt;

&lt;p&gt;Interesting Aspects &amp;amp; Features I'm Proud Of:&lt;/p&gt;

&lt;p&gt;One of the most exciting parts of building my robot-themed game was designing the dynamic high score system. Every time a player finished a game, their score would instantly update on the leaderboard if it was a new high, and a fun "New High Score!" popup animation would celebrate their achievement. 🎉&lt;/p&gt;

&lt;p&gt;I'm also proud of how I structured the game to feel responsive and lightweight. I optimized the game to load quickly from Object Storage Service (OSS) and ensured smooth communication with ApsaraDB and Function Compute for saving player data — creating a seamless experience without noticeable lag.&lt;/p&gt;

&lt;p&gt;Additionally, even though it was a browser-based game, I added animations, enemy behavior variety, and a boss level to keep the gameplay engaging and progressively challenging. Getting all the moving parts (front end + backend + database) to sync up in a cloud environment like Alibaba Cloud was a huge achievement for me.&lt;/p&gt;

</description>
      <category>alibabachallenge</category>
      <category>devchallenge</category>
      <category>gamedev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>RoboRescue Puzzle . A logic-based grid navigation game</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Thu, 17 Apr 2025 15:48:03 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/roborescue-puzzle-a-logic-based-grid-navigation-game-mgi</link>
      <guid>https://dev.to/adonaitechnologies/roborescue-puzzle-a-logic-based-grid-navigation-game-mgi</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://int.alibabacloud.com/m/1000402443/" rel="noopener noreferrer"&gt;Alibaba Cloud&lt;/a&gt; Challenge: &lt;a href="https://dev.to/challenges/alibaba"&gt;Build a Web Game&lt;/a&gt;.&lt;/em&gt;*&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;RoboRescue Puzzle is a simple robot-themed puzzle game. Players guide a robot through a 5x5 grid filled with obstacles, aiming to reach the green goal tile. Players use commands like “move forward” or “turn” to solve each level. The game has multiple levels, a level select menu, a clean robot-style interface, and saves progress using both local storage and Alibaba Cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://youtube.com/shorts/J2NihWy3Ck4?feature=share" rel="noopener noreferrer"&gt;Watch How To Play The Game Here&lt;/a&gt;&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%2Fjsj46re1kq0hm3fj5gqa.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%2Fjsj46re1kq0hm3fj5gqa.png" width="800" height="496"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://robo-rescue-assets.oss-eu-central-1.aliyuncs.com/index.html" rel="noopener noreferrer"&gt;This is the default link from Alibaba when deployed. It will only Download the file on  your computer&lt;/a&gt;&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%2F7y1x5eu8jk4r61ywfl5k.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%2F7y1x5eu8jk4r61ywfl5k.png" width="800" height="427"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://adonai-technologies.github.io/RoboRescue/" rel="noopener noreferrer"&gt;Click This Link to Play&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Alibaba Cloud Services Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Function Compute (FC)&lt;/strong&gt;&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%2F8yyl032u3euv8gm5u5mg.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%2F8yyl032u3euv8gm5u5mg.png" width="800" height="387"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Why we chose it&lt;/strong&gt;: We needed a lightweight backend to collect and sync player progress (level, time, moves) from the client side without setting up a full backend server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: We created a simple Function Compute endpoint that receives a POST request with gameplay data and stores it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works in the game&lt;/strong&gt;: After each level is completed, a fetch() POST request sends the player's current progress to our Function Compute endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experience&lt;/strong&gt;: The deployment was fast and straightforward. Function Compute was ideal for serverless handling of progress data. The main challenge was setting up proper CORS headers and endpoint permissions, but Alibaba’s documentation helped resolve that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object Storage Service (OSS)&lt;/strong&gt;&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%2Fgfh1ayllrbazfupjcnsc.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%2Fgfh1ayllrbazfupjcnsc.png" width="800" height="343"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Why we chose it&lt;/strong&gt;: OSS was used to host static assets like the robot image and optionally level configuration JSON files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Game assets such as robot.png are hosted on OSS and loaded directly into the game using their public URLs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works in the game&lt;/strong&gt;: The robot image is retrieved from OSS at runtime and rendered on the game board. This makes updating assets easier without needing to redeploy the entire app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experience&lt;/strong&gt;: Very smooth experience. We appreciated the high availability and CDN-backed delivery which ensured fast loading, even on mobile devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Game Development Highlights
&lt;/h2&gt;

&lt;p&gt;One aspect I'm particularly proud of is the level selection system with cloud progress saving using Alibaba Cloud. Players can resume from where they left off, thanks to local storage backed by Function Compute. I also enjoyed designing the robot-themed UI and making sure the game feels fun and intuitive, even on mobile. Adding movement commands, rotation, and obstacles gave it a real puzzle challenge vibe. Seeing it all come together with Alibaba Cloud services made the process both fun and educational.&lt;/p&gt;

</description>
      <category>alibabachallenge</category>
      <category>devchallenge</category>
      <category>gamedev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Github Repository Manager with Pulumi</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Sat, 05 Apr 2025 21:28:33 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/github-repository-manager-with-pulumi-4mmb</link>
      <guid>https://dev.to/adonaitechnologies/github-repository-manager-with-pulumi-4mmb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/pulumi"&gt;Pulumi Deploy and Document Challenge&lt;/a&gt;: Get Creative with Pulumi and GitHub&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;🧾 &lt;strong&gt;Overview of the Project&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Github Repository Manager&lt;/strong&gt; is a simple tool that helps you create a GitHub repository and connect it to a webhook using Pulumi.&lt;br&gt;
&lt;strong&gt;This means you can tell GitHub&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;“Hey, when someone opens an issue, send me a message!”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s like setting up an alarm that rings when someone knocks on your GitHub project. 🔔&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We use code (&lt;strong&gt;Pulumi&lt;/strong&gt;) instead of clicking around. It saves time and feels like magic!&lt;/p&gt;

&lt;p&gt;📺 Live Demo Video&lt;br&gt;
 &lt;a href="https://youtu.be/BDALAy-1aug" rel="noopener noreferrer"&gt;👉 Watch the demo here:&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/Github-Repository-Manager-with-Pulumi.git" rel="noopener noreferrer"&gt;Github Repo Link with a through readme anyone can read and understand&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Started with a Plan&lt;/strong&gt; 📝
I began by reading the Pulumi + GitHub challenge rules. My idea was simple:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;"Let’s make an app that creates a GitHub repo and connects a webhook to it using Pulumi."&lt;/p&gt;

&lt;p&gt;This app would let GitHub send messages (webhooks) whenever something happens — like someone opening an issue.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Building with Pulumi&lt;/strong&gt; ⚙️
I used the &lt;strong&gt;Pulumi GitHub Provider&lt;/strong&gt; and the &lt;strong&gt;Pulumi Automation API&lt;/strong&gt; to write code that:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ Creates a new GitHub repository&lt;/p&gt;

&lt;p&gt;✅ Adds a webhook to the repo&lt;/p&gt;

&lt;p&gt;✅ Sends event data (like when an issue is created) to a webhook site&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%2Fxmfjxe7vr6hxh6ls4200.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%2Fxmfjxe7vr6hxh6ls4200.png" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.** Challenges I Faced** 🚧&lt;br&gt;
Wrong Method Error: I tried using a function (getRepos) that didn’t exist in Pulumi — oops!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook Confusion&lt;/strong&gt;: At first, I didn’t know where to get a webhook URL. Later, I found Webhook.site, which made it easy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Errors&lt;/strong&gt;: I saw lots of red underlines in my code editor. I fixed them by reading Pulumi docs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;*&lt;em&gt;How I Fixed Things *&lt;/em&gt;🛠
I checked the Pulumi docs to find the correct resources and methods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I asked for help and used trial-and-error to understand how webhooks work&lt;/p&gt;

&lt;p&gt;I kept my code super simple so I could learn as I go&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What I Learned&lt;/strong&gt; 💡
How to use Pulumi to create GitHub repositories with code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How webhooks work and how they send data&lt;/p&gt;

&lt;p&gt;That reading error messages and asking questions is part of coding — and that’s okay!&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%2F04z6sv7euh9bownoo01s.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%2F04z6sv7euh9bownoo01s.png" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pulumi with GitHub
&lt;/h2&gt;

&lt;p&gt;🤖 &lt;strong&gt;How I Used Pulumi&lt;/strong&gt;&lt;br&gt;
I used Pulumi to write code that:&lt;/p&gt;

&lt;p&gt;Creates a GitHub repository&lt;/p&gt;

&lt;p&gt;Adds a webhook to it&lt;/p&gt;

&lt;p&gt;Runs everything with just one command: &lt;strong&gt;pulumi up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🎯 &lt;strong&gt;Why Pulumi Was Helpful&lt;/strong&gt;&lt;br&gt;
I didn’t have to click around in GitHub — everything was automated&lt;br&gt;
It saved time and helped me learn Infrastructure as Code&lt;/p&gt;

&lt;p&gt;I didnt use pulumi ai in this project&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>pulumichallenge</category>
      <category>github</category>
      <category>api</category>
    </item>
    <item>
      <title>Pulumi ESC Secrets &amp; Configuration Manager</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Thu, 03 Apr 2025 20:17:26 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/pulumi-esc-secrets-configuration-manager-1f2i</link>
      <guid>https://dev.to/adonaitechnologies/pulumi-esc-secrets-configuration-manager-1f2i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/pulumi"&gt;Pulumi Deploy and Document Challenge&lt;/a&gt;: Shhh, It's a Secret!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pulumi ESC Secrets &amp;amp; Configuration Manager&lt;/strong&gt; is a CLI-based tool built with Node.js that enables users to securely manage secrets and configurations using &lt;strong&gt;Pulumi ESC&lt;/strong&gt;. This tool allows users to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;List environments within a **Pulumi&lt;/strong&gt; project**&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create new environments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Store, retrieve, update, and delete secrets securely&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View and tag environment revisions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By leveraging the &lt;strong&gt;Pulumi ESC SDK&lt;/strong&gt;, this project ensures secure handling of sensitive data while providing a streamlined approach to configuration management. It is designed to be simple, efficient, and easy to use for developers managing infrastructure secrets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Demo Link
&lt;/h2&gt;

&lt;p&gt;You can access the full source code and documentation in the GitHub repository. The project is designed as a CLI tool to securely manage secrets and configurations using Pulumi ESC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/Pulumi-ESC-Secret-Management-CLI.git" rel="noopener noreferrer"&gt;Repo Link&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.pulumi.com/docs/esc/development/languages-sdks/javascript/" rel="noopener noreferrer"&gt;Pulumi ESC: TypeScript/JavaScript SDK installation link &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&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%2Fud9y8qh3iy217z0ehod8.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%2Fud9y8qh3iy217z0ehod8.png" width="800" height="277"&gt;&lt;/a&gt;&lt;br&gt;
I set up a Node.js project using the &lt;strong&gt;@pulumi/esc-sdk&lt;/strong&gt; to interact with Pulumi ESC for managing secrets and configurations. The CLI tool allows users to list environments, create environments, and manage secrets efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges &amp;amp; Solutions&lt;/strong&gt;&lt;br&gt;
Understanding Pulumi ESC SDK – I overcame this by reading the documentation and testing API calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Securely Managing Secrets&lt;/strong&gt; – Used Pulumi ESC’s encryption features to ensure security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improving CLI Usability&lt;/strong&gt; – Designed a structured menu for better user interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Learnings&lt;/strong&gt;&lt;br&gt;
I gained a deeper understanding of Pulumi ESC, secure configuration management, and best practices for building CLI tools in Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pulumi ESC
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How Pulumi Was Used &amp;amp; Its Benefits&lt;/strong&gt;&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%2F43edrp6nmt9h0ov2e3xu.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%2F43edrp6nmt9h0ov2e3xu.png" width="800" height="150"&gt;&lt;/a&gt;&lt;br&gt;
I used Pulumi ESC to securely manage secrets and configurations within environments. The &lt;strong&gt;Pulumi ESC SDK&lt;/strong&gt; allowed me to:&lt;/p&gt;

&lt;p&gt;List and create environments dynamically.&lt;/p&gt;

&lt;p&gt;Store, retrieve, update, and delete secrets securely using Pulumi’s built-in encryption.&lt;/p&gt;

&lt;p&gt;Track environment revisions and apply versioning for better configuration management.&lt;/p&gt;

&lt;p&gt;Why Pulumi Was Beneficial&lt;br&gt;
*&lt;em&gt;Security *&lt;/em&gt;– Pulumi ESC ensures secrets are encrypted and stored securely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt; – Managing multiple environments and configurations is straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt; – The SDK provides a clean API, making it easy to integrate with Node.js.&lt;/p&gt;

&lt;p&gt;I did not use Pulumi Copilot in this project.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>pulumichallenge</category>
      <category>webdev</category>
      <category>cloud</category>
    </item>
    <item>
      <title>GitHub Metrics Dashboard (Pulumi &amp; Grafana)</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Mon, 31 Mar 2025 11:44:50 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/github-metrics-dashboard-pulumi-grafana-3j0e</link>
      <guid>https://dev.to/adonaitechnologies/github-metrics-dashboard-pulumi-grafana-3j0e</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/pulumi"&gt;Pulumi Deploy and Document Challenge&lt;/a&gt;: Get Creative with Pulumi and GitHub&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;This project is a &lt;strong&gt;GitHub Metrics Dashboard&lt;/strong&gt;, built for the &lt;strong&gt;Get Creative with Pulumi and GitHub Challenge&lt;/strong&gt;. It automates GitHub analytics visualization using &lt;strong&gt;Pulumi&lt;/strong&gt;, &lt;strong&gt;GitHub Webhooks&lt;/strong&gt;, and &lt;strong&gt;Grafana&lt;/strong&gt;. The system collects GitHub repository events, processes them, and displays them in a Grafana dashboard for real-time insights.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Demo Link
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/GitHub-Metrics-Dashboard-Pulumi-Grafana-.git" rel="noopener noreferrer"&gt;https://github.com/Adonai-Technologies/GitHub-Metrics-Dashboard-Pulumi-Grafana-.git&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  GitHub Metrics Dashboard (Pulumi &amp;amp; Grafana)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated GitHub Metrics Collection&lt;/strong&gt; – Uses webhooks to track repository activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pulumi Infrastructure as Code (IaC)&lt;/strong&gt; – Deploys and configures cloud resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grafana Visualization&lt;/strong&gt; – Presents GitHub analytics with rich dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable and Flexible&lt;/strong&gt; – Supports multiple repositories and event types.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pulumi&lt;/strong&gt; (Infrastructure as Code)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Webhooks&lt;/strong&gt; (Event Processing)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js &amp;amp; TypeScript&lt;/strong&gt; (Webhook Receiver)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grafana&lt;/strong&gt; (Metrics Visualization)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt; (Webhook Exposure)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Clone the Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/yourusername/github-metrics-dashboard.git
&lt;span class="nb"&gt;cd &lt;/span&gt;github-metrics-dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2️⃣ Install Dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3️⃣ Set Up Webhook Receiver
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;webhook-receiver
npm &lt;span class="nb"&gt;install
&lt;/span&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, you should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook receiver running on port 4000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4️⃣ Expose Webhook Receiver
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudflared tunnel &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:4000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a public URL, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-tunnel.trycloudflare.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5️⃣ Configure GitHub Webhook
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to your GitHub repository.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Webhooks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add Webhook&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;Payload URL&lt;/strong&gt; to &lt;code&gt;https://your-tunnel.trycloudflare.com/github-webhook&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;application/json&lt;/strong&gt; as the content type.&lt;/li&gt;
&lt;li&gt;Select the events (push, pull request, issues, etc.).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add Webhook&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  6️⃣ Deploy to Cloud with Pulumi
&lt;/h3&gt;

&lt;p&gt;Ensure you have Pulumi installed and configured.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pulumi up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7️⃣ Access Grafana Dashboard
&lt;/h3&gt;

&lt;p&gt;Once Pulumi provisions Grafana, access it via the provided URL and configure data sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contribution
&lt;/h2&gt;

&lt;p&gt;Contributions are welcome! Feel free to submit issues and pull requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;MIT License. See &lt;code&gt;LICENSE&lt;/code&gt; for details.&lt;/p&gt;




&lt;p&gt;🚀 &lt;strong&gt;Built for the Get Creative with Pulumi and GitHub Challenge!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Initial Planning &amp;amp; Conceptualization&lt;/strong&gt;&lt;br&gt;
The project began with brainstorming ideas for the Get Creative with Pulumi and GitHub Challenge. The goal was to automate GitHub analytics visualization using Pulumi and Grafana, making it easier to track repository activity in real-time.&lt;/p&gt;

&lt;p&gt;⚙️ &lt;strong&gt;Setting Up Pulumi &amp;amp; Webhook Receiver&lt;/strong&gt;&lt;br&gt;
Pulumi Setup: We used Pulumi to define cloud resources for deploying the webhook receiver and Grafana dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook Receiver&lt;/strong&gt;: Implemented using Node.js &amp;amp; TypeScript, it listens for GitHub events and processes them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;: Used to expose the webhook receiver to GitHub.&lt;/p&gt;

&lt;p&gt;🚧 Challenges Faced &amp;amp; Solutions&lt;br&gt;
🔒 Webhook Exposure Issues&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Ngrok required a paid plan for custom domains, and localtunnel was unreliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Switched to Cloudflare Tunnel, which provided a stable public URL.&lt;/p&gt;

&lt;p&gt;💾 &lt;strong&gt;Webhook Signature Validati&lt;/strong&gt;on&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: GitHub webhooks require a secret signature for security, which initially caused authentication failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Implemented HMAC verification to validate GitHub signatures before processing events.&lt;/p&gt;

&lt;p&gt;📊 &lt;strong&gt;Grafana Deployment &amp;amp; Data Ingestion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Configuring Grafana to pull data from the webhook receiver was challenging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Used a time-series database (e.g., Prometheus) to store webhook data and connected it to Grafana.&lt;/p&gt;

&lt;p&gt;🎯 &lt;strong&gt;What We Learned&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Infrastructure as Code (IaC) with Pulumi&lt;/strong&gt; – Automating infrastructure deployment made setup reproducible and scalable.&lt;br&gt;
✅ &lt;strong&gt;GitHub Webhook Security&lt;/strong&gt; – Implementing proper authentication for webhooks is critical.&lt;br&gt;
✅ &lt;strong&gt;Grafana Dashboarding&lt;/strong&gt; – Visualizing GitHub repository activity in real-time provides valuable insights.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pulumi with GitHub
&lt;/h2&gt;

&lt;p&gt;Pulumi played a crucial role in automating infrastructure deployment for this project. We used Pulumi's TypeScript SDK to define and provision resources dynamically, making the setup more reproducible and scalable.&lt;/p&gt;

&lt;p&gt;🔹 &lt;strong&gt;Key Pulumi Implementations&lt;/strong&gt;:&lt;br&gt;
&lt;strong&gt;Provisioning a Webhook Receiver&lt;/strong&gt; – Pulumi was used to deploy a cloud-based webhook receiver to process GitHub events.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Deploying Grafana *&lt;/em&gt;– Pulumi automated the setup of a Grafana instance for visualizing GitHub metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring Cloud Resources&lt;/strong&gt; – Instead of manually managing infrastructure, Pulumi managed hosting, networking, and security configurations as code.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Why Pulumi&lt;/strong&gt;?&lt;br&gt;
✅ &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; – Allowed us to declaratively define infrastructure, reducing manual errors.&lt;br&gt;
✅ &lt;strong&gt;Automated Deployment&lt;/strong&gt; – One command (pulumi up) deploys the entire system.&lt;br&gt;
✅ &lt;strong&gt;Multi-Cloud &amp;amp; Flexible&lt;/strong&gt; – Pulumi supports various cloud providers, making future expansions easier.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>pulumichallenge</category>
      <category>github</category>
      <category>api</category>
    </item>
    <item>
      <title>GitHub Repository Blueprint Generator with Pulumi</title>
      <dc:creator>Akua Konadu</dc:creator>
      <pubDate>Sat, 29 Mar 2025 14:34:39 +0000</pubDate>
      <link>https://dev.to/adonaitechnologies/github-repository-blueprint-generator-with-pulumi-5183</link>
      <guid>https://dev.to/adonaitechnologies/github-repository-blueprint-generator-with-pulumi-5183</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/pulumi"&gt;Pulumi Deploy and Document Challenge&lt;/a&gt;: Get Creative with Pulumi and GitHub&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;My project, Repo Blueprint CLI, is a command-line tool that automates the creation of GitHub repositories using predefined templates. It leverages Pulumi to provision repositories programmatically, making it easier for developers to set up new projects with consistent structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Automated GitHub Repository Creation&lt;/strong&gt; – Uses Pulumi to create repositories dynamically.&lt;br&gt;
✅ &lt;strong&gt;Project Templates&lt;/strong&gt; – Supports multiple templates like Node.js and Express.js for quick project setup.&lt;br&gt;
✅ &lt;strong&gt;Pre-configured Files&lt;/strong&gt; – Initializes repositories with essential files like index.js, package.json, and .gitignore.&lt;br&gt;
✅ &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; – Manages GitHub resources programmatically.&lt;/p&gt;

&lt;p&gt;With Repo Blueprint CLI, developers can streamline the process of setting up new repositories, reducing manual work and ensuring best practices. 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Demo Link
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/pulumi-github-cli" rel="noopener noreferrer"&gt;Repo Blueprint CLI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Adonai-Technologies/pulumi-github-cli.git" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project Development Process&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial Planning &amp;amp; Setup&lt;/strong&gt;
The project started with the goal of automating GitHub repository creation using a CLI tool built with Pulumi. The key steps involved were:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Setting up the project structure with Node.js and Pulumi.&lt;/p&gt;

&lt;p&gt;Configuring GitHub authentication via a personal access token.&lt;/p&gt;

&lt;p&gt;Defining project templates (e.g., Node.js, Express.js) for repository initialization.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Implementation&lt;/strong&gt;
Developed a CLI command (create.js) to automate repository creation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Used Pulumi's GitHub provider to provision repositories programmatically.&lt;/p&gt;

&lt;p&gt;Implemented template handling to initialize repositories with relevant files.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Challenges &amp;amp; How They Were Overcome&lt;/strong&gt;
&lt;strong&gt;a)&lt;/strong&gt; Pulumi Configuration Issues
&lt;strong&gt;Challenge&lt;/strong&gt;: Encountered errors related to Pulumi.yaml configuration and stack outputs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Verified stack settings, ensured github:token was correctly set with pulumi config set, and reviewed Pulumi's documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b)&lt;/strong&gt; Missing Dependencies&lt;br&gt;
&lt;strong&gt;Challenge&lt;/strong&gt;: Errors like "Cannot find module '@pulumi/github'" and "Cannot find module 'dotenv'".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Installed missing dependencies using npm install and updated the package.json to include all required modules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c)&lt;/strong&gt; &lt;strong&gt;Pulumi Output Handling&lt;/strong&gt;&lt;br&gt;
Challenge: Error messages stating "Calling [toString] on an [Output] is not supported."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Used apply() or pulumi.interpolate instead of .toString() when handling Pulumi outputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;d)&lt;/strong&gt; Repository Push Blocked (Secrets Detected)&lt;br&gt;
Challenge: GitHub rejected pushes due to detected secrets in .env files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Removed sensitive data from commits.&lt;/p&gt;

&lt;p&gt;Updated .gitignore to exclude .env files.&lt;/p&gt;

&lt;p&gt;Used git rebase -i HEAD~X to remove commits containing secrets.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Key Learnings&lt;/strong&gt;
Pulumi Best Practices: Learned how to properly configure and use Pulumi’s GitHub provider.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;GitHub Security Rules&lt;/strong&gt;: Understood GitHub's secret scanning and how to prevent push protection errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modular Code Design&lt;/strong&gt;: Improved handling of dynamic template creation using JavaScript functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging &amp;amp; Dependency Management&lt;/strong&gt;: Learned how to efficiently debug module resolution errors and manage dependencies in Node.js projects.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Next Steps&lt;/strong&gt;
Expand the CLI to support more templates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Improve error handling and user feedback.&lt;/p&gt;

&lt;p&gt;Automate repository setup with initial commits and CI/CD integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pulumi with GitHub
&lt;/h2&gt;

&lt;p&gt;Pulumi was the core infrastructure-as-code (IaC) tool used to automate GitHub repository creation. Instead of manually setting up repositories, Pulumi allowed us to define repositories as code, ensuring consistency, repeatability, and automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Details&lt;/strong&gt;&lt;br&gt;
GitHub Provider: We leveraged Pulumi's GitHub provider to programmatically create repositories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated Setup&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Created repositories with predefined templates (e.g., Node.js, Express.js).&lt;/p&gt;

&lt;p&gt;Configured repository settings such as visibility and default branches.&lt;/p&gt;

&lt;p&gt;Added template files like index.js, package.json, and .gitignore.&lt;/p&gt;

&lt;p&gt;Secrets Management: Used pulumi config set github:token --secret to securely store GitHub credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Using Pulumi&lt;/strong&gt;&lt;br&gt;
✅ Infrastructure as Code (IaC): Defined repositories in a structured, version-controlled manner.&lt;br&gt;
✅ Automation: Eliminated manual GitHub setup, reducing errors and improving efficiency.&lt;br&gt;
✅ Security: Handled sensitive credentials securely using Pulumi’s built-in secret management.&lt;br&gt;
✅ Scalability: Made it easy to create multiple repositories with consistent settings.&lt;/p&gt;

&lt;p&gt;Pulumi Copilot Usage &amp;amp; Key Prompts&lt;br&gt;
Pulumi Copilot was used to generate configurations and troubleshoot issues. Some key prompts included:&lt;br&gt;
"&lt;strong&gt;How do I create a GitHub repository using Pulumi&lt;/strong&gt;?"&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%2F243hzbjbbodc0obp9vbx.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%2F243hzbjbbodc0obp9vbx.png" width="800" height="300"&gt;&lt;/a&gt;&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%2Fa7e3nw05lo293buoubs5.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%2Fa7e3nw05lo293buoubs5.png" width="800" height="470"&gt;&lt;/a&gt;&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%2F9iwe7gg8sdm3381jw6b0.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%2F9iwe7gg8sdm3381jw6b0.png" width="800" height="345"&gt;&lt;/a&gt;&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%2Ftub2lw5gcxql5czmjzlu.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%2Ftub2lw5gcxql5czmjzlu.png" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"&lt;strong&gt;How do I securely store GitHub tokens in Pulumi&lt;/strong&gt;?"&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%2F6dh1utfqqtx0deor1jgm.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%2F6dh1utfqqtx0deor1jgm.png" width="800" height="320"&gt;&lt;/a&gt;&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%2Fppa8utxruf7ubkhz2akl.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%2Fppa8utxruf7ubkhz2akl.png" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"&lt;strong&gt;How do I apply Pulumi Outputs correctly to retrieve repository URLs?&lt;/strong&gt;"&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%2Fbgwnpfd1t9go9mrhgcvb.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%2Fbgwnpfd1t9go9mrhgcvb.png" width="800" height="245"&gt;&lt;/a&gt;&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%2Fb0uqy01jbqui6gos8w4s.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%2Fb0uqy01jbqui6gos8w4s.png" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"&lt;strong&gt;How can I initialize a repository with template files using Pulumi&lt;/strong&gt;?"&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%2Fjtakfjnnlqmdtltcsqpx.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%2Fjtakfjnnlqmdtltcsqpx.png" width="800" height="307"&gt;&lt;/a&gt;&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%2Fo7xsgs0fbbxtr4mo1q0y.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%2Fo7xsgs0fbbxtr4mo1q0y.png" alt=" " width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Challenges &amp;amp; Solutions&lt;br&gt;
Issue: "Calling [toString] on an [Output] is not supported."&lt;/p&gt;

&lt;p&gt;Fix: Used apply() and pulumi.interpolate for handling outputs properly.&lt;/p&gt;

&lt;p&gt;Issue: "Push declined due to repository rule violations (secrets detected).”&lt;/p&gt;

&lt;p&gt;Fix: Removed secrets from committed files and used .gitignore to prevent future issues.&lt;/p&gt;

&lt;p&gt;Future Enhancements&lt;br&gt;
Automate repository initialization with default commits.&lt;/p&gt;

&lt;p&gt;Integrate CI/CD workflows using Pulumi.&lt;/p&gt;

&lt;p&gt;Extend support for more project templates.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>pulumichallenge</category>
      <category>github</category>
      <category>api</category>
    </item>
  </channel>
</rss>
