I bought a "production-ready" template once. It was a single page. Beautiful hero, three feature cards, a footer with href="#" links, and a contact form whose submit button did absolutely nothing. That's not a product — it's a screenshot with extra steps.
So when I built a set of 20 Next.js + Tailwind templates, I wrote down what "production-ready" has to mean before writing a line of UI. Here's the architecture, and the five rules that separate a real template from a glorified landing page.
Rule 1 — It's a site, not a page (≥5 real routes)
A real business site has a home, an about, a services/features page, a pricing or menu page, and a contact page — minimum. Every template ships as an actual multi-page App Router app:
src/app/
layout.tsx # shared nav + footer, wraps every route
page.tsx # home
about/page.tsx
services/page.tsx
pricing/page.tsx
contact/page.tsx
If a "template" is one page.tsx, you're buying a hero section, not a website.
Rule 2 — One source of truth for content (this is the whole game)
The difference between "a template" and "your template" should be one file. Every site reads its text, links, nav, and brand from a single typed config. The buyer edits that file and the whole site — nav, footer, SEO tags, OG image — updates.
// src/lib/data.ts — edit this, and the site is yours
export const site = {
name: "Nexus",
tagline: "Ship faster with the all-in-one platform",
nav: [
{ label: "Features", href: "/features" },
{ label: "Pricing", href: "/pricing" },
{ label: "Contact", href: "/contact" },
],
contactEmail: "hello@example.com",
} as const;
// src/app/layout.tsx — nav generated from config, with active-link state
import { site } from "@/lib/data";
import Link from "next/link";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<nav>
<Link href="/">{site.name}</Link>
{site.nav.map((item) => (
<Link key={item.href} href={item.href}>{item.label}</Link>
))}
</nav>
{children}
<footer>© {site.name}</footer>
</body>
</html>
);
}
No find-and-replace across 30 files. No hardcoded "Acme Inc" hiding in a footer you'll find in production. One typed object, white-label by design.
Rule 3 — No dead buttons. Forms actually submit.
The fastest way to spot a fake template is to click the contact button. In a real one, the form validates on the client and posts to a working API route:
// client: validate before sending
const [error, setError] = useState("");
async function onSubmit(e: React.FormEvent) {
e.preventDefault();
if (!email.includes("@")) return setError("Enter a valid email");
const res = await fetch("/api/contact", {
method: "POST",
body: JSON.stringify({ email, message }),
});
if (res.ok) setSent(true);
}
// src/app/api/contact/route.ts — a real endpoint, honestly labeled
export async function POST(req: Request) {
const { email, message } = await req.json();
if (!email || !message) {
return Response.json({ error: "Missing fields" }, { status: 400 });
}
// Demo handler — wire this to Resend / your inbox in one place.
return Response.json({ ok: true });
}
Demo behavior is fine. Dishonest demo behavior — a button that pretends to work — is not. Every interactive element either works or says exactly what it is ("demo checkout — no real payment").
Rule 4 — SEO and metadata come from the same config
Because content lives in one object, the SEO layer writes itself. Title templates, canonical URLs, and OG tags all read from site, so the buyer never edits meta tags by hand:
// src/app/layout.tsx
import type { Metadata } from "next";
import { site } from "@/lib/data";
export const metadata: Metadata = {
title: { default: site.name, template: `%s | ${site.name}` },
description: site.tagline,
openGraph: { title: site.name, description: site.tagline },
};
Rule 5 — It compiles clean, or it doesn't ship
Every template passes tsc --noEmit with zero errors and next build with zero errors before it's considered done. A template that throws type errors on npm install isn't a starting point — it's homework.
Why the architecture matters more than the pixels
Anyone can design a nice hero. The value of a template is how fast someone else can make it theirs — and that's an architecture decision, not a visual one. Single source of truth, real routes, working forms, generated SEO, clean build. Get those right and the template is worth paying for; skip them and you've sold a screenshot.
I applied these five rules to 20 templates across different niches (SaaS, agency, restaurant, real estate, e-commerce, and more). Live demos:
- SaaS → https://01-modern-saas.vercel.app
- Photography portfolio → https://12-photography-portfolio.vercel.app
- Hotel booking → https://17-hotel-booking.vercel.app
If you want the whole set as a starting point instead of building the boilerplate yourself, they're bundled here: cenkkurtoglu.com/templates (use code LAUNCH20 for the early-buyer discount).
But the five rules are the real takeaway — apply them to your own templates and you'll never ship a dead button again.
Top comments (0)