DEV Community

holdi
holdi

Posted on

How to Deliver Digital Downloads Automatically with No Backend

Moving from SaaS to digital products is a common pivot for freelancers. You want to sell a design pack, a code template, or a PDF guide without the overhead of a database, user authentication, or server-side file serving.

You don't need a full backend to do this. You can achieve instant, secure delivery using a static site generator, a few serverless functions, and a third-party file host. Here is the practical workflow to get it running.

1. The Architecture: Static Frontend, Dynamic Delivery

The goal is to keep your pricing page and product gallery static. This allows you to host the site for free on GitHub Pages, Netlify, or Vercel.

For the download mechanism, you will use a serverless function (or a "netlify function"). This function will serve as a bridge. It will accept a request, verify the payment (using Stripe or PayPal), and then stream the file from your third-party storage provider directly to the user's browser.

This approach ensures you never have to store user credentials, and the files live on a CDN, ensuring high speed.

2. Set Up Your Static Storefront

Build your pricing page using any framework—Hugo, Jekyll, Next.js, or plain HTML. The page should contain a "Buy" button for each product.

For this example, assume you have a Stripe Payment Link for a product called "React Dashboard UI Kit." The button on your site will look like this:

<a href="/api/checkout?productId=react-kit" class="buy-btn">
  Purchase React Kit - $19
</a>
Enter fullscreen mode Exit fullscreen mode

The crucial part is the link. It points to a local endpoint (/api/checkout) that you haven't built yet. The user is technically being directed to your backend, which will handle the logic.

3. Create the Serverless Function

If you are on Netlify, you create a folder named netlify/functions in your root directory. Create a file named checkout.js inside it.

You need to handle two main tasks here:

  1. Retrieve the file path associated with the product ID.
  2. Trigger a payment verification (or proxy the Stripe redirect) and serve the file.

Here is a practical implementation for a serverless environment:

const path = require('path');

exports.handler = async function(event, context) {
  // 1. Extract the product ID from the URL query string
  const productId = event.queryStringParameters.productId;

  // 2. Map products to their file paths on your storage provider
  // In a real app, fetch this from a database
  const products = {
    'react-kit': 'https://cdn.example.com/downloads/react-dashboard.zip',
    'illustrations': 'https://cdn.example.com/downloads/illustrations.zip'
  };

  const fileUrl = products[productId];

  if (!fileUrl) {
    return { statusCode: 404, body: 'Product not found' };
  }

  // 3. If this was a real payment verification, you would check the
  // Stripe payment intent here. For a simple drop-in, we pass the file URL.

  // 4. Redirect the user to the file URL
  return {
    statusCode: 302,
    headers: {
      Location: fileUrl
    },
    body: ''
  };
};
Enter fullscreen mode Exit fullscreen mode

4. Handling the File Delivery

In the code above, we are redirecting to a CDN link. This is efficient because the CDN handles the heavy lifting of serving the file.

If you want to obscure the file URL to prevent hotlinking or unauthorized access, you can modify the function to act as a proxy.

  1. The user hits your site.
  2. Your serverless function downloads the file from the hidden CDN URL.
  3. Your serverless function returns the file content to the user.

However, for most digital downloads, a 302 redirect is sufficient and reduces serverless function cold starts.

5. Payment Integration

The user's journey ends at the CDN link. You still need to ensure they actually paid. The most developer-friendly way to do this is using Stripe.

Do not create a backend server for your checkout. Instead, create a Stripe Payment Link. This is a static URL that allows you to set a price, a success URL, and a cancel URL.

  1. Success URL: Point this to your serverless function URL (e.g., https://your-site.com/api/checkout?productId=react-kit).
  2. Cancel URL: Point this to your home page (https://your-site.com).

When a user pays, Stripe sends them to your serverless function. The function returns the redirect to the file. No database is required to track who bought what; the static link itself acts as the key.

6. Security Best Practices

Without a backend, you must be careful about how you distribute links.

  • Don't use GET requests for payment: If you try to send the file directly from the button click on the frontend, anyone with inspect element can steal the download link. The serverless function ensures the user has been "validated" by the browser redirect flow initiated by Stripe.
  • TTL (Time to Live): If you want to disable a download after a week, you can use a tiny key-value store (like Supabase or Redis) to store the productId with a timestamp. Your serverless function checks this store before serving the file.

Summary

You can build a robust digital delivery system without writing a single line of backend authentication code. By combining a static storefront with serverless redirects and third-party storage, you keep your hosting costs at zero and your delivery instant.


I sell these kinds of digital packs in a tiny automated Telegram store - instant USDT delivery. Check it: https://t.me/m3lmhermes_bot

Top comments (0)