Inject up-to-date Schema.org JSON-LD into your nginx-served sites with zero crons, zero site file changes, always fresh. A FastAPI sidecar + nginx SSI integration that lets an upstream AI/automation push schemas to your hosting machine in real time.
If you host static or server-rendered HTML through nginx and want fresh, dynamic Schema.org JSON-LD in every page's <head> without redeploying the site every time a schema changes, you have three bad options:
- Edit the HTML files every time → site redeployment per schema change
- Cron job that rebuilds + redeploys → stale between cron runs, slow propagation
- Server-side rendering → couples schema generation to your rendering tier
SEO Sidecar is the fourth option. An upstream process (your AI, your CMS, your trend analyzer, whatever) pushes JSON-LD to a tiny FastAPI service on your nginx host. nginx pulls the schema in via SSI on every page load. Schema updates take effect instantly with no site redeployment, no cron lag, no rendering coupling.
Built in production for ThatDevPro's network of nine client websites.
<UPSTREAM> (your AI publishing source)
│
│ Push over Tailscale (event-driven)
│ POST /update/{site} with JSON-LD
│
▼
┌──────────────────────────────────────────┐
│ <SIDECAR_HOST> (your nginx host) │
│ │
│ seo-sidecar (localhost:9090) │
│ ├── SQLite: /var/lib/seo-sidecar/ │
│ ├── Receives pushes from upstream │
│ ├── Serves schemas to nginx │
│ └── Keeps history + versioning │
│ │
│ nginx │
│ ├── SSI include on every page load │
│ ├── Fetches from localhost:9090 │
│ ├── 5min proxy_cache (configurable) │
│ └── 1s timeout (pages never stall) │
│ │
│ 9 hosted sites │
│ └── Each gets dynamic JSON-LD in <head> │
└──────────────────────────────────────────┘
- Your upstream service decides a schema needs updating (trend shift, new FAQ, competitor gap)
- Upstream pushes the new JSON-LD to
http://<SIDECAR_HOST>:9090/update/{site}over Tailscale - Sidecar stores it in SQLite with version history
- nginx SSI fetches from
localhost:9090/schema/{site}on every HTML page load - Schema appears in the
<head>of the site — search engines and AI crawlers see it immediately
No cron jobs. No file writes. No site deployments. Upstream controls schema state remotely.
| File | Where It Goes | Purpose |
|---|---|---|
sidecar.py |
/opt/seo-sidecar/ on the sidecar host |
FastAPI service — receives pushes, serves to nginx |
nginx-seo-sidecar.conf |
/etc/nginx/conf.d/ on the sidecar host |
Upstream + hostname map |
seo-inject.conf |
/etc/nginx/snippets/ on the sidecar host |
Drop-in include for server blocks |
megamind_push.py |
upstream nodes | CLI push client |
seo_client.go |
Go push client | Go push client for integration |
seo-sidecar.service |
/etc/systemd/system/ on the sidecar host |
systemd unit |
deploy-sidecar.sh |
Run once on the sidecar host | Full automated deployment |
# Copy files to your sidecar host
scp -r seo-sidecar/ <YOUR_SERVER>:/tmp/seo-sidecar/
# SSH in and deploy
ssh <YOUR_SERVER>
cd /tmp/seo-sidecar
sudo bash deploy-sidecar.shThen add one line to each nginx server block:
include /etc/nginx/snippets/seo-inject.conf;Reload nginx:
nginx -t && systemctl reload nginx# Push single site
python megamind_push.py push thatdeveloperguy
# Push all 9 sites
python megamind_push.py push-all
# Bulk push (single HTTP request)
python megamind_push.py push-bulk
# Check what's live
python megamind_push.py status
# View version history
python megamind_push.py history thatdeveloperguyOr from Go:
client := seo.NewClient("http://<SIDECAR_HOST>:9090", "your-token")
client.Push("thatdeveloperguy", jsonldString)POST /update/{site}— Push schema for one sitePOST /update-bulk— Push schemas for multiple sitesDELETE /schema/{site}— Remove a schema
GET /schema/{site}— Returns<script type="application/ld+json">HTML
GET /status— All sites, versions, freshnessGET /history/{site}— Version history
Set in /etc/systemd/system/seo-sidecar.service:
| Env Var | Default | Description |
|---|---|---|
SEO_DB_PATH |
/var/lib/seo-sidecar/schemas.db |
SQLite database location |
SEO_AUTH_TOKEN |
CHANGE_ME_BEFORE_DEPLOY |
Bearer token for push auth |
SEO_HOST |
127.0.0.1 |
Listen address (keep localhost) |
SEO_PORT |
9090 |
Listen port |
- Add the hostname mapping in
nginx-seo-sidecar.conf(themapblock) - Add
include /etc/nginx/snippets/seo-inject.conf;to the new site's server block - Push a schema:
python megamind_push.py push newsite
That's it. No other config changes.
- aio-surfaces — MIT-licensed Python toolkit that generates the four AI-citation surfaces (llms.txt, aeo.json, entity.json, brand.json) from a single site config. Pairs naturally with this — generate schemas with
aio-surfaces, push them with this sidecar. - llms.txt generator — free Hugging Face Space that drafts a spec-compliant
llms.txtfrom any homepage URL.
MIT © 2026 Joseph W. Anady (ThatDevPro). See LICENSE.
Built and used in production by ThatDevPro — SDVOSB-certified veteran-owned web + AI engineering studio. Cassville, Missouri.