Guide

Infrastructure

The Pew Research Center Digital Publishing Platform runs on WordPress VIP, with multiple environments, automated deployments, and a modular monorepo.

Git lives on Cursor Origin. CI and deploys run on Depot. VIP is what is live. See RELEASING.md for the deploy-manager CLI.

See the README in the repo root for monorepo structure, Node.js workspaces, and dependency setup. The most recent version and release name are there as well.

Architecture overview

The PRC Platform follows a WordPress Multisite architecture with subdirectory configuration, hosted on WordPress VIP. It is a monorepo of modular plugins and a design-system theme.

Infrastructure Diagram

flowchart TB
    subgraph dx ["Developer experience"]
        DEV[Developer workstation]
        LOCAL[VIP CLI local<br/>Docker]
        CLOUD[Cursor Cloud]
        DEV --> LOCAL
        DEV --> CLOUD
    end

    subgraph scm ["Git and CI"]
        ORIGIN[Cursor Origin<br/>git]
        DEPOT[Depot CI]
        MIRROR[WPCOMVIP repo<br/>source mirror only]
        ORIGIN --> DEPOT
        ORIGIN --> MIRROR
    end

    LOCAL --> ORIGIN
    CLOUD --> ORIGIN

    subgraph depotjobs ["Depot workflows"]
        RESET[reset-alpha-beta-branch]
        STAGE[deploy-to-staging]
        PUB[publish-release]
        BUILD[build-release]
        RESET --> STAGE
        PUB --> BUILD
    end

    DEPOT --> RESET
    DEPOT --> STAGE
    DEPOT --> PUB

    subgraph vip ["WordPress VIP"]
        ALPHA[alpha]
        BETA[beta]
        CANARY[canary]
        PROD[production]
        STAGE --> ALPHA
        STAGE --> BETA
        STAGE --> CANARY
        BUILD --> PROD
    end

    subgraph stack ["WordPress stack"]
        EDGE[Edge cache / Varnish]
        WP[WordPress 6.8<br/>Multisite]
        PHP[PHP 8.4]
        DB[(MariaDB)]
        ES[VIP Search]
        MC[Memcached]
        ALPHA --> EDGE
        BETA --> EDGE
        CANARY --> EDGE
        PROD --> EDGE
        EDGE --> WP
        WP --> PHP
        PHP --> DB
        WP --> ES
        WP --> MC
    end

    subgraph app ["PRC Platform"]
        PLUGINS[Plugins and blocks]
        THEME[prc-design-system]
        WP --> PLUGINS
        WP --> THEME
    end

    subgraph fb ["Firebase"]
        AUTH[Auth]
        RTDB[Named Realtime Databases]
        PLUGINS --> AUTH
        PLUGINS --> RTDB
    end

    subgraph ext ["Other integrations"]
        LINEAR[Linear]
        SLACK[Slack]
        MAIL[Mailchimp]
        APPLE[Apple News]
        PARSELY[Parse.ly]
        CF[Cloudflare Turnstile]
        SHOT[ScreenshotOne / Cloudflare]
        PLUGINS --> SLACK
        PLUGINS --> MAIL
        PLUGINS --> APPLE
        PLUGINS --> PARSELY
        PLUGINS --> CF
        PLUGINS --> SHOT
        ORIGIN -.-> LINEAR
        DEPOT -.-> LINEAR
    end

Origin is git. Depot is CI. VIP is live. The WPCOMVIP repository is an archival source mirror. Production deploys use vip app deploy from Depot build-release.yml. They do not git-track on the VIP app.

Firebase is the outside-user data plane. Auth and named Realtime Databases back accounts, quizzes, interactives, datasets, and data tables. MySQL stays the editorial store.

Core Technologies

  • WordPress: 6.8 (Latest)
  • PHP: 8.4 with php-fpm (local VIP dev-env; see .wpvip/vip-dev-env.yml)
  • Database: MariaDB/MySQL cluster
  • Web Server: Nginx
  • Search: Elasticsearch (VIP Search)
  • Caching: Edge cache (Varnish) + Memcached object cache
  • Outside-user data: Firebase Auth + named Realtime Databases

Environment Structure

1. Local Development

  • VIP Dev Environment (Preferred)
    • Docker-based local environment using VIP CLI
    • Configuration: .wpvip/vip-dev-env.yml
    • Includes: Xdebug, Mailpit, phpMyAdmin, Elasticsearch
    • Commands: npm run vip:start, npm run vip:stop, npm run vip:sync
  • Cursor Cloud (autonomous agents)
    • Cloud VMs boot the same VIP CLI dev-env via .cursor/environment.json
    • Elasticsearch is disabled in cloud (cgroup limits)
    • See Cursor Cloud agents

2. Staging Environments

Alpha Environment

Beta Environment

Canary Environment

  • Purpose: Mutable experimental sandbox — stack ad hoc experiments without landing them on trunk first
  • Alias: @pewresearch.canary (https://canary-pewresearch.go-vip.net/ — temporary convenience domain until canary.[REDACTED] DNS is ready)
  • Deploy Trigger: Push to canary (a manual reset or an ad hoc experimental merge)
  • Reset: Manual only — dispatch .depot/workflows/reset-alpha-beta-branch.yml with target_branch=canary to force-push trunk onto canary. There is no auto-reset on push.
  • Promotion: Experiments promote via a normal PR to trunk with a changeset. Never merge canarytrunk.
  • Workflow: .depot/workflows/deploy-to-staging.yml
  • Data sync: config/.vip.pewresearch.canary.yml; pull locally with npm run vip:sync:canary

3. Production Environment

  • Purpose: Live public site
  • Alias: @pewresearch.production
  • Deploy Trigger: Dispatch Depot publish-release.yml for a production git tag (vMAJOR.MINOR.PATCH) with matching tag and confirm
  • Workflow: .depot/workflows/build-release.yml
  • Urgent fixes: Ship a patch on the release line through the same prep + publish path. There is no separate emergency hotfix workflow. See RELEASING.md.

WordPress VIP Platform Services

Edge & Caching Layer

  • Edge Cache (Varnish CDN): Global content delivery with intelligent caching
  • Object Cache (Memcached): In-memory database result caching
  • Vary Cache: Geo-location and device-specific caching
  • Photon: Automatic image optimization and WebP conversion

Search & Data

  • VIP Search (Elasticsearch): Enhanced search with faceted filtering
  • VIP Block Data API: REST API for block-based content
  • Geo Uniques: Location-based content targeting using GEOIP_COUNTRY_CODE

Security & Performance

  • Two-Factor Authentication: Enforced on production environment
  • VIP Login Limiter: Brute force protection with rate limiting
  • Block Governance: Content block security and compliance
  • Smart Redirects: SEO-friendly URL redirects with spam protection

Retired VIP Node.js

VIP Node.js microservices are being sunset. The old Asana–GitHub sync and Node screenshot service are not part of the live architecture. Chart PNGs now go through prc-chart-builder screenshot providers (ScreenshotOne, Cloudflare Browser Rendering, or Firebase). Project tracking is Linear.

Deployment Pipeline

Source Control Flow

Developer → Cursor Origin (git) → Depot CI → VIP app deploy
                                  ↘ Firebase functions + Slack app manifests
                                  ↘ WPCOMVIP source mirror (archival)

Do not use gh workflow run. Cut, prep, publish, and staging dispatch through npm run deploy-manager. Origin is git. Depot is CI. VIP is live. Firebase functions and Slack app manifests ship from the same staging and publish workflows via .depot/workflows/deploy-platform-services.yml.

Automated Deployment Process

  1. Code push: Developer pushes to a feature branch on Origin.
  2. PR: Pull request targets trunk (or a release/** maintenance branch as described in RELEASING.md).
  3. Merge: Merging to trunk updates the alpha mirror and redeploys alpha; merging to the active release/x.y updates beta and redeploys beta (see .depot/workflows/reset-alpha-beta-branch.yml and .depot/workflows/deploy-to-staging.yml).
  4. Production: Dispatching Depot .depot/workflows/publish-release.yml for a production git tag publishes announce notes to DocsPress, posts Slack, then runs .depot/workflows/build-release.yml (VIP zip) in parallel with .depot/workflows/deploy-platform-services.yml (Firebase functions and Slack manifests). Operators check live status with npm run deploy-manager -- status (see RELEASING.md).
  5. WPCOMVIP mirror: On merged PRs, .depot/workflows/copy-to-wpcomvip.yml force-pushes a source-only snapshot of the merged branch to wpcomvip/pewresearch-org (no node_modules, no Composer vendor/, no webpack build/ outputs). VIP production does not consume this mirror for deploys; it is archival/reference. The built tree for a release is pushed to WPCOMVIP as part of the build-release.yml job after publish.

PRC Platform Application Stack

WordPress Multisite Configuration

  • Primary public site ID: 20 (www.[REDACTED], local /pewresearch-org)
  • Docs site ID: 1 (PRC_DOCS_SITE_ID, network root). DocsPress Pages live at /docs. Production: platform.[REDACTED]/docs. Local: https://prc-platform.vipdev.lndo.site/docs.
  • Multisite Style: Subdirectory
  • Default Theme: prc-design-system on the public site. Docs use the DocsPress theme.

The old wiki site is gone. Help Center reads DocsPress pages from the docs site, not a separate wiki.

Core Platform Components

Must-Use Plugins (client-mu-plugins/)

  • plugin-loader.php: Bootstrap and plugin orchestration
  • prc-vip-dev-env: Development-specific configurations
  • prc-bimi: Brand indicator email authentication

Core Plugins (50+ modular plugins)

  • prc-platform-core: Foundation utilities and shared functionality
  • prc-firebase: Shared Firebase Auth and Realtime Database access
  • prc-block-library: Custom Gutenberg blocks for content creation
  • prc-analytics: Tracking and measurement integration
  • prc-chart-builder: Data visualization tools
  • prc-quiz-builder: Interactive quiz system with WordPress Interactivity API
  • prc-datasets: Data management and publishing
  • prc-elasticpress: Enhanced search functionality
  • prc-staff-bylines: Author and contributor management

Firebase

Firebase is the platform's outside-user data plane. Editorial content stays in MySQL. Simultaneous writes from many clients go to Firebase.

SurfaceRole
Firebase AuthSign-in for prc-user-accounts (magic link and federated providers). REST mutations send X-PRC-User-Id and X-PRC-User-Token.
Named Realtime DatabasesSeparate RTDBs for auth, interactives, and data-table-builder. Constants live in vip-config/ (PRC_PLATFORM_FIREBASE_*_DB and __DEV variants).
PHP SDKprc-firebase initializes Kreait from private/firebase-service-account.json (never commit; generate with npm run gen:firebase-sa).
JS moduleNew blocks import @prc/firebase. Older interactives still use the legacy firebase script handle.

Consumers include prc-user-accounts, prc-quiz-builder, prc-quiz-cast, prc-datasets, prc-block-tables, and interactives. Chart screenshot capture can also use a Firebase provider. See PRC Firebase and dependency auth.

External Service Integrations

Communication & Publishing

  • Slack: Development notifications and alerts
  • Apple News: Automated article publishing
  • Mailchimp: Email marketing and newsletter management

Project tracking

  • Linear: Issues, releases, and backport association. Release workflows sync Linear from git history.

Analytics, screenshots, and protection

  • Parse.ly: Content analytics
  • VIP APM & log shipping: Application performance and centralized logs on VIP
  • Google Analytics: Web analytics and user tracking
  • Cloudflare Turnstile: CAPTCHA and bot protection
  • ScreenshotOne / Cloudflare Browser Rendering: Chart featured-image PNGs via prc-chart-builder (not a VIP Node service)

Development Tools & Workflow

Command Line Tools

# VIP CLI for environment management
npm install -g @automattic/vip
vip dev-env create && vip dev-env start

# Development commands
npm run vip:start        # Start local VIP environment
npm run vip:sync         # Sync database from beta
npm run test             # Run Playwright tests
npm run deploy-manager -- status   # VIP live deploys + Depot CI overlay (see RELEASING.md)
# Plugin docs: use .cursor/skills/prc-plugin-docs (see docs/plugins/README.md)

Development Environment Features

  • Xdebug: PHP debugging with IDE integration
  • Mailpit: Email testing and preview (ports 8025/1025)
  • phpMyAdmin: Database administration interface (port 81)
  • Query Monitor: WordPress debugging and performance analysis
  • WP-CLI: WordPress command-line management

Code Quality & Standards

  • PHP: WordPress VIP coding standards with PHPCS
  • JavaScript/TypeScript: ESLint with WordPress standards
  • CSS/SCSS: Stylelint with BEM methodology
  • Git Hooks: Automated via Husky for pre-commit checks

Configuration Management

Environment Variables

  • Local: vip-env-vars.local.php (git-ignored, generated from 1Password Platform Secrets or PRC_PLATFORM_* env vars via npm run gen:vip-env-vars)
  • Cursor Cloud: Same generators; secrets come from the cloud environment
  • Depot CI: Platform Secrets items tagged depot via .depot/workflows/load-depot-secrets
  • VIP Environments: VIP platform environment variables

Key Configuration Files

  • vip-config/vip-config.php: WordPress and VIP-specific settings
  • vip-config/keys-and-tokens.php: API keys and credentials
  • vip-config/redirects.php: Platform URL redirects and security rules (pre-WordPress)
  • vip-config/server-redirects.php: Allowlist loader for plugin-owned server redirect contributors
  • .wpvip/vip-dev-env.yml: Local development environment config

PRC server redirects

High-traffic string-only redirects that must exit before WordPress boots live in vip-config. Plugins own their rules by committing a pure-PHP contributor file; vip-config loads those files via an explicit allowlist (not a glob).

Contributor path: plugins/prc-<name>/vip-config/server-redirects.php (monorepo). On VIP the same files are served from wp-content/plugins/prc-<name>/vip-config/server-redirects.php. The loader tries both roots.

Contract:

  • Pure PHP only ($_SERVER, $_GET, header(), exit / return)
  • No WordPress APIs, Composer autoload, plugin bootstrap, or ABSPATH
  • Register the relative plugin path + callback in the allowlist in vip-config/server-redirects.php
  • Keep query-aware redirects on template_redirect / Safe Redirect Manager

Current plugin owners:

RuleContributor
/interactives/featureplugins/prc-interactive-features/vip-config/server-redirects.php
/category//topic/plugins/prc-taxonomies/vip-config/server-redirects.php
?s=/search/{term} (+ ep_filter_*)plugins/prc-elasticpress/vip-config/server-redirects.php

Platform spam rules, lowercase normalization, staff/domain collapses stay in vip-config/redirects.php. Editorial / long-tail rules stay in Safe Redirect Manager (vip-config/srm-redirects-import.csv).

Verify contributors with:

npm run audit:server-redirects

Monitoring & Maintenance

Performance Monitoring

  • VIP APM & log shipping: Application performance metrics and centralized logs (production)
  • Query Monitor: Development database and query analysis
  • VIP Dashboard: Infrastructure metrics and alerts

Maintenance Features

  • Maintenance Mode: Site-wide lockdown capability
  • Database Sync: Automated staging-to-local data sync
  • Backup & Recovery: Automated VIP platform backups
  • Health Checks: Automated monitoring and alerting

Security Features

  • Two-Factor Authentication: Required for production access
  • VIP Login Protection: Automated brute force prevention
  • Firewall Rules: Custom security rules in vip-config/firewall.php
  • Spam Protection: Anti-spam redirects and filtering

Network Sites

The platform operates as a WordPress multisite network:

Primary Sites

  • www.[REDACTED] (Site ID: 20) – Main public website
  • platform.[REDACTED]/docs (Site ID: 1) – DocsPress documentation

Local Development URLs

  • Main Site: https://prc-platform.vipdev.lndo.site/pewresearch-org
  • Docs: https://prc-platform.vipdev.lndo.site/docs
  • Network Admin: https://prc-platform.vipdev.lndo.site/wp-admin/network

Troubleshooting & Support

Common Issues

  • Database Sync: Use npm run vip:sync for fresh local data
  • Environment Reset: npm run vip:destroy && npm run vip:start
  • Plugin Conflicts: Check client-mu-plugins/plugin-loader.php load order

Support Contacts

  • Technical Lead: srubenstein@[REDACTED]
  • Chart Technical: bwormald@[REDACTED]
  • Editorial Features (Interactives) Technical: cbaronavski@[REDACTED]

Resources

Was this helpful?