When people ask me what "indie game developer" means in practice, they usually picture Unity scenes and game jam submissions. That's part of it. But sustaining an indie studio long-term — even a one-person studio — requires a surprisingly complete software infrastructure stack.

This post is a real walkthrough of what's running behind MartianGames.com, Synagen.us, and this site — the tools, the architecture decisions, the things I got wrong, and the systems I'm proud of.

The Three-Site Cluster

Running one website is a weekend project. Running three connected sites as a coherent brand is infrastructure design. Here's how they divide responsibilities:

  • MartianGames.com — the game portfolio. PHP 8.3 on DigitalOcean, serving pages for Air Wars, Tank Off, Martian Wars, and more. This is where players land from Google, Y8, and Bing. SEO score: 100/100. Getting ~2,400 sessions/month from organic search alone.
  • Synagen.us — the AI agent framework app. A React SPA backed by a Node.js/FastAPI stack. This is the developer tooling layer — the same AI agent system that helps manage the other two sites.
  • JenniNexus.com — this site. The creative hub, blog, and portfolio. PHP + React islands (VideoGrid, ImageGallery via Vite). The aggregator for the whole cluster's SEO data.

Each site has its own design identity but shares a common token system via a www-theme-kit — JSON brand profiles that define colors, typography hierarchy, and design rules as machine-readable data. When GraphViz (our theme agent) audits a CSS file, it reads from the same source as the build pipeline.

The Build Pipeline (Zero Webpack, Zero Next.js)

I deliberately avoided the usual JavaScript framework stack. No Next.js, no Webpack, no server-side React. Here's why, and what I use instead:

The Rule: PHP renders the page, JavaScript enhances it. React only where animations, lazy loading, or complex state genuinely need it ("React islands" pattern).

The build process for JenniNexus is a PowerShell pipeline:

  1. CSS consolidation — 18 source CSS files → one main.css → PurgeCSS → main.min.css (258KB → ~85KB after purge). Token order is strict: www-design-tokens.csstheme-variables.css → layout → page themes.
  2. JS bundling — 5 core files through Terser → core.min.js (~18KB). Page-specific JS minified individually so each page only loads what it needs.
  3. React islands — Vite builds the VideoGrid and ImageGallery components independently, outputting code-split bundles to resources/react/. PHP mounts them via data-react-island attributes.
  4. Deploy — rsync over SSH. Incremental: only changed files transfer.

The whole pipeline runs in under 90 seconds. On a game jam Saturday, I can ship a CSS change to all three sites before my coffee gets cold.

The AI Agent Team

This is the part that surprises most people. JenniNexus has a team of 7 AI characters who each own a specific domain of the site:

  • GraphViz (Wed) — theme system, colors, light/dark modes
  • Vidette (Mon) — video grids, YouTube RSS, playlist constants
  • Bloggie (Tue) — blog posts, tag system, share buttons
  • GamerGirl (Thu) — game pages, gaming hubs, CTAs
  • DivineDesign (Fri) — site-wide layout, UX, visual hierarchy
  • Metrica (Sat) — SEO, analytics, GA4, GSC, sitemap
  • Vixel (Sun) — VR/Unity integration, devlogs

Each agent runs a weekly audit script against their domain. Current score: 100 PASS / 1 WARN / 0 FAIL across 5 audit dimensions. The one warning is an intentional dev-only inline style that's exempt.

The agents are defined as markdown profiles in a public GitHub repo (github.com/jenninexus/agency) with a two-layer override system: generic profiles usable by any project, with project-specific rules in a gitignored overlay. GamerGirl is JN-only — she exists only in the local overlay, not the public framework.

SEO Infrastructure: The Cluster Aggregator Pattern

One of my favorite systems is the SEO dashboard cluster. Instead of checking each site separately, JenniNexus's password-gated /seo page is the aggregator:

  • MartianGames serves a token-gated JSON export endpoint (?export=1&token=...)
  • Synagen publishes a static synagen.json file on aiqo
  • JN fetches both at page load (5-minute cache), merging them into a single three-tab dashboard

This means one login shows GA4 traffic, PageSpeed scores, GSC clicks/impressions, and action items for all three sites simultaneously. No third-party analytics dashboards, no paid tools. The data pipeline runs via Node.js scripts that call the GA4 Data API and PageSpeed Insights API directly.

Current scores from this morning's run: MG at Perf 59 (CLS confirmed fixed after a responsive AdSense containment fix last week — was at 1.0, back to 0). JN at Perf 68, SEO 100, Best Practices 100.

What I Got Wrong (So You Don't Have To)

1. Theme files shouldn't contain layout properties

Early on, I put padding and margins in the same CSS file as color variables. Now it's a hard rule: *-theme.css files contain only color definitions. Layout lives in custom.css, media in media.css, typography in jenni-fonts.css. When GraphViz audits themes, a layout property in a theme file is a fail.

2. Bootstrap's .ratio > * trap

Bootstrap applies position:absolute; width:100%; height:100% to all direct children of .ratio. If you put a badge or category label inside .ratio, it expands to full size and covers the image as a solid block. We hit this bug three times on blog card images before codifying the fix: the badge must be a sibling of .ratio, not inside it. Now it's in storage/docs/PROTOCOL.md.

3. PurgeCSS doesn't need a manual safelist for Bootstrap utilities

For the first year, I was manually adding every Bootstrap class to the PurgeCSS safelist. Unnecessary. Content scanning auto-keeps any class that appears in PHP/HTML/JS files. The safelist only needs to cover classes added by Bootstrap's JS at runtime (like show, collapse, fade) that don't appear in source files.

The Stack, Summarized

If you're an indie dev looking to build your own portfolio infrastructure, here's the actual list of what I'm running:

Layer Tool Cost
HostingDigitalOcean Droplet (Ubuntu 24.04, PHP-FPM, Nginx)~$6/mo
LanguagePHP 8.3 + Vanilla JS + React islandsFree
CSS frameworkBootstrap 5.3.8 (self-hosted)Free
BuildPowerShell + clean-css-cli + Terser + PurgeCSS + ViteFree
AnalyticsGA4 + GSC (own property, no third-party)Free
SSLLet's Encrypt (auto-renew)Free
Deployrsync over SSHFree
MonitoringPageSpeed Insights API + custom Node.js scriptsFree

Total monthly infrastructure cost: ~$6. Total time to first deploy: one weekend. The complexity came later, as the needs did.

What's Next

The immediate roadmap: LCP optimization on MartianGames (10.4s mobile is too high — hero image pipeline), adding BreadcrumbList JSON-LD to all pages, and growing JN's organic traffic from its current 2 sessions/month to something meaningful. That last one is a content problem, not a technical problem — which is why you're reading this.

The Synagen app is getting a lazy-loading pass on its WebGPU bundle next — currently causing a Perf 17 / FCP 18s score on mobile, which is catastrophic. That's the biggest technical fire in the queue.

If you're building an indie studio web presence and want to talk stack decisions, find me on Discord or Patreon. The full infrastructure is going open-source as it matures.