acquia-source
Connect to an Acquia Source ("Source powered by Drupal CMS") site — its JSON:API and MCP endpoints, OAuth2 auth, the @drupal-canvas CLI, and the Canvas Page API deploy workflow. Use when wiring an AI agent or app to a Source CMS site, building/uploading Drupal Canvas Code Components, deploying landing pages via the Page API, or registering the Source MCP server with Claude Code/Cursor.
What this skill does
# Acquia Source
Acquia Source ("Source powered by Drupal CMS") is a managed SaaS CMS wrapping Drupal CMS 11+ and the **Drupal Canvas** page builder (`drupal.org/project/canvas`, formerly Experience Builder). You don't get server/SSH access or arbitrary contrib — you interact through its **JSON:API**, its **MCP server**, the **Canvas Page API**, and the `@drupal-canvas` CLI. Admin/login at `https://source.acquia.com`.
> Acquia Source is a SaaS product, **not** Acquia Cloud Platform. The `acli` CLI manages Cloud Platform, **not** Source sites — don't reach for it here. Source is driven through the web admin + the APIs below.
## Site identity & credentials
- **CMS URL** looks like `https://<uuid>.cms.acquia.site` (auto-generated at site creation; a custom domain can be mapped later). This base URL is the JSON:API host and the OAuth host.
- **API clients** (OAuth2 client_id/secret) are created in the admin UI under **API → API clients → Add API client**.
- The `@drupal-canvas` CLI reads everything from a local `.env` (never committed):
```
CANVAS_SITE_URL=https://<uuid>.cms.acquia.site
CANVAS_CLIENT_ID=<client_id>
CANVAS_CLIENT_SECRET=<client_secret>
CANVAS_JSONAPI_PREFIX=api # Source serves JSON:API under /api, not the Drupal default /jsonapi
# CANVAS_ACCESS_TOKEN=<token> # optional: a pre-issued Bearer token instead of client credentials
```
## Authentication (OAuth2 via simple_oauth)
- **Token endpoint:** `POST https://<site>/oauth/token`, `Content-Type: application/x-www-form-urlencoded`.
- **Grants:** Authorization Code (user-present), **Client Credentials** (server/agent — use this for automation), Refresh Token.
- **Request header on API calls:** `Authorization: Bearer <access_token>`.
- **Scopes:** content scopes like `content:read` / `content:write` (examples — the full list isn't published); the Canvas CLI needs `canvas:asset_library` and `canvas:js_component`. Enable Client Credentials + add those scopes when creating the API client.
Client-credentials token, by hand:
```bash
curl -s -X POST "$CANVAS_SITE_URL/oauth/token" \
-d grant_type=client_credentials \
-d client_id="$CANVAS_CLIENT_ID" \
-d client_secret="$CANVAS_CLIENT_SECRET" \
-d scope="canvas:asset_library canvas:js_component" | jq -r .access_token
```
## JSON:API
- **Base path is `/api` on Source** (Drupal's default `/jsonapi` is overridden — set `CANVAS_JSONAPI_PREFIX=api`). So a collection is `https://<site>/api/<entity_type>/<bundle>` (e.g. `/api/node/article`).
- Resource types are standard Drupal `{entity_type}--{bundle}` (`node--article`, `media--image`, `taxonomy_term--tags`, …). No Source-proprietary prefix confirmed.
- The admin UI has a **JSON:API Query Builder** (API → JSON:API Query Builder) that generates live queries + code, and per-site **OpenAPI documentation** (API → OpenAPI documentation). Use those to discover exact bundles/fields for a given site.
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
"$CANVAS_SITE_URL/api/node/article?page[limit]=5" | jq '.data[].attributes.title'
```
## MCP server (connect an AI agent)
Acquia Source ships an **MCP server** (HTTP transport, OAuth2 with dynamic client registration). It's **experimental and per-site** — enable it first.
1. **Enable:** admin UI → **Configurations → Experimental features → MCP Server** toggle.
2. **Get the URL:** copy the site's MCP URL from **MCP Client Configuration** in the Source admin (the endpoint URL is provisioned per site; there's no fixed public path to hardcode).
3. **Register in Claude Code:**
```bash
claude mcp add acquia-source-mcp <ACQUIA_SOURCE_SITE_MCP_URL>
```
Then run `/mcp`, select `acquia-source-mcp`, and click **Authenticate** to complete the OAuth flow (dynamic client registration — no manual client_id needed).
**What it exposes** (read-only resources + write tools, via `drupal://` and `canvas://` URIs):
- **Content Management** — content types, media types, vocabularies, text formats; create/update nodes, media, taxonomy terms.
- **Content Modeling** — field storages, field types; create content types and add fields.
- **Drupal Canvas** — components and pages; manage layouts and component properties.
Prefer the MCP server over hand-rolled JSON:API calls when an agent needs to *model content or edit Canvas layouts conversationally*; use JSON:API/the Page API for deterministic, scripted deploys.
## Canvas Code Components — CLI workflow
Scaffold and manage React/JSX Code Components with the official tooling (install the [official Canvas skills](https://github.com/drupal-canvas/skills) for the component-authoring rules — don't reinvent them):
- `npx @drupal-canvas/create@latest` — scaffold a codebase (default template: [acquia/nebula](https://github.com/acquia/nebula), which ships `AGENTS.md` + `SETUP.md` with the Page API reference and pitfalls).
- `npx canvas download` / `npx canvas upload -c <comp1,comp2> -y` — pull/push components between repo and site. `canvas.config.json` (committed) defines structure; `.env` (uncommitted) holds the secrets above.
## Canvas Page API — deploying a page
Pages are built by uploading components, then PATCHing the page with a full component tree. The hard-won rules (these cost hours otherwise):
- **Each PATCH replaces the ENTIRE page.** Never build incrementally with multiple PATCHes — assemble the complete component tree and send it in one atomic request.
- **Version hashes change on every upload.** Re-discover all component version hashes after each `canvas upload`; never hardcode them. Only changed components get new hashes.
- **`FormattedText` strips inline `style` attributes** on the live site (works in Storybook, fails live). For text alignment add a `layout` prop (`left_aligned`/`center_aligned`/`right_aligned`) with CVA variants — never inline `style="text-align:…"`.
- **The `Image` component needs Drupal media-pipeline URLs** (with `alternateWidths`). External URLs / data URIs are accepted without error but render as **invisible 0×0 images** live. For logos use inline SVG/text; for content images upload as Drupal media first.
- **No raw hex colors as props** — use CVA variants mapped to Tailwind theme tokens in `global.css`.
- **Padding stacks:** `section` adds `px-4`, `grid_container` adds `px-6` → ~80px on a 375px screen. Use responsive prefixes (`px-0 md:px-6`) on inner containers.
- **Empty slot containers** need `min-w-*`/`min-h-*` so they stay interactive in the Canvas editor.
- Deploy script pattern: read `.env` → client-credentials token → discover all version hashes in one pass → build the tree (parents before children, fresh UUID per instance, `inputs` as a `json.dumps()` string) → single PATCH. Keep a `VERSIONS` dict at the top.
## Docs
- Overview: https://docs.acquia.com/acquia-source/overview
- API integration (JSON:API): https://docs.acquia.com/acquia-source/api-integration
- Access & authentication (OAuth2): https://docs.acquia.com/acquia-source/access-and-authentication
- MCP server: https://docs.acquia.com/acquia-source/acquia-source-mcp-server
- Creating custom components (CLI): https://docs.acquia.com/acquia-source/creating-custom-components
- JSON:API Query Builder: https://docs.acquia.com/acquia-source/jsonapi-query-builder
- Official Canvas component skills: https://github.com/drupal-canvas/skills · starter template: https://github.com/acquia/nebula
Related in Ads & Marketing
ads
IncludedMulti-platform paid advertising audit and optimization skill. Analyzes Google, Meta, YouTube, LinkedIn, TikTok, Microsoft, and Apple Ads. 250+ checks with scoring, parallel agents, industry templates, and AI creative generation.
banana
IncludedAI image generation Creative Director powered by Google Gemini Nano Banana models. Use this skill for ANY request involving image creation, editing, visual asset production, or creative direction. Triggers on: generate an image, create a photo, edit this picture, design a logo, make a banner, visual for my anything, and all /banana commands. Handles text-to-image, image editing, multi-turn creative sessions, batch workflows, and brand presets.
rpg-migration-analyzer
IncludedAnalyzes legacy RPG (Report Program Generator) programs from AS/400 and IBM i systems for migration to modern Java applications. Extracts business logic from RPG III/IV/ILE source code, identifies data structures (D-specs), file operations (F-specs), program dependencies (CALLB/CALLP), and converts RPG constructs to Java equivalents. Generates migration reports, complexity estimates, and Java implementation strategies with POJO classes, JPA entities, and service methods. Use when modernizing AS/400 or IBM i legacy systems, analyzing RPG source files (.rpg, .rpgle, .RPGLE), converting RPG to Java, mapping data specifications to Java classes, planning legacy system migration, or when user mentions RPG analysis, Report Program Generator, RPG III/IV/ILE, AS/400 modernization, IBM i migration, packed decimal conversion, or mainframe application rewrite.
brand-library-architect
IncludedBuild a complete brand library for a product — visual asset render pipeline, brand documentation set (BRAND, COPY, MANIFESTO, BIOS, FAQ, GLOSSARY, TONE, PRICING), open-source convention files (README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT), and a self-contained press kit. This skill should be used when the user asks to "build a brand library / brand kit / press kit / brand assets" for a product, "set up a brand library workflow," "create a positioning manifesto plus visual identity," or any combination of brand documentation + visual asset pipeline. Apply phase-by-phase or run end-to-end. Templates are product-agnostic and use {{TOKEN}} placeholders the skill prompts the user to fill.
writing-tech-post
IncludedAuthors engineering blog posts end-to-end: launch deep-dives, incident postmortems, architecture migrations, performance case studies, tutorials, AI/agent system writeups, security disclosures, and research-to-product translations. Picks the correct archetype, plans the abstraction ladder, enforces an evidence cadence (diagrams, benchmarks, profiles, traces, code, ablations), tunes voice against publisher house styles (Datadog, Vercel, GitHub, AWS, Meta, Cloudflare, Jane Street), and runs a pre-publish gate for narrative momentum and disclosure ethics. Use when drafting a new engineering post, restructuring a draft that feels flat, deciding which evidence form belongs where, validating that depth and product context are balanced, or preparing a postmortem, migration, or performance narrative for external publication. Do not use for API reference documentation, README authoring, marketing copy, release notes, generic SEO content, ghost-written executive thought leadership, or non-engineering long-form essays.
blog-google
IncludedGoogle API integration for blog performance: PageSpeed Insights, CrUX Core Web Vitals with 25-week history, Search Console performance, URL Inspection, Indexing API, GA4 organic traffic, NLP entity analysis for E-E-A-T, YouTube video search for embedding, and Google Ads Keyword Planner. Progressive feature availability based on credential tier (API key, OAuth/service account, GA4, Ads). Shares config with claude-seo at ~/.config/claude-seo/google-api.json. Use when user says "google data", "page speed", "core web vitals", "search console", "indexation", "GA4", "keyword research", "nlp entities", "blog performance", "youtube search", "google api setup".