DEV Community

Nexus Intelligence Research
Nexus Intelligence Research

Posted on

🚀 Launching an AI‑Powered SaaS with Stripe Checkout, Docker & Auto‑Marketing

Your end‑to‑end guide to turning a simple Flask app into a production‑ready, SSL‑secured service that sells itself.


📚 TL;DR

  1. Start from the ciel_auto_1._write_a_flask_(or_fastapi).py template.
  2. Add two routes – a landing page (/) and a Stripe checkout (/checkout/<plan>).
  3. Dockerize the app and run it behind nginx on a VPS (169.58.38.67) listening on port 80.
  4. Secure everything with Let’s Encrypt (auto‑renew).
  5. Publish the site at https://ciel‑services.com.
  6. Create a 2‑minute YouTube promo, embed the checkout link, and push the video.
  7. Update three existing Dev.to posts with a CTA to the new URL.
  8. Automate social posts (Twitter, Reddit, LinkedIn) every 12 h using NewsAPI.
  9. Reward the first 5 customers with a one‑time “LAUNCH10” discount.

Below is a complete Dev.to‑ready markdown article (500 + words) that walks you through each step, includes ready‑to‑copy code, and even drops a couple of affiliate links for the tools we love.


🎯 Why This Project Matters

AI, crypto, geopolitics, and data analysis are hot topics—but building a product that actually makes money is still a pain point. By the end of this guide you’ll have a live SaaS storefront that sells a subscription plan (or any digital product) without writing a single line of JavaScript for the checkout flow. All you need is a Python web framework, Stripe, Docker, and a bit of Bash.

Pro tip: The same pattern works for any AI‑driven API (e.g., a sentiment‑analysis endpoint) or crypto‑price‑alert service. Just swap the business logic inside the Flask route.


🛠️ 1. Base Code – ciel_auto_1._write_a_flask_(or_fastapi).py

Below is a minimal Flask skeleton (you can replace it with FastAPI if you prefer). Save it as app.py.

# app.py
import os
from flask import Flask, render_template, redirect, url_for, abort
import stripe

app = Flask(__name__)

# -------------------------------------------------
# Stripe configuration – replace with your own keys
# -------------------------------------------------
stripe.api_key = os.getenv("STRIPE_SECRET_KEY")
DOMAIN = os.getenv("DOMAIN", "https://ciel-services.com")   # used for redirects

# -------------------------------------------------
# Landing page – product overview
# -------------------------------------------------
@app.route("/")
def landing():
    # In a real app you’d pull this from a DB or CMS
    product = {
        "name": "Ciel AI Insight",
        "description": "AI‑powered data analysis for crypto traders & geopolitics enthusiasts.",
        "price_monthly": "$19.99/mo",
        "price_yearly": "$199.99/yr",
        "features": [
            "Real‑time market sentiment",
            "Geo‑risk heatmaps",
            "Custom alerts",
            "API access"
        ],
        "testimonials": [
            {"author": "Alice", "text": "Game‑changer for my crypto portfolio."},
            {"author": "Bob", "text": "The geopolitics dashboard saved me $5k last quarter."}
        ]
    }
    return render_template("landing.html", product=product)

# -------------------------------------------------
# Checkout – creates a Stripe Checkout Session
# -------------------------------------------------
@app.route("/checkout/<plan>")
def checkout(plan):
    if plan not in ("monthly", "yearly"):
        abort(404)

    # Prices created in Stripe Dashboard – use your own IDs
    price_id = {
        "monthly": "price_1MxxxxxxMonthly",
        "yearly": "price_1MxxxxxxYearly"
    }[plan]

    try:
        session = stripe.checkout.Session.create(
            payment_method_types=["card"],
            line_items=[{
                "price": price_id,
                "quantity": 1,
            }],
            mode="subscription",
            discounts=[{
                "coupon": os.getenv("STRIPE_COUPON_ID")  # optional discount
            }] if os.getenv("STRIPE_COUPON_ID") else None,
            success_url=f"{DOMAIN}/success?session_id={{CHECKOUT_SESSION_ID}}",
            cancel_url=f"{DOMAIN}/cancel",
        )
        return redirect(session.url, code=303)
    except Exception as e:
        return str(e), 400

# -------------------------------------------------
# Simple success / cancel pages
# -------------------------------------------------
@app.route("/success")
def success():
    return "✅ Payment successful! Check your email for the receipt."

@app.route("/cancel")
def cancel():
    return "❌ Checkout cancelled. Feel free to try again!"

if __name__ == "__main__":
    # Bind to 0.0.0.0 so Docker can expose it
    app.run(host="0.0.0.0", port=5000, debug=False)
Enter fullscreen mode Exit fullscreen mode

Templates (templates/landing.html) can be simple HTML with placeholders for the product data. Feel free to style with Tailwind or Bootstrap—nothing in this guide depends on a particular CSS framework.


📦 2. Dockerize the App

Create a Dockerfile in the project root:

# Dockerfile
FROM python:3.12-slim

# Install system dependencies (optional)
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    && rm -rf /var/lib/apt/lists/*

# Set workdir
WORKDIR /app

# Install Python deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy source
COPY . .

# Expose Flask default port
EXPOSE 5000

# Run the app
CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

requirements.txt:

Flask==3.0.3
stripe==9.9.0
gunicorn==22.0.0   # optional, for production
Enter fullscreen mode Exit fullscreen mode

Build and test locally:

docker build -t ciel-saas .
docker run -d -p 5000:5000 -e STRIPE_SECRET_KEY=sk_test_... \
    -e STRIPE_COUPON_ID=coupon_... ciel-saas
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:5000 – you should see the landing page.


🌐 3. Deploy on VPS (169.58.38.67) with Nginx Reverse Proxy

3.1 Install Docker & Docker‑Compose

# On the VPS
apt update && apt install -y docker.io docker-compose nginx certbot python3-certbot-nginx
systemctl enable docker
Enter fullscreen mode Exit fullscreen mode

3.2 Create a docker-compose.yml


yaml
version: "3.8"
services:
  web:
    image: ciel-saas:latest
    build: .
    container_name: ciel_web
    restart: unless-stopped
    environment:
      - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
      - STRIPE_COUPON_ID=${STRIPE_COUPON_ID}
      - DOMAIN=https://ciel-services.com
Enter fullscreen mode Exit fullscreen mode

Top comments (0)