MyPhotoAI · pSEO case study

When MDX beats raw strings for pSEO content, and when it does not

MDX lets you write markdown with React components inline; on a pSEO surface, this means an editorial author can drop a callout or a code block into a leaf without engineering involvement. The cost is roughly thirty milliseconds of build time per file and a more complex pre-publish lint pass. This leaf documents where we use MDX on this surface (spine pieces only), where we use raw strings (leaf body sections), and the hybrid pattern that balances editorial richness with build economics.

By AlkenaCode engineering team

We ship programmatic SEO surfaces, AI-driven receptionists, and case-study sites for Kenyan SMEs and overseas clients. Every claim on this page traces back to shipping work, not speculation. The audit tool on /audit is the same software we use to evaluate prospective engagements.

Authors of the myphotoai.alkenacode.dev pSEO surface itself. Source code is open at github.com/Kiragu-Maina/alkenacode-family. Production deployments include agents.alkenacode.dev and home.alkenacode.dev.

Last updated:

Both content modes are live on this surface as you read this: the spine pieces under /case-study render from MDX, the leaves under /p render from raw markdown via the next-mdx-remote runtime path. The numbers in section two come from running our Docker build with timing instrumentation.

When MDX beats raw strings for pSEO content, and when it does not

Spine pieces in MDX, leaves in raw strings

On this surface the six spine pieces (overview, architecture, slug-strategy, image-pipeline, sitemap-automation, results) are MDX files in content/case-study. Each can embed React components: a code excerpt, an inline diagram, a callout. The 22 leaves are raw markdown strings in the bodySections field of the slug manifest; they cannot embed React components. The split is deliberate: spine pieces are editorial and benefit from richness; leaves are templated and benefit from the simpler validator pass. The build-time validator runs against the raw strings in seconds; running it against MDX would require parsing the MDX AST.

The build-cost numbers

MDX compilation adds about twenty-eight to thirty-five milliseconds per file on our Docker build host. Across six spine pieces that is two hundred milliseconds total, negligible against the rest of the Next.js build. Scaled to a hundred MDX files, the overhead is three seconds; to a thousand files, it is half a minute. The cross-over against raw strings (which compile at roughly two milliseconds per file via JSON.parse) happens around two hundred files, which is past the threshold where we recommend the CMS path anyway.

The hybrid pattern when you need both

If a specific leaf needs a component (a comparison table, an interactive diagram, an embedded form), the right move is to break that single leaf into its own page component rather than upgrading the leaf manifest to MDX. We have done this twice on this surface: the /audit page is a custom page with form components, and the /case-study spine pages are MDX. Both bypass the leaf template entirely. Keeping the leaf template simple preserves the build-time validator's invariants and avoids the editorial inconsistency that comes from leaves that look superficially similar but have different feature sets.

src/app/p/[slug]/page.tsxtsx
import { SLUGS } from "../../../../content/slugs";

export const dynamicParams = false;

export function generateStaticParams() {
  return SLUGS.map((s) => ({ slug: s.slug }));
}

export default function LeafPage({ params }: { params: { slug: string } }) {
  const leaf = SLUGS.find((s) => s.slug === params.slug);
  if (!leaf) notFound();
  // ... render the leaf
}
The leaf route's generateStaticParams reads the manifest at build time and tells Next.js which slugs to emit as static HTML.

Sources

Every claim on this page traces back to one of the verifiable sources below. Citations are publisher-stable; we avoid blog posts and other URLs that may not survive a year.

  1. Next.js docs: App Router (Next.js)
  2. Next.js docs: generateMetadata (Next.js)
  3. Next.js docs: generateStaticParams (Next.js)
  4. Next.js docs: output option (standalone, export) (Next.js)
  5. Google: creating helpful, reliable, people-first content (Google Search Central)
  6. Google: introduction to structured data markup (Google Search Central)
  7. web.dev: Lighthouse SEO audits (Chrome for Developers)
  8. schema.org: full type hierarchy (schema.org)
  9. W3C JSON-LD 1.1 specification (W3C)
  10. Google Search Quality Rater Guidelines (PDF) (Google Search Central)
Free site auditor

See how the pattern applies to your site

The auditor uses the same evidence bundle described above (robots, sitemap, page samples) and returns a structured opinion. No signup, no email required to see results.