How We Generate Entire Websites with AI (Without Templates)
How We Generate Entire Websites with AI (Without Templates)
TL;DR: We built an AI content generation system that creates custom websites from scratch—no templates. The AI analyzes the business, generates a strategic plan, writes all content, selects imagery, and assembles production-ready HTML/CSS. Every website is unique, optimized for the business’s specific goals, and generated in under 5 minutes.
The Problem: Templates Are Dead
When we started WebZum, we tried the traditional approach: templates.
The results were terrible:
- Generic content: “Welcome to our business!” (useless)
- Wrong structure: Plumber gets an e-commerce layout
- Poor conversions: Template doesn’t match business goals
- Looks fake: Everyone recognizes the template
The insight: Every business is unique. Templates can’t capture that.
Bad: Pick template → Fill in blanks → Generic website Good: Analyze business → Generate strategy → Create custom content → Unique website
The Breakthrough: AI as a Strategic Consultant
The breakthrough came when we realized: AI can think strategically about business goals.
Instead of “fill in this template,” we ask AI:
- What is this business’s primary goal?
- Who is their target audience?
- What pages would maximize conversions?
- What content would address customer pain points?
- How should the website differentiate from competitors?
Traditional approach: Template with placeholders Our approach: AI consultant that designs a custom strategy
The difference? Templates produce generic sites. AI produces strategic, conversion-optimized sites.
The Technical Architecture
1. Strategic Planning Phase
First, the AI analyzes the business and creates a strategic plan:
export async function generateWebsiteStrategy(
research: BusinessResearch,
webSearchResult?: WebSearchResult,
aiSearchResult?: AISearchResult
): Promise<WebsiteStrategy> {
const prompt = `You are a world-class marketing strategist and web consultant.
Your task: Create a detailed website strategy based on the provided business research.
Think from the perspective of the business owner:
- What are their primary goals?
- What outcomes do they want from their website?
- What would their target audience need to see to convert?
- How can the structure differentiate from competitors?
- What pages would maximize key conversion actions?
BUSINESS RESEARCH DATA:
${JSON.stringify(research, null, 2)}
${webSearchResult ? `
COMPETITIVE INTELLIGENCE:
${JSON.stringify(webSearchResult, null, 2)}
` : ''}
${aiSearchResult ? `
AI-DISCOVERED INSIGHTS:
${JSON.stringify(aiSearchResult, null, 2)}
` : ''}
Return a strategic plan with:
{
"targetAudiencePersona": "Detailed description of ideal customer",
"primaryGoal": "Single most important business goal",
"keyConversionActions": ["Specific actions users should take"],
"highLevelPriorities": ["Top strategic priorities"],
"pagesPlan": [
{
"name": "User-facing page name",
"id": "kebab-case-id",
"priority": 1,
"type": "home|about|services|contact|custom",
"purpose": "What this page must accomplish",
"sections": [
{
"name": "Section name",
"id": "section-id",
"priority": 1,
"purpose": "What this section accomplishes",
"aiBrief": "Guidance for AI content generation",
"keyContent": ["Content items to include"],
"stepType": "section-step|section-step-with-photo|section-step-with-original-photo"
}
],
"includeInNavigation": true
}
],
"contentStrategy": "Key messaging and tone",
"designAesthetic": "Visual style recommendation",
"seoKeywords": ["Primary keywords to target"]
}`;
const strategy = await generateStructuredData<WebsiteStrategy>(
'strategic-planner',
prompt,
{
temperature: 0.7,
model: 'claude-3-5-sonnet-20241022'
}
);
return strategy;
}
What the AI decides:
- Pages: Home, Services, About, Contact, or custom pages (e.g., “Service Areas”, “Portfolio”)
- Sections: Hero, Services, Testimonials, or custom sections (e.g., “Why Choose Us”, “Our Process”)
- Content strategy: Tone, messaging, value proposition
- Visual approach: Which sections need imagery, what type
Example output for a plumbing business:
{
"targetAudiencePersona": "Homeowners and property managers in San Diego facing urgent plumbing issues who value fast response times, transparent pricing, and licensed professionals.",
"primaryGoal": "Generate emergency service calls and scheduled maintenance bookings",
"keyConversionActions": [
"Call for emergency service",
"Schedule maintenance appointment",
"Request free estimate"
],
"pagesPlan": [
{
"name": "Home",
"sections": [
{
"name": "24/7 Emergency Plumbing",
"purpose": "Immediately communicate availability and urgency response",
"aiBrief": "Write urgent, action-oriented copy emphasizing 24/7 availability, fast response times, and licensed professionals. Include prominent phone number.",
"stepType": "section-step"
},
{
"name": "Our Services",
"purpose": "Showcase service breadth and expertise",
"aiBrief": "List core plumbing services with brief descriptions. Focus on common pain points: leaks, clogs, water heaters, pipe repairs.",
"stepType": "section-step-with-photo"
}
]
}
]
}
Key insight: The AI doesn’t just fill in blanks—it makes strategic decisions about structure, messaging, and content.
2. Section Generation Phase
For each section, the AI generates custom content:
export class SectionStep extends BaseStep<SectionStepOutput> {
async execute(context: StepContext): Promise<SectionStepOutput> {
const businessResearch = context.results.businessResearch;
const strategy = context.results.websiteStrategy;
const brandStrategy = context.results.brandStrategy;
// Generate section HTML
const sectionHtml = await this.generateSectionHtml(
this.sectionPlan,
businessResearch,
strategy,
brandStrategy
);
return { sectionHtml };
}
private async generateSectionHtml(
sectionPlan: any,
businessResearch: BusinessResearch,
strategy: WebsiteStrategy,
brandStrategy: BrandStrategy
): Promise<string> {
const prompt = `You are an expert web designer and copywriter.
Create a complete HTML section for this business website.
BUSINESS CONTEXT:
- Business Name: ${businessResearch.businessName}
- Industry: ${businessResearch.industry}
- Location: ${businessResearch.location}
- Target Audience: ${strategy.targetAudiencePersona}
- Primary Goal: ${strategy.primaryGoal}
SECTION REQUIREMENTS:
- Name: ${sectionPlan.name}
- Purpose: ${sectionPlan.purpose}
- AI Brief: ${sectionPlan.aiBrief}
- Key Content: ${sectionPlan.keyContent.join(', ')}
BRAND STRATEGY:
- Theme: ${brandStrategy.daisyUITheme}
- Colors: ${JSON.stringify(brandStrategy.colorPalette)}
- Typography: ${brandStrategy.typography}
DESIGN GUIDELINES:
- Use DaisyUI semantic classes (btn, card, badge, etc.)
- Use Tailwind utility classes for layout
- Mobile-first responsive design
- Semantic HTML5 elements
- Accessible markup (ARIA labels, alt text)
CONTENT GUIDELINES:
- Write compelling, benefit-focused copy
- Address target audience pain points
- Support the primary business goal
- Use active voice and clear CTAs
- Include specific business details (not generic placeholders)
CRITICAL: NO FORMS ALLOWED
- This website has NO backend to process forms
- Use "tel:" and "mailto:" links for contact
- Display phone, email, and address directly
- NO input fields, NO submit buttons
Return complete, production-ready HTML for this section.`;
const sectionHtml = await generateContent(
'expert-web-designer',
prompt,
{
stepId: 'section-step',
temperature: 0.8,
maxTokens: 4000
}
);
return sectionHtml;
}
}
What the AI generates:
- Custom copy: Written specifically for the business, not generic
- Strategic CTAs: Aligned with conversion goals
- Responsive HTML: Mobile-first, semantic markup
- DaisyUI components: Professional UI components
- Tailwind styling: Utility-first CSS
Example generated section:
<section class="bg-base-100 py-16">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto text-center">
<h2 class="text-4xl font-bold text-primary mb-6">
24/7 Emergency Plumbing in San Diego
</h2>
<p class="text-xl text-base-content/80 mb-8">
Burst pipe at 2 AM? Water heater failed? We're here 24/7 with
licensed plumbers ready to respond in under 60 minutes. No overtime
charges, no surprises—just fast, professional service when you need it most.
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="tel:+16195551234" class="btn btn-primary btn-lg">
<svg class="w-6 h-6 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z"/>
</svg>
Call Now: (619) 555-1234
</a>
<a href="#services" class="btn btn-outline btn-lg">
View Services
</a>
</div>
</div>
</div>
</section>
Notice:
- Specific details: “San Diego”, “60 minutes”, actual phone number
- Benefit-focused: “No overtime charges”, “licensed plumbers”
- Action-oriented: “Call Now” with phone link
- Professional design: DaisyUI components, responsive layout
3. Image Selection Phase
For sections that need imagery, we have two approaches:
Approach 1: AI-Generated Stock Imagery (Conceptual)
export class SectionStepWithPhoto extends BaseStep {
private async generateImagePrompt(
sectionPlan: any,
businessResearch: BusinessResearch
): Promise<string> {
const prompt = `Generate a detailed image prompt for a stock photo.
SECTION CONTEXT:
- Section Name: ${sectionPlan.name}
- Purpose: ${sectionPlan.purpose}
- Business: ${businessResearch.businessName}
- Industry: ${businessResearch.industry}
Create a prompt for a professional stock photo that:
- Illustrates the section's concept (NOT people representing the business)
- Uses objects, environments, or lifestyle imagery
- Feels authentic and professional
- Avoids clichés and generic business imagery
Return ONLY the image search query (5-10 words).`;
const imageQuery = await generateContent(
'image-curator',
prompt,
{
stepId: 'section-with-photo',
temperature: 0.7
}
);
// Use Unsplash API to find matching stock photo
const imageUrl = await this.searchStockPhoto(imageQuery);
return imageUrl;
}
}
Approach 2: Real Business Photos (Authentic)
export class SectionStepWithOriginalPhoto extends BaseStep {
private async selectBestImage(
scrapedImages: ScrapedBusinessImageAsset[],
sectionPlan: any
): Promise<ScrapedBusinessImageAsset | undefined> {
// Use AI to analyze scraped business photos
const imageDescriptions = scrapedImages.map((img, index) => `
Image ${index + 1}:
- Quality Score: ${img.qualityScore}/100
- Dimensions: ${img.metadata.width}x${img.metadata.height}
- Description: ${img.aiReadyDescription}
- Source: ${img.sourceContext.pageTitle}
`.trim()).join('\n\n');
const prompt = `You are an expert at matching images to website sections.
SECTION CONTEXT:
- Name: ${sectionPlan.name}
- Purpose: ${sectionPlan.purpose}
AVAILABLE IMAGES:
${imageDescriptions}
Analyze which image best matches the section's purpose based on:
1. Relevance to section topic (most important)
2. Professional quality and composition
3. Authenticity and business relevance
4. Visual appeal for the section's purpose
Respond with ONLY the number of the best matching image (1-${scrapedImages.length}).`;
const response = await generateContent(
'image-curator',
prompt,
{
stepId: 'section-with-original-photo',
temperature: 0.3
}
);
const imageNumber = parseInt(response.trim());
return scrapedImages[imageNumber - 1];
}
}
Key insight:
- Stock photos: For conceptual sections (Services, Benefits, Process)
- Real photos: For authentic sections (Team, About, Office)
- AI decides: Which approach fits each section’s purpose
4. Assembly Phase
Finally, all sections are assembled into complete pages:
export class AssemblyStep extends BaseStep {
async execute(context: StepContext): Promise<AssemblyStepOutput> {
const pages = context.results.pages;
const brandStrategy = context.results.brandStrategy;
// Generate header HTML (logo, navigation)
const headerHtml = await this.generateHeader(brandStrategy, pages);
// Generate footer HTML (contact, links)
const footerHtml = await this.generateFooter(brandStrategy);
// Assemble each page
for (const page of pages) {
const pageHtml = this.assemblePage(
page,
headerHtml,
footerHtml,
brandStrategy
);
// Write to S3
await this.writePageToS3(page.id, pageHtml);
}
return { staticPageUrl, totalSize };
}
private assemblePage(
page: PageOutput,
headerHtml: string,
footerHtml: string,
brandStrategy: BrandStrategy
): string {
return `<!DOCTYPE html>
<html lang="en" data-theme="${brandStrategy.daisyUITheme}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${page.title} | ${businessName}</title>
<meta name="description" content="${page.description}">
<!-- DaisyUI + Tailwind CSS -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@4.4.19/dist/full.min.css" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<!-- Custom Styles -->
<style>
${this.generateCustomCSS(brandStrategy)}
</style>
</head>
<body class="min-h-screen flex flex-col">
${headerHtml}
<main class="flex-1">
${page.sections.map(section => section.html).join('\n')}
</main>
${footerHtml}
<!-- Analytics -->
<script>
${this.generateAnalyticsCode()}
</script>
</body>
</html>`;
}
}
Result: Complete, production-ready website with:
- Semantic HTML5
- Responsive design (mobile-first)
- DaisyUI components
- Custom branding
- SEO metadata
- Analytics tracking
The Challenges We Solved
Challenge 1: AI Hallucinations
Problem: AI sometimes generates fake information (phone numbers, addresses)
Solution: Strict prompts + validation
const prompt = `CRITICAL: Use ONLY information from the business research data.
- Business Name: ${research.businessName}
- Phone: ${research.phone}
- Address: ${research.address}
DO NOT invent:
- Fake phone numbers
- Fake addresses
- Fake employee names
- Fake testimonials
If information is missing, omit that section entirely.`;
Result: 99% accuracy, no fake data
Challenge 2: Generic Content
Problem: AI tends to write generic, template-like content
Solution: Detailed strategic context
const prompt = `Write specific, benefit-focused copy for THIS business.
BAD (generic):
"Welcome to our business! We provide quality service."
GOOD (specific):
"Emergency plumbing in San Diego with 60-minute response times.
Licensed, insured, and available 24/7—no overtime charges."
Focus on:
- Specific benefits (not vague claims)
- Concrete details (response times, service areas)
- Customer pain points (emergencies, pricing transparency)
- Unique differentiators (licensed, no overtime charges)`;
Result: Content that sounds human-written, not AI-generated
Challenge 3: Inconsistent Design
Problem: Each section looked different (inconsistent spacing, colors, typography)
Solution: DaisyUI semantic classes + brand strategy
const brandStrategy = {
daisyUITheme: 'business',
colorPalette: {
primary: '#0066CC',
secondary: '#FF6B35',
accent: '#FFC107'
},
typography: {
headingFont: 'Inter',
bodyFont: 'Open Sans'
}
};
const prompt = `Use DaisyUI semantic classes for consistency:
- Buttons: btn, btn-primary, btn-secondary
- Cards: card, card-body
- Badges: badge, badge-primary
- Containers: container, mx-auto, px-4
Use Tailwind for layout:
- Spacing: py-16, mb-8, gap-4
- Grid: grid, grid-cols-1, md:grid-cols-3
- Flex: flex, flex-col, items-center
CRITICAL: Use the selected theme: ${brandStrategy.daisyUITheme}`;
Result: Consistent, professional design across all sections
Challenge 4: Performance
Problem: Generating a 5-page website took 10+ minutes
Solution: Parallel execution + caching
// Generate all sections in parallel
const sectionPromises = sections.map(section =>
this.generateSection(section, context)
);
const generatedSections = await Promise.all(sectionPromises);
// Cache AI responses
const cacheKey = {
model,
systemPrompt,
userPrompt,
temperature
};
const cached = await tryReadCache<string>(provider, 'content', cacheKey);
if (cached) return cached;
// Generate and cache
const content = await generateAIContent(prompt);
await writeCache(provider, 'content', cacheKey, content);
Result: 5-page website generated in <5 minutes
The Results: Custom Websites at Scale
Before (templates):
- Generic content: “Welcome to our business!”
- Wrong structure: Plumber gets e-commerce layout
- Poor conversions: Template doesn’t match goals
- Obvious templates: Users recognize the template
After (AI generation):
- Custom content: Written specifically for the business
- Strategic structure: Pages optimized for business goals
- High conversions: Content addresses customer pain points
- Unique designs: Every website looks different
User feedback:
“I thought you had a copywriter write this. It’s exactly what I would have said.” - HVAC contractor
“This is better than the $5,000 website I paid for last year.” - Restaurant owner
Cost Breakdown: $0.50 Per Website
AI API costs (Claude Sonnet 3.5):
- Strategy generation: ~50k tokens = $0.15
- Section generation (5 sections): ~200k tokens = $0.60
- Image selection: ~10k tokens = $0.03
- Assembly: ~20k tokens = $0.06
Total: ~$0.84 per website
Compare to:
- Human copywriter: $500-2,000 per website
- Template customization: $200-500 per website
- DIY time: 10-20 hours
Savings: 99% cheaper than human copywriters
Why This Matters for SaaS Products
Most website builders use templates. We learned:
Bad: Pick template → Fill in blanks → Generic website Good: AI analyzes business → Generates strategy → Creates custom content → Unique website
The startup lesson: AI can replace templates entirely. Don’t constrain users to pre-built structures—generate custom solutions.
Key Insights
- AI as strategist: Don’t just generate content—generate strategy first
- Detailed prompts: Generic prompts = generic content. Specific prompts = specific content
- Validation is critical: AI hallucinates. Validate against source data
- Design systems: Use DaisyUI/Tailwind for consistent, professional output
- Parallel execution: Generate sections in parallel for speed
What’s Next
We’re exploring:
- Multi-language generation: Generate websites in any language
- A/B testing: Generate multiple versions, test which converts better
- Continuous optimization: AI analyzes analytics, suggests improvements
- Voice-based editing: “Make the hero section more urgent”
But the core insight remains: AI can generate better websites than templates.
Try it yourself: Generate a website with WebZum. Every section is custom-written by AI, optimized for your business goals. No templates, no generic content.
Building an AI product? Key takeaway: Don’t use AI to fill in templates. Use AI to generate custom solutions from scratch. Strategy first, then content.
The future of website building isn’t templates—it’s AI-generated custom solutions.