Skip to main content

Website Builder

FleetQ ships a full AI website builder. Describe what you want, let an agent generate the site, refine it in a visual editor, and publish it — all from the same platform your agents, workflows, and chatbots live in. Forms post back as Signals, contact flows trigger workflows, and your existing Chatbot can be embedded as a widget.

Scenario: A marketing team types "Landing page for an AI coding assistant with pricing, FAQ, contact form, and a chatbot." FleetQ generates a multi-page site, assigns a theme, and drops the contact form into Signals. The team edits copy visually in the GrapesJS editor, publishes to Vercel, and the whole thing ships in minutes — without writing a line of HTML.

What you can do

AI generation from a prompt

Two-phase generation: an LLM plans the site structure (pages, sections, nav), then generates HTML for each page. Every page is automatically converted to GrapesJS project data so it's editable visually the moment it's created.

Visual GrapesJS editor

Drag-and-drop block editor with style manager, asset library, and device preview. Each page is stored as both rendered HTML and GrapesJS project JSON — no lock-in.

Plugin packages

Extend the builder with Composer packages. First-party packs include website-plugin-core (navbar, hero, pricing, CTA, footer), website-plugin-blog, website-plugin-forms, website-plugin-chatbot, and website-plugin-ecommerce (Stripe/Paddle checkout).

Publishing drivers

Export a site as a ZIP (static HTML + assets) for manual hosting, or deploy directly to Vercel via an API token. Each publish creates an immutable revision you can roll back.

Architecture

Four models form the core of the Website domain. Every record is team-scoped and soft-deletable.

Model What it stores
Website Name, slug, theme, status (draft/published/archived), publish driver config, content_version for cache invalidation.
WebsitePage Title, slug, rendered HTML, GrapesJS project JSON, SEO metadata, order, publish status.
WebsiteAsset Uploaded images, fonts, and files. Served from the assets tab in the editor.
WebsiteDeployment One row per publish. Tracks the driver (zip/vercel), target URL, status, deploy log, and timestamps — your rollback history lives here.

AI generation flow

GenerateWebsiteFromPromptAction runs a two-phase pipeline:

  1. Plan — one LLM call parses the prompt into a site plan: { name, pages[], each page: { title, slug, type, sections[] } }.
  2. Generate — one LLM call per page produces the HTML body. Each output is passed through HtmlSanitizer::purify() (HTMLPurifier) before storage.
  3. Convert — each HTML body is run through GrapesJsExporter::htmlToProjectData() so the page is immediately editable in the visual builder.
  4. PersistCreateWebsiteAction + CreateWebsitePageAction create the rows, auto-wire the navbar, and return the Website.
Generate via API
// POST /api/v1/websites/generate
{
  "prompt": "Landing page for an AI coding assistant: hero, features, pricing, FAQ, contact form",
  "theme": "minimal-dark"
}

Dynamic content widgets

Pages can include server-rendered placeholders that are replaced at publish time (and cached in Redis). These are useful when you want a page to stay in sync with your blog or sitemap without re-publishing every time content changes.

Placeholder Behaviour
<!-- fleetq:recent-posts --> Injects the N most recent blog posts for the site.
<!-- fleetq:page-list --> Injects a list of all published pages (auto-nav).

Widget output is cached in Redis keyed by website_id + content_version. Updating a page bumps the version and invalidates the cache. Hit/miss metrics are recorded for observability.

When the navbar is auto-synced from the page list, any renamed or reordered pages are reflected on every published page without manual edits. A broken-link rewriter also updates stale internal <a href>s when a page slug changes.

Publishing drivers

Driver How it works
zip Renders every published page, collects assets, and returns a signed download URL for a ZIP file containing static HTML. Drop the archive into any static host (Cloudflare Pages, Netlify drop, Nginx, S3).
vercel Uses a team-scoped Vercel API token (stored as a Credential) to deploy the ZIP as a new Vercel deployment. Custom domain, preview URLs, and rollback are handled by Vercel natively.
Publish via API
curl -X POST https://fleetq.169.58.89.204.sslip.io/api/v1/websites/WEBSITE_ID/publish \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"driver": "vercel"}'

Forms → Signals

Contact forms and newsletter sign-ups posted from a FleetQ-hosted site land at a stable public endpoint:

text
POST /api/public/sites/{slug}/forms/{formId}

The formId is validated against the saved page graph (IDOR guard), payloads pass through a honeypot + rate-limiter, and the resulting submission is ingested as a Signal. Add a Trigger Rule on the binding to route form submissions into a workflow or experiment automatically.

MCP tools

The Website domain ships 17 granular MCP tools — available on /mcp/full and via stdio. The FleetQ assistant can call every one of them on your behalf.

Tool Purpose
website_listList all websites for the team.
website_getRetrieve a single website with metadata.
website_createCreate a new empty website.
website_updateUpdate name, slug, theme, or publish driver config.
website_deleteSoft-delete a website.
website_generateAI-generate a full multi-page site from a plain-text prompt.
website_deployPublish the current version via the configured driver (zip or vercel).
website_unpublishTear down the live deployment.
website_exportReturn a signed ZIP download URL without deploying.
website_analyticsTraffic, form submission, and widget cache hit/miss metrics.
website_deployment_listHistory of deploys (driver, status, URL, timestamps) for rollback.
website_page_listList pages of a website.
website_page_getRetrieve a single page.
website_page_createCreate a new page with HTML body + GrapesJS JSON.
website_page_updateUpdate page content or SEO metadata.
website_page_publishPublish an individual page.
website_page_unpublishHide an individual page from the live site.
The assistant understands the dynamic content widget vocabulary. Ask it to "add a recent-posts block to the home page" and it will drop the correct HTML comment into the page for you.

API endpoints

All endpoints are under /api/v1/websites and require a Sanctum bearer token. Full OpenAPI 3.1 schema at /docs/api.

Method Path Purpose
GET /api/v1/websites List all websites (cursor-paginated).
POST /api/v1/websites Create a new website manually.
POST /api/v1/websites/generate AI-generate a website from a prompt.
GET /api/v1/websites/{id} Retrieve a website with its pages.
PUT /api/v1/websites/{id} Update a website (name, slug, theme, status).
DELETE /api/v1/websites/{id} Soft-delete a website.
POST /api/v1/websites/{id}/publish Publish via selected driver (zip / vercel).
POST /api/v1/websites/{id}/unpublish Tear down the published copy.
GET /api/v1/websites/{id}/pages List pages for a website.
POST /api/v1/websites/{id}/pages Create a page (HTML body + GrapesJS JSON).
PUT /api/v1/websites/{id}/pages/{pageId} Update a page.
POST /api/v1/websites/{id}/pages/{pageId}/publish Publish an individual page.
POST /api/v1/websites/{id}/assets Upload an asset.
GET /api/v1/websites/{id}/export Returns a signed ZIP download URL.
Generated HTML is always sanitised with HTMLPurifier before storage. Do not bypass HtmlSanitizer::purify() when writing custom page content through the API — inline JavaScript and dangerous attributes will be stripped on save.