From drupal-boost
REST and JSON:API endpoint development in Drupal 11 including custom REST resources, JSON:API customization, authentication, input validation, and decoupled architecture patterns. Use when building APIs, decoupled frontends, or custom REST endpoints.
npx claudepluginhub abderrahimghazali/drupal-boostThis skill is limited to using the following tools:
JSON:API is enabled by default. Endpoints follow the pattern:
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
JSON:API is enabled by default. Endpoints follow the pattern:
/jsonapi/{entity_type_id}/{bundle_id}
/jsonapi/{entity_type_id}/{bundle_id}/{uuid}
GET /jsonapi/node/article # List articles
GET /jsonapi/node/article/{uuid} # Get single article
POST /jsonapi/node/article # Create article
PATCH /jsonapi/node/article/{uuid} # Update article
DELETE /jsonapi/node/article/{uuid} # Delete article
/jsonapi/node/article?filter[status]=1
/jsonapi/node/article?sort=-created
/jsonapi/node/article?include=uid,field_tags
/jsonapi/node/article?fields[node--article]=title,body
/jsonapi/node/article?page[limit]=10&page[offset]=0
{
"data": {
"type": "node--article",
"attributes": {
"title": "My Article",
"body": {
"value": "<p>Content</p>",
"format": "basic_html"
}
},
"relationships": {
"uid": {
"data": { "type": "user--user", "id": "USER_UUID" }
}
}
}
}
For non-entity data or complex business logic:
namespace Drupal\MODULE_NAME\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
#[RestResource(
id: "my_resource",
label: new TranslatableMarkup("My Resource"),
uri_paths: [
"canonical" => "/api/my-resource/{id}",
"create" => "/api/my-resource",
]
)]
class MyResource extends ResourceBase {
public function get(string $id): ResourceResponse {
$data = ['id' => $id, 'message' => 'Hello'];
$response = new ResourceResponse($data, 200);
$response->addCacheableDependency(CacheableMetadata::createFromRenderArray([
'#cache' => ['max-age' => 3600],
]));
return $response;
}
public function post(array $data): ModifiedResourceResponse {
// Validate and process $data
return new ModifiedResourceResponse($result, 201);
}
}
Enable via REST UI module or config:
# rest.resource.my_resource.yml
id: my_resource
plugin_id: my_resource
granularity: resource
configuration:
methods: [GET, POST]
formats: [json]
authentication: [cookie, basic_auth, oauth2]
basic_auth module)simple_oauth contrib module)GET /session/token → returns token string
POST /jsonapi/node/article
X-CSRF-Token: {token}
Content-Type: application/vnd.api+json
For non-RESTful endpoints:
class ApiController extends ControllerBase {
public function data(): JsonResponse {
return new JsonResponse(['status' => 'ok']);
}
}
Route:
MODULE_NAME.api_data:
path: '/api/data'
defaults:
_controller: '\Drupal\MODULE_NAME\Controller\ApiController::data'
requirements:
_permission: 'access content'
options:
_format: json
->accessCheck(TRUE) on all entity queries in custom endpointsjsonapi_resource_config to limit