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 build process for JenniNexus is a PowerShell pipeline:
- CSS consolidation — 18 source CSS files → one
main.css→ PurgeCSS →main.min.css(258KB → ~85KB after purge). Token order is strict:www-design-tokens.css→theme-variables.css→ layout → page themes. - JS bundling — 5 core files through Terser →
core.min.js(~18KB). Page-specific JS minified individually so each page only loads what it needs. - React islands — Vite builds the
VideoGridandImageGallerycomponents independently, outputting code-split bundles toresources/react/. PHP mounts them viadata-react-islandattributes. - 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.jsonfile 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 |
|---|---|---|
| Hosting | DigitalOcean Droplet (Ubuntu 24.04, PHP-FPM, Nginx) | ~$6/mo |
| Language | PHP 8.3 + Vanilla JS + React islands | Free |
| CSS framework | Bootstrap 5.3.8 (self-hosted) | Free |
| Build | PowerShell + clean-css-cli + Terser + PurgeCSS + Vite | Free |
| Analytics | GA4 + GSC (own property, no third-party) | Free |
| SSL | Let's Encrypt (auto-renew) | Free |
| Deploy | rsync over SSH | Free |
| Monitoring | PageSpeed Insights API + custom Node.js scripts | Free |
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.