Webblocx: Building & Deploying Static Sites with AI and Pulumi Automation

This is a submission for the Pulumi Deploy and Document Challenge: Fast Static Website Deployment What I Built I built an AI-Powered Static Website Builder designed to rapidly generate, customize, and deploy simple websites directly to the cloud. Here's a breakdown of what it does: AI Generation: 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. Multi-Modal Editing: Users can refine the AI-generated site in multiple ways: Visual Editor: A GrapeJS instance allows drag-and-drop editing and visual style adjustments. Code Editor: A CodeMirror instance displays the underlying HTML (including JS) for direct code modifications. AI Editing: 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. Editor Syncing: 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. Local Project Management: 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. Preview: Offers both an in-page modal preview and the ability to open the current state in a new browser tab. Pulumi-Powered Deployment: 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. Cloud Cleanup: Users can destroy the deployed Azure resources for a project directly from the UI. The goal is to bridge the gap between AI content generation and actual deployment, using Pulumi's programmatic capabilities for seamless infrastructure provisioning. Live Demo Link Currently, a live demo is not available, but you can run it locally following the setup instructions in the repository. This are links to already deploy websites created with webblocx. https://siteproja6a4d085sa.z6.web.core.windows.net/ https://siteprojac1f89ebsa.z6.web.core.windows.net/ https://siteproj70df8ec4sa.z6.web.core.windows.net/ Github Project Repo The full source code and setup instructions are available on GitHub: https://github.com/Mahmudqosim/webblocx My Journey 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. Foundation: I started with a standard Node.js/Express backend and Pug for templating the builder's UI. Editors: 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 -> CodeMirror automatic sync and a manual Code -> Visual sync button to avoid performance issues and state resets with editor.setComponents(). Detecting changes reliably in GrapeJS required switching from change:canvas to the more general update event. AI Integration: I chose the Google Gemini API. Crafting effective prompts was key – instructing it to use only Tailwind, generate full HTML documents, include inline JS and CDN links when appropriate, and respond only with code took some iteration. Robustly cleaning the AI's response (removing backticks, potential preamble text) was essential. Persistence: A stateless editor isn't very useful. I added local project management using the server's filesystem. Each project gets a directory (projects/proj_xyz), storing its index.html and a project.json for metadata (name, deployment status, Pulumi stack name). This allows users to save work and manage multiple sites. Pulumi Deployment: This was the core IaC part. Instead of generating separate Pulumi project files, I integrated the Pulumi Automation API directly into the Node.js backend. When a user clicks "Deploy", the backend: Identifies the project and its associated stack name (e.g., site-proj_xyz). Calls LocalWorkspace.createOrSelectStack. Defines the necessary Azure resources (ResourceGroup, StorageAccount with static website settings, Blob for the index.html) programmatically within an inline function passed to

Apr 6, 2025 - 16:26
 0
Webblocx: Building & Deploying Static Sites with AI and Pulumi Automation

This is a submission for the Pulumi Deploy and Document Challenge: Fast Static Website Deployment

What I Built

I built an AI-Powered Static Website Builder designed to rapidly generate, customize, and deploy simple websites directly to the cloud.

Here's a breakdown of what it does:

  1. AI Generation: 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.
  2. Multi-Modal Editing: Users can refine the AI-generated site in multiple ways:
    • Visual Editor: A GrapeJS instance allows drag-and-drop editing and visual style adjustments.
    • Code Editor: A CodeMirror instance displays the underlying HTML (including JS) for direct code modifications.
    • AI Editing: 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.
  3. Editor Syncing: 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.
  4. Local Project Management: 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.
  5. Preview: Offers both an in-page modal preview and the ability to open the current state in a new browser tab.
  6. Pulumi-Powered Deployment: 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.
  7. Cloud Cleanup: Users can destroy the deployed Azure resources for a project directly from the UI.

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

Live Demo Link

Currently, a live demo is not available, but you can run it locally following the setup instructions in the repository.

This are links to already deploy websites created with webblocx.

https://siteproja6a4d085sa.z6.web.core.windows.net/

https://siteprojac1f89ebsa.z6.web.core.windows.net/

https://siteproj70df8ec4sa.z6.web.core.windows.net/

Github

Project Repo

The full source code and setup instructions are available on GitHub:
https://github.com/Mahmudqosim/webblocx

My Journey

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.

  1. Foundation: I started with a standard Node.js/Express backend and Pug for templating the builder's UI.
  2. Editors: 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 -> CodeMirror automatic sync and a manual Code -> Visual sync button to avoid performance issues and state resets with editor.setComponents(). Detecting changes reliably in GrapeJS required switching from change:canvas to the more general update event.
  3. AI Integration: I chose the Google Gemini API. Crafting effective prompts was key – instructing it to use only Tailwind, generate full HTML documents, include inline JS and CDN links when appropriate, and respond only with code took some iteration. Robustly cleaning the AI's response (removing backticks, potential preamble text) was essential.
  4. Persistence: A stateless editor isn't very useful. I added local project management using the server's filesystem. Each project gets a directory (projects/proj_xyz), storing its index.html and a project.json for metadata (name, deployment status, Pulumi stack name). This allows users to save work and manage multiple sites.
  5. Pulumi Deployment: This was the core IaC part. Instead of generating separate Pulumi project files, I integrated the Pulumi Automation API directly into the Node.js backend. When a user clicks "Deploy", the backend:
    • Identifies the project and its associated stack name (e.g., site-proj_xyz).
    • Calls LocalWorkspace.createOrSelectStack.
    • Defines the necessary Azure resources (ResourceGroup, StorageAccount with static website settings, Blob for the index.html) programmatically within an inline function passed to the stack. The path to the project's index.html is passed into this function.
    • Runs stack.up() to provision/update the Azure resources.
    • This stack-per-project approach provides excellent isolation.
  6. UX: 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.

Challenges:

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

Learning:
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.

Using Pulumi

Pulumi was central to the deployment workflow, specifically through its Automation API. 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.

How it Works:

  1. Trigger: When a user deploys a project (e.g., proj_abc), the backend API receives the request.
  2. Stack Management: It uses automation.LocalWorkspace.createOrSelectStack() with a unique stack name derived from the project ID (e.g., site-proj_abc). This ensures each deployed website has its own isolated state and lifecycle.
  3. Programmatic Infrastructure Definition: The core logic resides in an inline async function passed to createOrSelectStack. This function uses the @pulumi/azure-native library to define the required Azure resources:
    • azure_native.resources.ResourceGroup
    • azure_native.storage.StorageAccount (configured for static website hosting)
    • azure_native.storage.Blob (to upload the project's index.html using pulumi.asset.FileAsset) This definition is created dynamically based on the specific projectId, stackName, and the path to the project's index.html on the server.
  4. Configuration: Before deploying, the code programmatically sets necessary stack configuration like the Azure region using stack.setConfig('azure-native:location', { value: ... }).
  5. Deployment Execution: stack.up({ ... }) is called to execute the deployment, creating or updating the Azure resources. Pulumi handles the diffing and state management automatically.
  6. Output Retrieval: The generated website URL is retrieved from the stack outputs (upResult.outputs.websiteUrl.value).
  7. Cleanup: The "Destroy Cloud Deployment" feature similarly uses the Automation API, selecting the correct stack (LocalWorkspace.selectStack()) and running stack.destroy().

Why Pulumi was Beneficial:

  • Programmatic Control: The Automation API allowed defining and deploying infrastructure dynamically based on application data (project ID, content path) without leaving the Node.js environment. This seamless integration was key.
  • Real Programming Language: Defining the simple Azure resources using TypeScript within the Node.js backend felt natural and consistent with the rest of the application stack.
  • Isolation via Stacks: 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.
  • State Management: Pulumi reliably handles the state of deployed resources, making updates and destruction straightforward.
  • Automation: Triggering deployments directly via an API call makes the user experience much smoother compared to manual CLI workflows.

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.