Skip to main content

Feature deep-dive · SaaSForge Agency

Directus headless CMS + Next.js for agencies

Directus headless CMS + Next.js for agencies

Most Next.js templates pretend MDX is the answer to every content problem. For developer-authored content that is mostly true. For agency marketing sites, where the client edits their own case studies, services, and blog after launch, handing them a git repo and asking for a pull request is the wrong workflow. A headless CMS is the right shape, and Directus is the credible self-hosted option that does not lock you into a SaaS provider.

Why a CMS for an agency marketing site, not for a SaaS app

Agencies hand off marketing-site control to clients; clients are not developers; PRs and MDX commits are not their workflow. A CMS gives non-technical editors a familiar admin UI to update services, case studies, team bios, and blog posts without touching the codebase. Directus's admin is structured around your actual database schema, so 'case_studies' as a Postgres table becomes a 'Case Studies' collection in admin with the right fields.

The other three BoilerlyKit templates do not ship a CMS because their content shapes are different: SaaSForge Starter is developer-authored MDX, SaaSForge AI's content is user-generated (chat threads, uploads), and SaaSForge Core's product UI is dynamic per-workspace. CMS overhead would slow down those buyers; it pays for itself only on the marketing-site use case Agency is built for.

How Next.js fetches and revalidates Directus content

Server Components fetch from the Directus REST or GraphQL API with the typed SDK. Pages use Next.js's `revalidate` to cache responses for a configurable window (5-60 minutes is typical for marketing content), so a popular page does not hit Directus on every request but updates within the window after an editor publishes.

On-demand revalidation is the second mechanism: Directus webhooks fire on collection changes, hit a Next.js revalidation endpoint, and bust the cache for the affected slug. The result is that editors see their changes within seconds of publishing without a full rebuild. ISR-friendly fetching is the pattern that makes a CMS-backed Next.js site feel like a static site to visitors and like a live CMS to editors.

Fetching a Directus collection in a Server Component
import { directus } from "@/lib/directus";

export const revalidate = 600;

export default async function CaseStudyPage({ params }: { params: { slug: string } }) {
  const study = await directus.request(
    readItems("case_studies", {
      filter: { slug: { _eq: params.slug } },
      fields: ["title", "summary", "body", "client", "translations.*"],
      limit: 1,
    })
  );
  if (!study?.[0]) notFound();
  return <CaseStudy data={study[0]} />;
}

Self-hosting Directus on Railway (or any Docker host)

SaaSForge Agency self-hosts Directus alongside Postgres 16 and Redis 7 via Docker Compose. Railway is the default deployment target in the docs because its one-click Docker deploy and managed Postgres remove most of the operational friction; AWS, Fly, Render, and any other Docker-capable host work the same way.

Self-hosting matters for agencies because client data, case studies, contact submissions, internal notes, lives on infrastructure you control rather than a CMS SaaS vendor's. The trade-off is operational responsibility: backups, updates, and uptime are yours. For most agency sites this is a fair trade; the data volume is small and Railway's managed Postgres handles the heavy lifting.

Schema-as-code and Directus migrations

Directus's schema lives in the Postgres database; changes to collections, fields, and relations can be exported as SQL migrations and committed alongside your code. This is the discipline that keeps a CMS-backed site from becoming a 'works on my laptop' problem: every collection change ships through the same review process as code.

SaaSForge Agency ships an initial schema covering services, case studies, portfolio items, blog posts, pages, and FAQs, each with translations for the three locales (EN, FR, ES). Adding a new collection is a Directus admin change plus a migration export, a half-hour exercise, not a research project.

Frequently asked

Can I use Directus with the other BoilerlyKit templates?
Directus is exclusive to SaaSForge Agency in the BoilerlyKit lineup. The other templates (Starter, AI, Core) are config-driven for marketing content and database-driven for product content; adding Directus to them is possible but not what they ship for. If you want a CMS-backed marketing site plus a SaaS app, the typical pattern is SaaSForge Agency for marketing and SaaSForge Core (or AI) for the product, two repos, two domains.
Why Directus instead of Sanity, Contentful, or Strapi?
Sanity and Contentful are managed SaaS CMS products with their own pricing and content lock-in; Strapi is a self-hosted alternative with a different schema model. Directus's positioning is that your Postgres database is the source of truth, the CMS is a layer on top, not a separate store. For agencies who already deploy with Postgres on Railway, that is the lowest-friction shape. The choice is reasonable across all four; SaaSForge Agency picks Directus because it lines up with the rest of the stack (Postgres + Docker + Railway).
How are the three locales handled in Directus?
Directus has a native translations model: each collection has a `translations` related collection where per-locale fields live. Editors switch the locale in admin and edit French or Spanish copy alongside the English source. Next.js fetches the translation matching the active locale at request time. The pattern works for both UI strings (handled by next-intl message catalogues) and content (handled by Directus translations).
What if I want a fully static marketing site without a CMS?
Then SaaSForge Starter is the cheaper, simpler answer, MDX files in the repo, no CMS to host, no Docker stack to run. Agency is the right pick when the editor is a non-developer or you are running a white-label template across multiple client engagements. Pick by who edits the content, not by which sounds more impressive on the feature list.
Ships in SaaSForge Agency

See SaaSForge Agency. Skip the deliberation.

Full source code. Lifetime updates. Polar Merchant-of-Record checkout. Private GitHub repo on purchase.