Architecture

A quick tour of how the starter is organized and why each piece is where it is.

Folder layout

saasforge-starter/
├── content/
│   ├── blogs/              # MDX blog posts
│   └── docs/               # MDX docs (you're here)
├── public/
│   ├── integrations/       # Integration logos
│   └── logo/               # Brand logos
├── src/
│   ├── app/                # Next.js App Router
│   │   ├── (legal)/        # /terms, /privacy, /license grouped
│   │   ├── blog/           # Blog listing + [slug]
│   │   ├── docs/           # Docs listing + [slug]
│   │   ├── layout.tsx      # Root layout + fonts
│   │   ├── page.tsx        # Home
│   │   ├── opengraph-image.tsx
│   │   ├── robots.ts
│   │   ├── rss.xml/
│   │   └── sitemap.ts
│   ├── components/
│   │   ├── blog/           # Blog listing + post card
│   │   ├── docs/           # Docs sidebar + nav
│   │   ├── ui/             # shadcn/ui primitives
│   │   ├── seo/            # JSON-LD schemas
│   │   └── [...sections]   # Hero, Features, FAQ, CTA, etc.
│   ├── config/
│   │   ├── app.ts          # Metadata
│   │   ├── blog.ts         # Blog post index
│   │   ├── brand.ts        # Brand strings
│   │   ├── docs.ts         # Doc index
│   │   ├── marketing-copy.ts
│   │   ├── routes.ts
│   │   ├── seo.ts
│   │   └── ui/             # Per-section configs
│   └── lib/
│       └── utils.ts        # cn() helper, etc.
└── next.config.ts

Rendering model

The starter is React Server Components by default. Only components that need hooks (useState, useTheme) or browser APIs get "use client".

  • app/page.tsx → server component, reads config statically
  • app/blog/[slug]/page.tsx → server component, reads MDX at request time (or build time)
  • components/theme/theme-provider.tsx → client (needs next-themes)
  • components/ui/button.tsx → server-compatible (no hooks)

Route groups

src/app/(legal)/ is a route group: the parenthesized name doesn't appear in the URL. It lets us share a layout for /terms, /privacy, and /license without affecting the URL structure.

Static + ISR

Most pages pre-render at build time (○ Static in the build output). Blog posts and doc pages use ISR with 1-hour revalidation (● SSG + revalidate: 3600). That means:

  • First request after build: served from the static HTML
  • After 1 hour: Next.js regenerates in the background
  • Next request: gets the fresh HTML
  • You can trigger on-demand revalidation via revalidatePath() when you need instant updates

Typed config

Every config file under src/config/ui/ exports a typed object. The types live in src/config/ui/types.ts. TypeScript errors catch:

  • Deleted required fields
  • Wrong field types (e.g., icon: "github" → icon must be a known key)
  • Typos in referenced keys

This is how the starter achieves "rebrand without grepping strings."

Theme token flow

globals.css :root {
  --primary: oklch(...);
  --color-primary: var(--primary);  // Tailwind v4 mapping
}

           ↓

shadcn/ui Button component
  className="bg-primary text-primary-foreground"

           ↓

Tailwind v4 utility
  background-color: var(--color-primary);

Change --primary once, every bg-primary / text-primary / border-primary updates. The .dark { --primary: ... } block overrides for dark mode.

MDX pipeline

  1. Page route calls readFile(content/path/file.mdx)
  2. next-mdx-remote/rsc parses MDX on the server
  3. remark-gfm plugin adds GitHub-flavored markdown support
  4. Our custom mdxComponents map overrides <a>, <img>, <pre>, <code>, tables, etc. to use next/link + next/image + theme-aware styling
  5. Rendered HTML streams to the browser as React Server Component output

Why no auth / DB / billing?

Because every product makes different choices. Forcing a stack (Supabase + Stripe + Resend) would mean:

  • You pay for complexity you don't use
  • Swapping vendors is expensive
  • The starter has opinions beyond its scope

When you need those layers, pick the vendor yourself: the starter stays out of your way.

If you're building a product where auth + workspaces + billing are the main features (not a content site), use SaaSForge Core: it's the same design system with those layers wired in.

Next