diff --git a/README.md b/README.md index f52b3e7..4c726cf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ # Catholic Digital Commons Foundation — Website CMS +[![Next.js](https://img.shields.io/github/package-json/dependency-version/CatholicOS/cdcf-website/next?label=Next.js&logo=nextdotjs&color=000000)](https://nextjs.org) +[![React](https://img.shields.io/github/package-json/dependency-version/CatholicOS/cdcf-website/react?label=React&logo=react&color=61DAFB&logoColor=white)](https://react.dev) +[![TypeScript](https://img.shields.io/github/package-json/dependency-version/CatholicOS/cdcf-website/dev/typescript?label=TypeScript&logo=typescript&color=3178C6&logoColor=white)](https://www.typescriptlang.org) +[![Tailwind CSS](https://img.shields.io/github/package-json/dependency-version/CatholicOS/cdcf-website/dev/tailwindcss?label=Tailwind%20CSS&logo=tailwindcss&color=06B6D4&logoColor=white)](https://tailwindcss.com) +[![PR Build](https://github.com/CatholicOS/cdcf-website/actions/workflows/pr-build.yml/badge.svg?branch=main)](https://github.com/CatholicOS/cdcf-website/actions/workflows/pr-build.yml) + The official website for the **Catholic Digital Commons Foundation (CDCF)**, built with Next.js and headless WordPress. This site serves as the public-facing portal for the foundation, showcasing projects, community resources, news, and governance information. ## Tech Stack -- **Framework:** Next.js 15 (App Router, React Server Components) +- **Framework:** Next.js 16 (App Router, React Server Components) - **CMS:** WordPress (headless) with WPGraphQL + ACF + Polylang - **Styling:** Tailwind CSS v4 + custom CDCF brand system - **i18n:** next-intl (UI chrome) + Polylang (CMS content) @@ -289,32 +295,70 @@ You can set this up as a WordPress publish hook (e.g. via the WP Webhooks plugin ## Deployment -### Production Architecture +### Production and Staging Architecture -Production runs natively on a Plesk-managed server (no Docker) with two subdomains: +Production and staging both run natively on the same Plesk-managed server (no Docker) on three subdomains: -- **`catholicdigitalcommons.org`** — Next.js frontend (standalone build running via Node.js) +- **`catholicdigitalcommons.org`** — production Next.js frontend (standalone build, Node.js) +- **`staging.catholicdigitalcommons.org`** — staging Next.js frontend (separate standalone build, same Node.js) - **`cms.catholicdigitalcommons.org`** — WordPress admin backend (PHP-FPM managed by Plesk) -WordPress and Next.js share the same MariaDB instance already running on the server. Plesk manages Nginx, SSL certificates, and PHP-FPM. +**Staging shares the production WordPress backend.** That keeps the staging environment lightweight (no second WP install or DB), but it also means staging-only theme/plugin testing isn't possible — both environments see the same CMS code at any moment. The deploy workflow only ships the Next.js bundle to staging for that reason. + +`proxy.ts` sets `X-Robots-Tag: noindex, nofollow` on every response from any host other than `catholicdigitalcommons.org` / `www.catholicdigitalcommons.org`, so staging (and any preview / one-off subdomain) is never indexed by search engines. + +The Next.js apps fetch content from WordPress via `WP_GRAPHQL_URL=https://cms.catholicdigitalcommons.org/graphql`. The WordPress theme's CORS headers (registered in `functions.php`) allow cross-origin GraphQL requests from both the production and staging frontends. -The Next.js app fetches content from WordPress via `WP_GRAPHQL_URL=https://cms.catholicdigitalcommons.org/graphql`. The WordPress theme's CORS headers (registered in `functions.php`) allow cross-origin GraphQL requests from the frontend subdomain. +Per-environment runtime env vars (`WP_GRAPHQL_URL`, `WP_PREVIEW_SECRET`, etc.) are configured in the **Plesk panel** for each Node.js app, not in `.env.local` files on disk. `NEXT_PUBLIC_SITE_URL` is per-environment too but is **baked into the client bundle at build time** (different value per workflow run, see below). ### GitHub Actions CI/CD -The deploy workflow (`.github/workflows/deploy.yml`) triggers when a GitHub release is published. It builds the Next.js standalone output in CI, then SCPs the artifacts to the VPS (no repo clone needed on the server). +The deploy workflow (`.github/workflows/deploy.yml`) is unified for both environments: + +- **`release: published`** — automatically deploys to **production** +- **`workflow_dispatch`** — user picks `production` or `staging` (default: `staging`) + +Production-only steps (WP theme + plugin tarballs, plugin activation) are gated behind an environment check. Staging deploys ship only the Next.js bundle so they can't overwrite production WordPress code. -**Required GitHub Secrets:** +**Triggering deploys from the command line** (no UI dropdown needed): + +```bash +# Deploy to staging (matches the dropdown default) +gh workflow run deploy.yml --ref main -f environment=staging + +# Deploy to production +gh workflow run deploy.yml --ref main -f environment=production + +# No -f → uses the workflow default (staging) +gh workflow run deploy.yml --ref main +``` + +A separate workflow (`.github/workflows/pr-build.yml`) runs `next build` on every pull request as a required check, so build-only failures (file-name conflicts, missing imports, type errors) are caught pre-merge instead of at deploy time. + +**Required GitHub repository configuration:** + +Secrets (encrypted, used as credentials): | Secret | Description | |--------|-------------| -| `WP_GRAPHQL_URL` | WordPress GraphQL endpoint (e.g. `https://cms.catholicdigitalcommons.org/graphql`) | -| `WP_PREVIEW_SECRET` | Shared secret for preview/revalidation | | `VPS_HOST` | VPS IP address or hostname | | `VPS_USERNAME` | SSH username | | `VPS_SSH_KEY` | SSH private key for deployment | -| `VPS_APP_DIR` | Directory on the VPS where the Next.js standalone app runs | -| `WP_THEME_DIR` | WordPress theme directory (e.g. `/var/www/vhosts/.../wp-content/themes/cdcf-headless`) | +| `WP_APP_USERNAME` | WordPress application-password username (for plugin activation) | +| `WP_APP_PASSWORD` | WordPress application password | + +Variables (plain config, visible in workflow logs): + +| Variable | Description | +|----------|-------------| +| `WP_GRAPHQL_URL` | WordPress GraphQL endpoint (e.g. `https://cms.catholicdigitalcommons.org/graphql`) | +| `WP_REST_URL` | WordPress REST root (e.g. `https://cms.catholicdigitalcommons.org/wp-json`) | +| `NEXT_PUBLIC_SITE_URL_PROD` | Public URL of the production site (e.g. `https://catholicdigitalcommons.org`) | +| `NEXT_PUBLIC_SITE_URL_STAGING` | Public URL of the staging site (e.g. `https://staging.catholicdigitalcommons.org`) | +| `VPS_APP_DIR` | Production Next.js app directory on the VPS | +| `VPS_STAGING_APP_DIR` | Staging Next.js app directory on the VPS | +| `WP_THEME_DIR` | WordPress theme directory (e.g. `/var/www/vhosts/.../wp-content/themes`) | +| `WP_PLUGINS_DIR` | WordPress plugins directory (e.g. `/var/www/vhosts/.../wp-content/plugins`) | ### Docker (Local Development Only)