Building better product websites

As an indie hacker (a software developer who bootstraps his own products), I wanted to develop a system that would allow me to host a bunch of product sites for cheap. I needed a system that could 1 handle lots of traffic, 2 accept payments through Stripe, and 3 be low-cost or even free.

For context, I sell digital, downloadable products, although you could use a similar strategy to handle web applications, too. To meet my requirements, I set up a system that has the following flow:

  1. People land on and click “Buy”
  2. It takes them to where they pay
  3. They are shown download links and receive an email

Building landing pages that can stand up to traffic

The typical website is built on top of a database. For instance, if you’re using WordPress, this is what happens on the technical side when a user visits your site:

Enable JavaScript to view this content. If you've enabled JavaScript and still can't see this content, you might be using an unsupported browser.

This happens for every user, so if there are a lot of users, the database can’t keep up. (You’ve probably seen “Error establishing a database connection” before.)

On the other hand, a static website can handle much more. Static sites are websites which are generated once and the resulting files are distributed as plain HTML, without the need for a database:

Enable JavaScript to view this content. If you've enabled JavaScript and still can't see this content, you might be using an unsupported browser.

I use as a base domain for my blog and my projects. It’s a simple static site generated with Jekyll (same as Obama’s) and hosted for free on GitHub Pages. Each of my projects has its own dedicated landing page like Let me say that again: with GitHub Pages, hosting is free. The only cost I incur is my domain name, which I’ve registered via Hover.

You can use a separate domain name for each of your projects if you want.

This is the stack:

Setting up a server for Stripe

If you’re using Stripe to accept payments, you’ll need to write some server-side code, which you can’t do from GitHub Pages. I’ve created a Node.js site on Heroku and linked it to (If you’re completely new to all of this, don’t worry.)

This “storefront” site only needs to handle the traffic from people who want to purchase my products. This will naturally be lower than the traffic that hits my marketing site (unless I’m really freaking lucky), so I can rest easy knowing that my site won’t go down.

Here’s the stack of the payment processing site:

  • Hosted on Heroku
  • Uses Node.js, Express, and Handlebars
  • Plain HTML/CSS, Stripe’s JS
  • Uses Stripe Elements for payments (my own custom design)
  • Sends purchase emails with a Stripe + Zapier recipe

I set up the DNS records for via Cloudflare. I used their article on connecting a subdomain to Heroku. In Cloudflare’s DNS, you just create a CNAME record:

  • name: the subdomain you want to use, such as store
  • value: the public URL of your Heroku app (

Paying for Heroku is optional because they offer a free tier. The only downside of their free tier is that your server will go to sleep after 30 minutes of inactivity, and then it will take ~7 seconds to start up when the next visitor hits it (so your visitor will just be sitting on a blank screen for a few seconds). To keep your server awake, you can pay for their $7/month Hobby tier, which I think is fair – and it’s considered a business expense.

If you’re new to setting up Heroku, Stripe, and Node

Follow along with this video if you’re new to setting up a Stripe payment processing website. By the end of this video, you’ll have a functioning payments app:

The End Result

You’ll have an ultra-low-cost set of landing pages that can withstand traffic, as well as a payment processing storefront hosted on one of your subdomains. You can tweak this as necessary to fit your needs. Happy hacking!

  1. If you’re using Cloudflare to set up your subdomain, don’t use the CNAME that Heroku recommends, but rather the public URL of your app (which will be something like You can check out Cloudflare’s support article if you want to read more. ↩︎