The Vision: One CMS, Many Sites
When we started AIKit, the goal was simple: build a blog that publishes SEO content automatically. But as the plugin matured, we realized the same architecture could power multiple sites from a single D1 database creating a content network with shared infrastructure and zero marginal cost per site.
**Why this matters:** Most content operations scale by hiring more writers, buying more domains, and managing more CMS instances. We scale by adding rows to a database table.
The Architecture: Multi-Site from One D1
Database Design
```sql
-- All sites share one D1 database
CREATE TABLE ec_posts (
id TEXT PRIMARY KEY,
slug TEXT,
site_id TEXT NOT NULL DEFAULT 'primary',
title TEXT,
content JSON,
status TEXT DEFAULT 'draft',
UNIQUE(slug, site_id, locale)
);
```
Each EmDash site (AIKit.net, AiSalonHub, future sites) runs its own Cloudflare Workers deployment, but reads from the same D1 instance. The `site_id` column filters which posts appear on which site.
Publishing Pipeline
```
Cron Job (Hermes) Generates JSON Blog Publisher D1
site_id = 'aikit' or 'aisalonhub'
Cloudflare Workers SSR rendering
```
The same cron pipeline that publishes to AIKit.net can target any site by setting the `site_id` field. All SEO meta, scoring, and revision tracking works identically across sites.
Step 1: Site Routing
Each deployment has a Workers binding:
```json
{
"d1_databases": [{
"binding": "DB",
"database_id": "ai-kit-net",
"database_internal_env": "PROD"
}],
"vars": {
"SITE_ID": "aikit",
"SITE_URL": "https://ai-kit.net"
}
}
```
The EmDash loader filters by SITE_ID at query time:
```typescript
const result = await env.DB.prepare(
"SELECT * FROM ec_posts WHERE site_id = ? AND status = 'published'"
).bind(env.SITE_ID).all();
```
Step 2: Shared Infrastructure
With multi-site D1, the infrastructure overhead per site drops to near zero:
| Resource | Standalone Cost | Shared D1 Cost | Savings |
|---------|----------------|---------------|---------|
| D1 Database | $5/mo | $0 (shared) | 100% |
| Workers | $0.30/mo | $0.50/mo (shared) | ~40% |
| KV | $0.50/mo | $0.50/mo (shared) | ~50% |
| R2 Storage | $0.015/GB | $0.015/GB | Same |
| **Total** | **~$6/mo per site** | **~$1/mo per addl site** | **~83%** |
Content Growth Strategy
A multi-site content network enables several growth tactics unavailable to single-site blogs:
1. **Cross-site internal linking** Link from an AIKit post to an AiSalonHub post (and vice versa). Google sees the link graph across your network.
2. **Shared topic clusters** Write pillar content on the main site, supporting posts on satellite sites. The pillar post links out, satellite posts link back.
3. **Content repurposing** A single LLM generation run produces the same core article adapted for each site's audience (technical vs business, general vs niche).
4. **Siloed crawl budgets** Each Workers deployment has its own crawl budget. Splitting content across sites means Google crawls more pages total.
Real Metrics from Our Network
After running 2 sites off the same D1 for 3 weeks:
- **Infrastructure cost:** $1.02 total (both sites)
- **Posts deployed:** 108 (AIKit) + 65 (AiSalonHub)
- **DB queries per day:** ~4,200 (both sites combined, under D1 free tier)
- **Time to deploy a new site:** ~10 minutes (clone repo, update SITE_ID, deploy)
Key Takeaways
- One D1 database can power multiple EmDash sites with zero per-site database cost
- The publishing pipeline is site-agnostic same JSON, different site_id
- Cross-site linking creates a content network that outperforms isolated blogs
- Scalable content operations don't require more CMS instances just more rows