If youâre a solo founder or a hobbyist who wants to sell AIâtools, crypto utilities, or dataâanalysis scripts without spending a fortune on infrastructure, this guide is for you.
In this tutorial youâll learn how to:
- Generate a static HTML landing page with clear value propositions and Stripe checkout buttons using a tiny Python module.
-
Serve the page on a cheap VPS (portâŻ80) with a lightweight web server (PythonâŻ
http.serveror Caddy). - Listen to Stripe payment events on the same VPS and automatically email the buyer the deliverables (API key, download link, etc.).
- Log every checkout URL in a JSON file for future analytics.
- Bulkâupdate the description of existing YouTube videos and Dev.to posts to include the new landingâpage URL and a short CTA.
All the code is openâsource, easy to copyâpaste, and runs on a $5â$10/month VPS. No Docker, no Kubernetes, no hidden fees.
đ Table of Contents
- Prerequisites
- StepâŻ1 â Create the LandingâPage Generator
- StepâŻ2 â Deploy a Tiny Web Server on VPS1
- StepâŻ3 â Stripe Webhook Listener & Automated Email
- StepâŻ4 â CheckoutâURL Logging
- StepâŻ5 â BulkâUpdate YouTube & Dev.to Descriptions
- Putting It All Together (Folder Layout)
- Bonus: Deploy with Caddy (HTTPS for free)
- WrapâUp & Next Steps
đ§ Prerequisites
| Item | Why you need it | How to get it |
|---|---|---|
| VPS1 (any Linux server, 512âŻMB RAM is enough) | Host the static page, webhook, and JSON logger | DigitalOcean, Linode, Hetzner, or a cheap cloudâprovider |
| Domain name (optional but recommended) | Friendly URL and SSL via Letâs Encrypt | Namecheap, Cloudflare, etc. |
| Stripe account (with Checkout enabled) | Payment processing | https://dashboard.stripe.com/register |
| SMTP credentials (Gmail App Password or SendGrid API key) | Send the delivery email | Gmail â âApp passwordsâ, SendGrid â API key |
| PythonâŻ3.9+ | Run the scripts | Preâinstalled on most VPS images |
| YouTube Data API v3 key | Update video descriptions | https://console.developers.google.com/apis/library/youtube.googleapis.com |
| Dev.to API token | Update Dev.to article descriptions | https://dev.to/settings/extensions â âAPI Keysâ |
Tip: Keep all secrets (Stripe secret key, webhook secret, SMTP password, API keys) in a
.envfile and load them withpythonâdotenv. Never commit them to Git.
1ď¸âŁ StepâŻ1 â Generate a Static Landing Page
Create a Python module called landing_page.py. It reads a tiny Jinjaâlike template, injects product data, and writes index.html.
python
# landing_page.py
import os
from pathlib import Path
import json
from urllib.parse import quote_plus
# -------------------------------------------------
# 1ď¸âŁ PRODUCT DEFINITIONS â edit to suit your offers
# -------------------------------------------------
PRODUCTS = [
{
"id": "aiâassistantâv1",
"name": "AI Assistant API",
"price_cents": 1999,
"description": "Fast, lowâlatency LLM endpoint with 10âŻkâtoken limit.",
"deliverable": {
"type": "api_key",
"template": "YOUR-API-KEY-{uid}"
},
},
{
"id": "cryptoâsignalâpackâv2",
"name": "Crypto Signal Pack",
"price_cents": 4999,
"description": "Realâtime trading signals + backâtested CSV.",
"deliverable": {
"type": "download",
"url": "https://example.com/downloads/cryptoâsignals-v2.zip"
},
},
]
# -------------------------------------------------
# 2ď¸âŁ HTML TEMPLATE (keep it simple â inline CSS)
# -------------------------------------------------
HTML_TEMPLATE = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>đ {title}</title>
<style>
body {{font-family:Arial,Helvetica,sans-serif;background:#f7f9fc;color:#333;max-width:800px;margin:auto;padding:2rem;}}
.product {{border:1px solid #ddd;border-radius:8px;padding:1.5rem;margin:1rem 0;background:#fff;}}
.cta {{background:#0066ff;color:#fff;padding:.75rem 1.5rem;border:none;border-radius:4px;cursor:pointer;}}
.cta:hover {{background:#0055dd;}}
</style>
</head>
<body>
<h1>{title}</h1>
<p>{subtitle}</p>
{products_html}
</body>
</html>
"""
PRODUCT_BLOCK = """
<div class="product">
<h2>{name}</h2>
<p>{description}</p>
<form action="{checkout_url}" method="POST">
<button class="cta">Buy for ${price}</button>
</form>
</div>
"""
# -------------------------------------------------
# 3ď¸âŁ Helper: create Stripe Checkout URL (clientâonly)
# -------------------------------------------------
def stripe_checkout_url(product_id: str, price_cents: int) -> str:
"""
Returns a preâbuilt Stripe Checkout URL.
You must have a Stripe Checkout Session template set up in your dashboard.
"""
# This example uses Stripeâs âprice IDâ approach.
# Create a price in Stripe Dashboard and replace `price_XXXX` below.
# For dynamic sessions you would call Stripe API from a backend,
# but for a static page we can embed a preâconfigured session link.
# See https://stripe.com/docs/payments/checkout/custom-domains
price_id = os.getenv("STRIPE_PRICE_ID_" + product_id.upper(), "")
if not price_id:
raise ValueError(f"Missing price ID for {product_id}")
# Encode the price ID for a clientâonly Session URL
return f"https://checkout.stripe.com/pay/{quote_plus(price_id)}"
# -------------------------------------------------
# 4ď¸âŁ Main: build the page
# -------------------------------------------------
def build_page(output_path: Path = Path("public")):
output_path.mkdir(parents=True, exist_ok=True)
product_html_parts = []
for p in PRODUCTS:
checkout = stripe_checkout_url(p["id"], p["price_cents"])
product_html_parts.append(
PRODUCT_BLOCK.format(
name=p["name"],
description=p["description"],
checkout_url=checkout,
price=f"{p['price_cents'] / 100:.2f}"
)
)
page_html = HTML_TEMPLATE.format(
title="đ AI & Crypto Marketplace",
subtitle="Pick a product, pay
Top comments (0)