How I Built a Multi-Tenant Static Site Engine with Next.js, Nginx, and Coolify
December 13, 2025
Author: Boby Santoso Freedantius
Reading time: 4 minutes
Over the past few months my Sister started this Embroidery business, and as a good brother I was eager to help her. I really wanted to help her get more visibility online. Naturally, my first thought was: let's make her a simple landing page.
But, here's the thing:
As a Software Engineer who uses coding agents a lot and understands how powerful automation can be, I had zero interest in building landing pages using drag and drop tools. Not with Wix, Wordpress, not with Lovable, not even with V0. I already pay for Claude Code, and I want the most optimized, scalable, and developer friendly solution I can build.
That’s what led me to this idea:
a Multi-Tenant Static Site Engine with
Next.js.
But Boby, Next.js? Static? What are you talking about?
Let me explain.
High-Level Overview
Before diving into the technical details, let me show you what the system looks like from the top.
Most landing pages today are built manually or with drag-and-drop tools. I wanted something different:
- Automated
- Config Driven
- Super Fast
- SEO Optimized
- Super Cheap to Host
- And able to host hundreds of sites without breaking a sweat
Architecture
This is the “bird's-eye view” of the entire system:

- A single engine built with
Next.js - A Config Driven system for each tenant
- A Component Factory that assembles pages
- A Static Export that generates pure HTML
- Automated output (sitemap, robots, analytics, Nginx configs)
- Deployment handled by Coolify, assigning subdomains or custom domains
One engine -> unlimited landing pages.
Build Pipeline

-
Business Config
Each tenant has a JSON config with branding, colors, services, copy, etc.
-
Component Factory
The engine picks from a library of reusable section templates. For example, you can build commonly used sections like this:
hero
|- default
|- split
features
|- grid
|- list
footer
|- default
|- multi-columns
gallery
|- default
|- scrolling
-
Static Export (
Next.js)Next.jscompiles everything into static HTML.
const nextConfig: NextConfig = {
output: "export",
images: {
unoptimized: true,
},
trailingSlash: true,
};
-
Auto-Generated Assets
The system produces sitemap.xml, robots.txt, analytics, OpenGraph metadata, etc.
-
Nginx Configuration
The generator builds the routing + subdomain config for each tenant.
-
Deploy via Coolify
Coolify picks up the output -> reloads Nginx -> site goes live.
What this means in Practice
Instead of building landing pages one by one, I can:
- onboard a new business
- fill out a config
- pick the sections
- run the generator
- instantly deploy a fully functional, SEO-ready landing page.
It’s fast, cheap, scalable, and extremely flexible.
Why Static > SSR for This Kind of Project
For a Multi-Tenant system where I want to host tens or hundreds of small business sites, SSR can be overkill:
- Every request needs a Node.js process to run the app
- You usually have middleware, auth, data fetching, layout logic on each hit
- You need to think about concurrency, memory, cold starts, scaling
With static export:
- Each page is already rendered to HTML at build time
Nginx(or any simple web server) just reads files from disk and sends them- There's no React/
Next.jscode running on the server per request - No per-request rendering = less CPU, less RAM, less that can break
For my use case (small businesses, mostly “read-only” marketing pages), static wins:
- First byte is faster (no render step)
- Less complexity to scale
- Way easier to reason about performance
- Much cheaper infrastructure
If I ever need “dynamic” behavior, I can still add:
- Small API routes, I have one already
- Client-side interactivity
- Webhooks or background workers
But the core of the site remains static.
Why I Can Host Hundreds of Pages on a “Cheap” Server
So how much is "cheap"?
A basic cloud server (like a small DigitalOcean/Vultr/Linode instance) typically costs around:
USD $4–7 / month for:
- 1 vCPU
- 0.5-1 GB RAM
- ~10-25 GB SSD
- 500 GB - 1 TB outbound bandwidth per month
That kind of machine is not great for heavy SSR apps with databases and background jobs. But for pure static hosting with Nginx, it's actually kind of overpowered.
Rough math:
Let’s say one page (HTML + CSS + a bit of JS) is ~300 KB With 500 GB outbound bandwidth, you can theoretically serve:
500,000,000 KB / 300 KB ≈ 1.6 million page views per month
With 1 TB bandwidth, that’s ≈ 3.3 million page views per month
Real traffic will be lower, and you'll have images etc. But even if you divide those numbers by 10, you still get hundreds of thousands of page views comfortably.
For a multi-tenant scenario:
100 tenants × 1,000 page views/month each = 100,000 views/month
That’s nothing for a static Nginx box with 500 GB+ bandwidth
And because:
- There's no SSR
- No per-tenant backend
- No database queries per page view
Your main bottleneck becomes bandwidth, not CPU or RAM. And cheap servers already give you a lot of bandwidth for this use case.
So when I say "cheap", I literally mean:
One small cloud instance in the $4–7/month range
If I later outgrow that, I can:
- Add a CDN in front
- Scale horizontally (more small boxes)
- Or move to a slightly bigger instance
But the core benefit stays the same: Static + Multi-Tenant = a lot of sites on very little infrastructure.