Article

GitHub Pages + Jekyll: The $4/Month Marketing Site Stack

How to deploy professional marketing sites for multiple projects using GitHub Pages, Jekyll, and Cloudflare Workers. No WordPress. No hosting bills. Just static sites that work.

Bill

November 30, 2025 · 10 min read

Article Info
10
Minutes
read time
Nov 30
Published
2025
0
Tags
topics
2
Related
articles

WordPress is overkill for most marketing sites. You don’t need a database. You don’t need PHP. You don’t need a $20/month hosting bill per site. You need HTML, CSS, and a way to capture leads.

Here’s the stack I use for all my marketing sites—including this one (vibeengineer.ing) and Joy Cork:

  • GitHub Organization: $4/month for unlimited private repos
  • GitHub Pages: Free static hosting with SSL
  • Jekyll: Free, open-source static site generator
  • Cloudflare Workers: Serverless functions for contact forms
  • Postmark: $15/month for transactional email across all projects
  • Claude Code: AI-assisted design and content writing

Total monthly cost for hosting multiple marketing sites: under $20.

Why Not WordPress?

WordPress powers 40% of the web. It’s also:

  • Slow by default: Database queries on every page load
  • Security maintenance: Constant plugin updates, vulnerability patches
  • Hosting costs: $10-30/month per site for decent performance
  • Overkill: You’re running a CMS to serve static pages

For a marketing site that changes once a week, this is absurd.

Static sites solve all of these problems:

  • Fast: Pre-built HTML served from a CDN
  • Secure: No database to hack, no plugins to exploit
  • Free hosting: GitHub Pages, Netlify, Vercel—all free for static sites
  • Simple: HTML, CSS, and maybe some JavaScript

The Architecture

Here’s how I structure a marketing site:

marketing-site/
├── _layouts/
│   ├── default.html      # Base template
│   └── post.html         # Blog post template
├── _includes/
│   ├── header.html       # Navigation
│   ├── footer.html       # Footer with links
│   └── contact-form.html # Reusable form component
├── _posts/               # Blog articles (optional)
├── assets/
│   ├── css/output.css    # Tailwind CSS (compiled)
│   └── images/           # Logo, OG images
├── index.html            # Landing page
├── contact.html          # Contact form page
├── privacy.md            # Privacy policy
├── _config.yml           # Jekyll configuration
├── CNAME                 # Custom domain
└── Gemfile               # Ruby dependencies

Jekyll compiles this into a _site/ folder of pure HTML. Push to GitHub, and Pages serves it globally.

Setting Up a GitHub Organization

For $4/month, a GitHub Team organization gives you:

  • Unlimited private repositories
  • GitHub Pages for each repo
  • Custom domains per site
  • Branch protection rules
  • Collaborator access

One organization can host dozens of marketing sites. Each site is its own repo, its own domain, its own deployment.

Setup:

  1. Create a GitHub organization (or upgrade existing)
  2. Create a repo named yoursite.github.io or any name
  3. Enable GitHub Pages in repo settings
  4. Point to main branch (or gh-pages branch)

Custom Domain DNS

GitHub Pages makes custom domains simple. Two DNS records:

# A Records (point to GitHub's servers)
Type: A
Name: @
Values:
  185.199.108.153
  185.199.109.153
  185.199.110.153
  185.199.111.153

# CNAME for www subdomain
Type: CNAME
Name: www
Value: your-org.github.io

Add a CNAME file to your repo root containing just your domain:

joycork.com

GitHub handles SSL certificates automatically via Let’s Encrypt. No configuration needed.

Jekyll Configuration

Here’s a minimal _config.yml that covers the essentials:

# Site settings
title: "Your Site Name"
description: "Your tagline here"
url: "https://yoursite.com"
baseurl: ""

# Markdown and permalinks
markdown: kramdown
permalink: /blog/:title/

# SEO plugins (GitHub Pages supports these)
plugins:
  - jekyll-feed      # RSS feed
  - jekyll-seo-tag   # Meta tags
  - jekyll-sitemap   # Sitemap.xml

# Social metadata
twitter:
  username: yourhandle

The jekyll-seo-tag plugin automatically generates Open Graph tags, Twitter Cards, and structured data. No manual meta tag management.

The Contact Form Problem

Static sites can’t process forms. No server = no POST handler.

Bad solutions:

  • Formspree: Works, but another vendor dependency
  • Netlify Forms: Locks you into Netlify
  • Google Forms: Ugly, breaks your brand

My solution: Cloudflare Workers + Postmark

A Cloudflare Worker is a serverless function that runs at the edge. It can:

  • Receive form submissions
  • Validate and sanitize input
  • Send email via Postmark API
  • Return success/error responses

Here’s the architecture:

User submits form
       ↓
JavaScript POSTs to Worker
       ↓
Worker validates input
       ↓
Worker calls Postmark API
       ↓
Email delivered to your inbox
       ↓
User sees success message

The Worker Code

export default {
  async fetch(request, env) {
    // Handle CORS preflight
    if (request.method === 'OPTIONS') {
      return new Response(null, {
        headers: {
          'Access-Control-Allow-Origin': 'https://yoursite.com',
          'Access-Control-Allow-Methods': 'POST',
          'Access-Control-Allow-Headers': 'Content-Type',
        },
      });
    }

    // Parse form data
    const data = await request.json();
    const { name, email, message } = data;

    // Basic validation
    if (!name || !email || !message) {
      return new Response(JSON.stringify({ error: 'Missing fields' }), {
        status: 400,
        headers: { 'Content-Type': 'application/json' },
      });
    }

    // Send via Postmark
    const response = await fetch('https://api.postmarkapp.com/email', {
      method: 'POST',
      headers: {
        'X-Postmark-Server-Token': env.POSTMARK_API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        From: 'noreply@yoursite.com',
        To: 'hello@yoursite.com',
        Subject: `Contact from ${name}`,
        TextBody: `Name: ${name}\nEmail: ${email}\n\n${message}`,
        ReplyTo: email,
      }),
    });

    if (response.ok) {
      return new Response(JSON.stringify({ success: true }), {
        headers: {
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': 'https://yoursite.com',
        },
      });
    }

    return new Response(JSON.stringify({ error: 'Failed to send' }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' },
    });
  },
};

Deploy with Wrangler CLI:

wrangler deploy
wrangler secret put POSTMARK_API_KEY

Cost: Cloudflare Workers free tier includes 100,000 requests/day. You’ll never hit it with a contact form.

Postmark Pricing

Postmark’s $15/month plan includes 10,000 emails. More importantly:

  • One account, multiple domains: Add all your projects
  • Excellent deliverability: Not going to spam
  • Simple API: One HTTP call to send

For transactional email (contact forms, password resets, notifications), Postmark is the best value I’ve found.

Claude Code for Design and Content

Here’s where the workflow gets interesting.

Traditional marketing site workflow:

  1. Design in Figma (hours)
  2. Convert to HTML/CSS (hours)
  3. Write copy (hours)
  4. Build pages (hours)
  5. Deploy (minutes)

With Claude Code:

  1. Describe what you want
  2. Claude generates HTML/Tailwind
  3. Iterate in conversation
  4. Deploy (minutes)

I built the Joy Cork landing page in a single afternoon. Hero section, features grid, pricing table, footer—all generated through conversation with Claude Code, then refined.

Example prompt:

“Create a hero section for a wine chatbot SaaS. Dark burgundy color scheme. Headline, subheadline, email capture form, and a mockup image placeholder. Use Tailwind CSS.”

Claude generates working HTML. I paste it in, see what needs adjustment, describe the changes, iterate. Faster than any visual builder, more flexible than any template.

For content, same approach:

“Write landing page copy for an AI chatbot that helps wineries answer customer questions. Focus on reducing staff workload and 24/7 availability. Conversational tone.”

Edit for voice, adjust for specifics, done.

Why This Beats WordPress

Aspect WordPress Jekyll + GitHub Pages
Hosting cost $10-30/month Free
Speed 2-4s load time <1s load time
Security Constant patches Nothing to patch
Maintenance Plugin updates None
Scaling Need better hosting Already on CDN
Design flexibility Theme limitations Full HTML/CSS control
Content workflow Admin panel Git + Markdown

When to Use This Stack

Perfect for:

  • Landing pages for SaaS products
  • Company marketing sites
  • Personal portfolios
  • Documentation sites
  • Simple blogs
  • Testing demand before building product

Not ideal for:

  • User-generated content
  • Complex dynamic applications
  • Frequently changing data
  • Non-technical content editors

If your marketing person can’t use Git, this isn’t the stack. But if you’re a solo builder or technical team, it’s unbeatable.

The Real Win: Testing Demand

Here’s why this matters for SaaS builders:

Before writing a line of product code, you can:

  1. Build a landing page (1 day)
  2. Set up email capture (1 hour)
  3. Drive some traffic (ads, social, communities)
  4. Measure interest (signups, messages)

Total cost: Under $20 and a weekend.

If nobody signs up, you saved months of building the wrong thing. If people are interested, you’ve validated demand and started building an audience.

This is exactly how I’m approaching Joy Cork. Marketing site is live. Waitlist is collecting emails. The product will follow—but only because people showed up.

Getting Started

  1. Create GitHub organization ($4/month)
  2. Create repo with Jekyll structure
  3. Add CNAME for custom domain
  4. Configure DNS (A records + CNAME)
  5. Deploy contact form with Cloudflare Worker
  6. Set up Postmark for email delivery
  7. Start building pages with Claude Code

You’ll have a professional marketing site live in a day, serving globally from GitHub’s CDN, with working contact forms and email capture.

No WordPress admin panel. No hosting bills. No security patches.

Just static HTML doing what static HTML does best: loading fast and staying online.


Stack used: Jekyll, GitHub Pages, Tailwind CSS, Cloudflare Workers, Postmark Monthly cost: ~$19 (GitHub org + Postmark) for unlimited sites Setup time: 1 day for first site, hours for subsequent sites Maintenance: Near zero

This article is part of my series.

Build with me

Weekly insights on building SaaS with AI. Real code, real struggles, real numbers.

Subscribe Free