<?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>Forem: Qosim Mahmud Folaranmi</title>
    <description>The latest articles on Forem by Qosim Mahmud Folaranmi (@mahmudqosim).</description>
    <link>https://forem.com/mahmudqosim</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%2F168989%2F45e2a473-9858-4ddc-8fb5-edaedb5e3f2a.jpg</url>
      <title>Forem: Qosim Mahmud Folaranmi</title>
      <link>https://forem.com/mahmudqosim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mahmudqosim"/>
    <language>en</language>
    <item>
      <title>Webblocx: Building &amp; Deploying Static Sites with AI and Pulumi Automation</title>
      <dc:creator>Qosim Mahmud Folaranmi</dc:creator>
      <pubDate>Sun, 06 Apr 2025 14:54:45 +0000</pubDate>
      <link>https://forem.com/mahmudqosim/webblocx-building-deploying-static-sites-with-ai-and-pulumi-automation-5f46</link>
      <guid>https://forem.com/mahmudqosim/webblocx-building-deploying-static-sites-with-ai-and-pulumi-automation-5f46</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;: Fast Static Website Deployment&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-Powered Static Website Builder&lt;/strong&gt; designed to rapidly generate, customize, and deploy simple websites directly to the cloud.&lt;/p&gt;

&lt;p&gt;Here's a breakdown of what it does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;AI Generation:&lt;/strong&gt; Users provide a natural language prompt describing the website they want (e.g., "a portfolio for a photographer", "a landing page for a new app"). The application uses the Google Gemini API to generate the initial HTML structure, styled with Tailwind CSS classes, and can even include basic inline JavaScript (e.g., for animations with GSAP or simple interactions) along with necessary CDN links.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Multi-Modal Editing:&lt;/strong&gt; Users can refine the AI-generated site in multiple ways:

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Visual Editor:&lt;/strong&gt; A GrapeJS instance allows drag-and-drop editing and visual style adjustments.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Code Editor:&lt;/strong&gt; A CodeMirror instance displays the underlying HTML (including JS) for direct code modifications.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;AI Editing:&lt;/strong&gt; Users can provide further prompts to the AI assistant (e.g., "change the hero background to blue", "add a contact form section", "make the title bounce using GSAP") to iteratively modify the current code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Editor Syncing:&lt;/strong&gt; Provides toggling between Visual and Code views, with a manual sync option to update the visual editor from code changes. Changes in the visual editor automatically update the code view.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Local Project Management:&lt;/strong&gt; Users can create multiple named projects. The HTML content for each project is saved locally on the server's filesystem, allowing users to load, save, and manage different website drafts.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Preview:&lt;/strong&gt; Offers both an in-page modal preview and the ability to open the current state in a new browser tab.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Pulumi-Powered Deployment:&lt;/strong&gt; With a single click, users can deploy their selected project directly to an Azure Static Website (hosted on Azure Blob Storage). Each project deployment gets its own isolated Azure resources managed by a unique Pulumi stack.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Cloud Cleanup:&lt;/strong&gt; Users can destroy the deployed Azure resources for a project directly from the UI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is to bridge the gap between AI content generation and actual deployment, using Pulumi's programmatic capabilities for seamless infrastructure provisioning.&lt;/p&gt;

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

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

&lt;p&gt;&lt;em&gt;Currently, a live demo is not available, but you can run it locally following the setup instructions in the repository.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This are links to already deploy websites created with webblocx.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://siteproja6a4d085sa.z6.web.core.windows.net/" rel="noopener noreferrer"&gt;https://siteproja6a4d085sa.z6.web.core.windows.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://siteprojac1f89ebsa.z6.web.core.windows.net/" rel="noopener noreferrer"&gt;https://siteprojac1f89ebsa.z6.web.core.windows.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://siteproj70df8ec4sa.z6.web.core.windows.net/" rel="noopener noreferrer"&gt;https://siteproj70df8ec4sa.z6.web.core.windows.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Mahmudqosim/webblocx" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The full source code and setup instructions are available on GitHub:&lt;br&gt;
&lt;a href="https://github.com/Mahmudqosim/webblocx" rel="noopener noreferrer"&gt;https://github.com/Mahmudqosim/webblocx&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;My initial idea was to explore how AI generation could be tightly coupled with Infrastructure as Code (IaC) for extremely fast prototyping and deployment. Static websites are a great starting point. I wanted a user to describe a site, see it generated, tweak it easily, and deploy it without touching complex cloud consoles or writing separate IaC code.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Foundation:&lt;/strong&gt; I started with a standard Node.js/Express backend and Pug for templating the builder's UI.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Editors:&lt;/strong&gt; Integrating GrapeJS (visual) and CodeMirror (code) was the first major step. Getting them to display correctly and eventually adding a toggle mechanism instead of side-by-side was crucial for usability. Syncing state between them presented challenges – I opted for GrapeJS -&amp;gt; CodeMirror automatic sync and a manual Code -&amp;gt; Visual sync button to avoid performance issues and state resets with &lt;code&gt;editor.setComponents()&lt;/code&gt;. Detecting changes reliably in GrapeJS required switching from &lt;code&gt;change:canvas&lt;/code&gt; to the more general &lt;code&gt;update&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;AI Integration:&lt;/strong&gt; I chose the Google Gemini API. Crafting effective prompts was key – instructing it to use &lt;em&gt;only&lt;/em&gt; Tailwind, generate full HTML documents, include inline JS and CDN links when appropriate, and respond &lt;em&gt;only&lt;/em&gt; with code took some iteration. Robustly cleaning the AI's response (removing backticks, potential preamble text) was essential.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Persistence:&lt;/strong&gt; A stateless editor isn't very useful. I added local project management using the server's filesystem. Each project gets a directory (&lt;code&gt;projects/proj_xyz&lt;/code&gt;), storing its &lt;code&gt;index.html&lt;/code&gt; and a &lt;code&gt;project.json&lt;/code&gt; for metadata (name, deployment status, Pulumi stack name). This allows users to save work and manage multiple sites.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Pulumi Deployment:&lt;/strong&gt; This was the core IaC part. Instead of generating separate Pulumi project files, I integrated the &lt;strong&gt;Pulumi Automation API&lt;/strong&gt; directly into the Node.js backend. When a user clicks "Deploy", the backend:

&lt;ul&gt;
&lt;li&gt;  Identifies the project and its associated stack name (e.g., &lt;code&gt;site-proj_xyz&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Calls &lt;code&gt;LocalWorkspace.createOrSelectStack&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Defines the necessary Azure resources (&lt;code&gt;ResourceGroup&lt;/code&gt;, &lt;code&gt;StorageAccount&lt;/code&gt; with static website settings, &lt;code&gt;Blob&lt;/code&gt; for the &lt;code&gt;index.html&lt;/code&gt;) &lt;em&gt;programmatically within an inline function&lt;/em&gt; passed to the stack. The path to the project's &lt;code&gt;index.html&lt;/code&gt; is passed into this function.&lt;/li&gt;
&lt;li&gt;  Runs &lt;code&gt;stack.up()&lt;/code&gt; to provision/update the Azure resources.&lt;/li&gt;
&lt;li&gt;  This stack-per-project approach provides excellent isolation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;UX:&lt;/strong&gt; Finally, I added modals for creating projects and confirmations for destructive actions (delete, destroy), status indicators, and general layout improvements using Tailwind CSS via the CDN script for simplicity in this version.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Editor Integration:&lt;/strong&gt; Making GrapeJS and CodeMirror coexist and sync effectively.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;AI Output Parsing:&lt;/strong&gt; Handling variations in Gemini's output format.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;State Management:&lt;/strong&gt; Keeping track of the current project, dirty state, and deployment status.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Pulumi Automation API:&lt;/strong&gt; Learning the nuances of driving Pulumi programmatically from within a running application server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Learning:&lt;/strong&gt;&lt;br&gt;
This project was a fantastic dive into the Pulumi Automation API, demonstrating its power for dynamic, application-driven infrastructure. It also reinforced the importance of clear prompting for AI and robust handling of its output, alongside the complexities of integrating sophisticated frontend libraries.&lt;/p&gt;

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

&lt;p&gt;Pulumi was central to the deployment workflow, specifically through its &lt;strong&gt;Automation API&lt;/strong&gt;. Instead of requiring users (or the application) to manage separate Pulumi programs or CLI commands, Pulumi's engine is embedded directly within the Node.js backend service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it Works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Trigger:&lt;/strong&gt; When a user deploys a project (e.g., &lt;code&gt;proj_abc&lt;/code&gt;), the backend API receives the request.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Stack Management:&lt;/strong&gt; It uses &lt;code&gt;automation.LocalWorkspace.createOrSelectStack()&lt;/code&gt; with a unique stack name derived from the project ID (e.g., &lt;code&gt;site-proj_abc&lt;/code&gt;). This ensures each deployed website has its own isolated state and lifecycle.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Programmatic Infrastructure Definition:&lt;/strong&gt; The core logic resides in an inline async function passed to &lt;code&gt;createOrSelectStack&lt;/code&gt;. This function uses the &lt;code&gt;@pulumi/azure-native&lt;/code&gt; library to define the required Azure resources:

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;azure_native.resources.ResourceGroup&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;azure_native.storage.StorageAccount&lt;/code&gt; (configured for static website hosting)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;azure_native.storage.Blob&lt;/code&gt; (to upload the project's &lt;code&gt;index.html&lt;/code&gt; using &lt;code&gt;pulumi.asset.FileAsset&lt;/code&gt;)
This definition is created &lt;em&gt;dynamically&lt;/em&gt; based on the specific &lt;code&gt;projectId&lt;/code&gt;, &lt;code&gt;stackName&lt;/code&gt;, and the path to the project's &lt;code&gt;index.html&lt;/code&gt; on the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Configuration:&lt;/strong&gt; Before deploying, the code programmatically sets necessary stack configuration like the Azure region using &lt;code&gt;stack.setConfig('azure-native:location', { value: ... })&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Deployment Execution:&lt;/strong&gt; &lt;code&gt;stack.up({ ... })&lt;/code&gt; is called to execute the deployment, creating or updating the Azure resources. Pulumi handles the diffing and state management automatically.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Output Retrieval:&lt;/strong&gt; The generated website URL is retrieved from the stack outputs (&lt;code&gt;upResult.outputs.websiteUrl.value&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Cleanup:&lt;/strong&gt; The "Destroy Cloud Deployment" feature similarly uses the Automation API, selecting the correct stack (&lt;code&gt;LocalWorkspace.selectStack()&lt;/code&gt;) and running &lt;code&gt;stack.destroy()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why Pulumi was Beneficial:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Programmatic Control:&lt;/strong&gt; The Automation API allowed defining and deploying infrastructure &lt;em&gt;dynamically&lt;/em&gt; based on application data (project ID, content path) without leaving the Node.js environment. This seamless integration was key.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Real Programming Language:&lt;/strong&gt; Defining the simple Azure resources using TypeScript within the Node.js backend felt natural and consistent with the rest of the application stack.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Isolation via Stacks:&lt;/strong&gt; The ability to easily create a unique stack per deployed website is incredibly powerful for managing the lifecycle and state of many independent deployments without interference.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;State Management:&lt;/strong&gt; Pulumi reliably handles the state of deployed resources, making updates and destruction straightforward.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Automation:&lt;/strong&gt; Triggering deployments directly via an API call makes the user experience much smoother compared to manual CLI workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project demonstrates how Pulumi can be more than just a CLI tool – it can be a powerful programmatic engine embedded within applications to manage cloud resources dynamically.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>pulumichallenge</category>
      <category>webdev</category>
      <category>cloud</category>
    </item>
    <item>
      <title>TheNames: Smart Portfolio Website Builder</title>
      <dc:creator>Qosim Mahmud Folaranmi</dc:creator>
      <pubDate>Mon, 24 Mar 2025 06:57:37 +0000</pubDate>
      <link>https://forem.com/mahmudqosim/thenames-smart-portfolio-website-builder-2ene</link>
      <guid>https://forem.com/mahmudqosim/thenames-smart-portfolio-website-builder-2ene</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/kendoreact"&gt;KendoReact Free Components Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;TheNames is a modern portfolio website builder that uses Gemini AI to generate beautiful, customized single-page websites with more robust design capabilities. Users can quickly create and publish professional-looking portfolio websites without design experience, thanks to AI-assisted generation and the intuitive GrapeJS visual editor.&lt;br&gt;
The application combines the power of Next.js for the frontend, and Google's Gemini AI for intelligent website generation. TheNames streamlines the process of creating personal branding websites, then having AI generate a fully functional website that can be further customized using a visual editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Live Demo: &lt;a href="https://thenames-frontend.vercel.app/editor" rel="noopener noreferrer"&gt;https://thenames-frontend.vercel.app/editor&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%2Ffh9lq0e4n5fgpg1qslyo.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%2Ffh9lq0e4n5fgpg1qslyo.png" alt="Image description" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Mahmudqosim/thenames-frontend" rel="noopener noreferrer"&gt;https://github.com/Mahmudqosim/thenames-frontend&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  KendoReact Experience
&lt;/h2&gt;

&lt;p&gt;KendoReact Experience&lt;br&gt;
TheNames leverages an extensive suite of KendoReact components to create a professional, intuitive user interface. These components were critical to achieving a polished, enterprise-grade look and feel while maintaining rapid development speed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KendoReact Buttons - Used throughout the application for all interactive controls, providing consistent styling and behavior for primary actions, secondary actions, and destructive operations.&lt;/li&gt;
&lt;li&gt;KendoReact Layout - Implemented for the overall application structure, including panels, dividers, and responsive layout containers that adapt seamlessly to different screen sizes.&lt;/li&gt;
&lt;li&gt;KendoReact Dialogs - Created modal interactions for website creation, AI content generation, settings configuration, and confirmation of important actions.&lt;/li&gt;
&lt;li&gt;KendoReact Form Components - Utilized the comprehensive suite of input components:&lt;/li&gt;
&lt;li&gt;Inputs for text fields and form controls&lt;/li&gt;
&lt;li&gt;DateInputs for scheduling and date selection&lt;/li&gt;
&lt;li&gt;Dropdowns for selection lists and filtering options&lt;/li&gt;
&lt;li&gt;ListBox for multi-select capabilities&lt;/li&gt;
&lt;li&gt;KendoReact Notifications - Implemented toast notifications for system messages and alerts about site creation, publishing, and updates.&lt;/li&gt;
&lt;li&gt;KendoReact TreeView - Used to display and navigate site structure and content hierarchy in the editor.&lt;/li&gt;
&lt;li&gt;KendoReact ProgressBars - Displayed loading states during AI generation and site publishing processes.&lt;/li&gt;
&lt;li&gt;KendoReact Tooltips - Added contextual help and information throughout the interface to guide users.&lt;/li&gt;
&lt;li&gt;KendoReact Indicators - Implemented loading spinners and status indicators for asynchronous operations.&lt;/li&gt;
&lt;li&gt;KendoReact Animation - Created smooth transitions between UI states and when displaying new content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AIm to Impress
&lt;/h3&gt;

&lt;p&gt;AI-Powered Website Generation - Users can describe their desired website in natural language, including style preferences, content sections, and links. Gemini analyzes this input and generates complete HTML, CSS, and JavaScript code for a responsive, personalized website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delightfully Designed
&lt;/h3&gt;

</description>
      <category>devchallenge</category>
      <category>kendoreactchallenge</category>
      <category>react</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
