Summary
| Layer | Technology | Repository and Acquia application |
|---|---|---|
| Frontend | Next.js App Router, React, next-intl, Tailwind, standalone output on Node.js | padi.com on padifrontend |
| CMS | Drupal, PHP, MySQL, Memcache | drupal.padi.com on padicom |
| Contract | JSON:API with jsonapi_extras, jsonapi_views and menu items; decoupled_router for path resolution. No GraphQL. | |
| Legacy | Drupal 10 serving www.padi.com until cutover | Legacy Acquia application |
Rendering
- Partial prerendering. Each page is a static shell built ahead of time, with Drupal content streamed into it at request time.
- Build-time prerender of the default locale only. Other locales render on their first request and are then cached at the edge.
- URL shape
/{country}/{language}/…, for example/us/en/coursesor/fr/fr/blog. - Page classes decide edge caching: A (content), A0 (content whose page could not be identified in time, tagged coarsely), B (listings and finder places), C (not found), N (never shared: account, MyPADI, sign-in, search, preview, any request with a session).
- HTML is cached only at Cloudflare. Pages leave the frontend marked
private(no-cachefor shareable pages so the browser can restore them on back and forward,no-storefor personal pages), so Acquia Varnish never stores HTML. Cloudflare reads separateCloudflare-CDN-Cache-Controland environment-prefixedCache-Tagheaders.
Components (C4 level 3)
Page request
An anonymous page view is usually answered by Cloudflare. On a miss, Next.js serves the prebuilt shell and streams content from Drupal, whose JSON:API responses are cached in Varnish.
Publish and purge
Publishing invalidates Drupal cache tags. Varnish is banned by tag and Cloudflare is purged by environment-prefixed tag twice: immediately, and again 6 minutes later to catch servers that rendered from older data. Next.js menus, footers and banners refresh on their own within about a minute.
A frontend deploy invalidates all HTML for its environment. A Drupal deploy purges everything only when code or configuration changed.
Content model
| Group | Members |
|---|---|
| Node types (16) | marketing page, page, article, blog article, blog page, Pros blog article, Pros blog page, ambassadiver, consumer alert, course, FAQ, gear, offer, promo, notification bar, testimonial |
| Paragraph types (34) | Hero banners, carousels, content and information cards, journey cards, MyPADI component, text sections, split and promotional cards, tabs, FAQ, video, gallery, testimonials, statistics, views, library items and others |
| Vocabularies (16) | Blog and Pros blog categories and tags, content category and collection, certification, credential, discipline, equipment, experience level, FAQ category, PADI office, region, tags, ambassadiver hometown |
| Media | Acquia DAM image, video, audio, PDF, document, archive, spinset and generic assets, plus core media types |
| Regions | Domain records www_padi_com (US), uk, australia, japan, padi_com_cn. The go-live model serves the first three. |
| Workflow | One editorial workflow; see Editorial workflow |
Editorial workflow
All 16 node types and 4 block types share one moderation workflow. New content starts as a draft; only the Published state is visible on the site. Most steps send an email notification, and 13 node types can be scheduled to publish or unpublish.
| Role | Can do |
|---|---|
| Content editor, blog author, Pros blog author | Create drafts and submit them for review |
| Global content manager, blog editor, Pros blog editor | Every step: review, send to translation, publish, archive, restore |
| Blog admin | Every step, including publishing straight from initial review |
Send to translate creates Crowdin jobs (Localisation); publishing purges the edge and Varnish caches (Publish and purge).
Resilience in code (C4 level 4)
Runtime switches
Operational switches let the team change behaviour without a code deploy.
| Switch | Values | Production setting | Effect |
|---|---|---|---|
| Edge cache | off, shadow, on | on | Cloudflare caches HTML by page class |
| Edge TTL | 60 s to 3 days | 24 h | Edge lifetime of content and listing pages |
| Coarse invalidation | off, shadow, on | on | Clears all pages of an environment for changes that tags cannot reach |
| Private pages | no-store, no-cache, off | no-cache | Keeps Varnish from storing HTML; shareable pages may be restored from the browser's back and forward cache; personal pages stay no-store |
| Telemetry | 0 or unset | unset (on) | Turns all telemetry off when 0 |
| Load shedding thresholds | numbers | defaults | Returns 503 with Retry-After 5 when a server is saturated |
| Fault injection | fault spec | refused | Used to test resilience on dev and stage |
Three small Node.js preloads ship with the frontend: one exposes metrics for Acquia autoscaling, one sends runtime metrics to Datadog every minute, and one trims response headers because Acquia returns 502 above about 22 KiB of headers.