The Multi-Site Challenge

When you run multiple projects — AIKit (ai-kit.net), AiSalonHub (aisalonhub.com), CCFish (ccfish.app), and a Playable Ad Studio — your content strategy needs to scale across all of them. Each site has its own audience, voice, SEO keywords, and publishing cadence. Managing them separately would mean duplicated infrastructure, inconsistent workflows, and wasted engineering time.

We solved this by running all four sites on the same stack: EmDash CMS on Cloudflare Workers, backed by D1 databases and R2 storage. Each site is an independent deployment with its own D1 database, but they share tooling, deployment patterns, and content automation pipelines.

This is the story of how that architecture works — and what we learned about running a multi-project CMS at the edge.

The Shared Pipeline Architecture

One Queue, Many Sites

All four sites share a single content automation pipeline. Blog posts are generated as JSON files in a queue directory, published via a Python script that inserts directly into the appropriate D1 database, and verified via HTTP checks. The queue system is project-aware — each queue file's tags and category determine which site it targets.

```

Content Pipeline Flow:

[Queue Files] → [blog-publisher.py] → [Cloudflare D1] → [Live EmDash site]

↑ ↓

[Content Calendar] [Published archive]

```

This shared pipeline means we only maintain one publishing script, one verification process, and one error recovery path. When we add a new site to the portfolio, the content pipeline is already ready for it.

Database Isolation at the Edge

Each site gets its own D1 database and R2 bucket. This keeps data completely isolated — no risk of cross-contamination between blog posts, and no shared query performance issues. The Workers runtime handles routing: each custom domain maps to a specific Worker that binds to its own D1 database.

| Site | D1 Database | Content Focus |

|------|-------------|---------------|

| ai-kit.net | ai-kit-net | EmDash CMS, AI tools, SEO |

| aislonhub.com | aislonhub-db | Nail salon tech comparisons |

| ccfish.app | ccfish-db | Mobile game development |

Despite the isolation, all sites use the same EmDash version and seed file patterns. A new site can go from zero to live in under an hour — we timed it with AiSalonHub.

Cron-Driven Publishing

Content publishing is fully automated via cron jobs running Mon/Wed/Fri at 6AM. The cron job checks the queue, publishes the first file, verifies the published URL returns 200, archives the file, and repeats until the queue is empty. If the queue has one or fewer remaining posts, it auto-generates fresh content from the content calendar.

```bash

Simplified cron workflow (runs autonomously)

python3.9 ~/cmo/scripts/queue-publisher.py

Checks queue, publishes, archives, generates if needed

```

This means we never have to manually publish a blog post. The content calendar is the single source of truth — entries are written to it, the cron system reads from it, and posts go live without human intervention.

Marketing Win: Content Consistency at Scale

The multi-site architecture isn't just a technical achievement — it's a marketing multiplier. Here's why:

1. **Cross-site content repurposing** — a blog post about EmDash's schema design on ai-kit.net becomes the foundation for a comparison-page strategy on aislonhub.com

2. **Consistent brand positioning** — every site uses the same voice and publishing quality bar because they flow through the same pipeline

3. **SEO link equity** — each site can link to relevant content on sibling sites, building a content network that Google recognizes as authoritative

4. **Zero incremental cost** — adding a new site adds no operational overhead because the pipeline is already built

What It Costs

The entire multi-site infrastructure runs on Cloudflare's free tier:

- Workers: Included in the $0 plan (100k requests/day)

- D1: 5GB storage, 5M read operations/month included

- R2: 10GB storage, 10M read operations/month included

- KV: 100k read operations/day included

For four active sites, our monthly Cloudflare bill is exactly $0. The only cost is the EmDash license.

Lessons Learned

Lesson 1: Seed Files Are Your Schema Contract

Every EmDash site starts with a `seed/seed.json` file. By standardizing seed file patterns across projects — same collection naming, same field type conventions, same taxonomy patterns — we made it trivial to route content between sites and train new team members on the system.

Lesson 2: Portable Text Makes Content Portable

EmDash's use of Portable Text (Sanity's JSON block format) means content is structurally identical regardless of which site it lives on. A blog post exported from ai-kit.net can be imported into aislonhub.com with no format conversion. This makes cross-site content syndication a simple SQL query, not a data migration project.

Lesson 3: Automate Everything, Including Content Generation

The most transformative lesson was automating not just publishing but content creation itself. By hooking the queue system into a content calendar with theme rotation, we eliminated the biggest bottleneck in content marketing: actually writing the posts.

The cron job doesn't just publish — it decides what to write based on current themes, project focus, and calendar availability. This makes content marketing truly autonomous, not just automated.

What's Next

We're building a cross-site content hub that aggregates blog posts from all four projects into a single feed, making it easy for users to discover content across the entire ecosystem. Each site benefits from the traffic of all the others, creating a network effect that no single-site CMS can match.