Use Druxt in a Node application
Use Druxt's framework-agnostic clients from plain Node, via the druxt-inspect CLI in the node-client example.
Before you start: this guide assumes a Drupal backend with Druxt enabled (see Getting started) and Node with access to the
druxtpackage.
Everything below Nuxt - DruxtClient, DruxtRouter, DruxtSchema, the Vuex
store modules - is plain, dependency-light JavaScript with no Vue or Nuxt
requirement. The
examples/node-client
package in the druxt.js monorepo proves it: a standalone Node CLI,
druxt-inspect, built directly on druxt and druxt-schema with no
framework in between.
It's a practical backend-inspection tool (and a convenient way for AI agents
to discover a Druxt site's shape via --json), and a reference for using the
clients programmatically in any Node environment.
Installation and setup
The CLI runs straight from the checked-out monorepo - its only dependencies
are the workspace druxt and druxt-schema packages (run yarn build in
the repo root once if packages/*/dist doesn't exist yet):
cd examples/node-client
node bin/druxt-inspect.js --help
Point it at any Druxt-enabled Drupal backend, either with --baseUrl or the
DRUXT_BASE_URL environment variable. The examples in this site assume the
docs/drupal Umami backend on http://127.0.0.1:8888.
Commands
types - list resource types
druxt-inspect -b http://127.0.0.1:8888 types
RESOURCE TYPE ENDPOINT
---------------------------------------------------- --------
action--action .../jsonapi/action/action
block--block .../jsonapi/block/block
block_content--banner_block .../jsonapi/block_content/banner_block
node--recipe .../jsonapi/node/recipe
...
schema <resourceType> - display mode schemas
Prints the Druxt view and form schemas for a resource type and display mode.
These are the same schemas druxt-entity uses to render entities - field
order, labels, formatters, and settings.
druxt-inspect -b http://127.0.0.1:8888 schema node--recipe --mode card
{
"id": "node--recipe--card--view",
"resourceType": "node--recipe",
"fields": [
{ "id": "field_difficulty", "label": { "text": "Difficulty", "position": "hidden" }, "type": "list_default", ... },
{ "id": "field_media_image", "label": { "text": "Media Image", "position": "hidden" }, "type": "entity_reference_entity_view", ... }
]
}
stubs <resourceType> - generate wrapper stubs
Writes the boilerplate for a Druxt Entity wrapper component - one slot per
schema field, named and registered the way DruxtEntity's wrapper resolution
expects. A themed component can start from this and move fields into markup:
druxt-inspect -b http://127.0.0.1:8888 stubs node--recipe --mode card --output components/druxt/entity/node
<template>
<div>
<!-- Difficulty (list_default) -->
<slot name="field_difficulty" />
<!-- Media Image (entity_reference_entity_view) -->
<slot name="field_media_image" />
</div>
</template>
<script>
// Druxt Entity wrapper generated by druxt-inspect for schema 'node--recipe--card--view'.
// See https://druxtjs.org for theming documentation.
import { DruxtEntityMixin } from 'druxt-entity';
export default {
name: 'DruxtEntityNodeRecipeCard',
mixins: [DruxtEntityMixin],
};
</script>
sample <resourceType> - fetch entities
druxt-inspect -b http://127.0.0.1:8888 sample node--recipe --limit 3
UUID LANG LABEL
------------------------------------ ---- -----
62a560b5-1954-4bf7-ba87-609ce73675e0 en Deep mediterranean quiche
67f44980-de26-4567-82f4-b058595720ec en Vegan chocolate and nut brownies
...
views - list Views and displays
Lists the Views exposed by the JSON:API Views module. The displays line is
what a DruxtView component (<DruxtView viewId="recipes" displayId="page_1" />)
or the views--<viewId> resource convention can query.
druxt-inspect -b http://127.0.0.1:8888 views
VIEW LABEL
------------------ -----
archive Archive
displays: block_1, default, page_1
recipes Recipes
displays: block_1, default, page_1
...
--json everywhere
Every command takes --json for machine-readable output - useful for
scripting, and for letting an AI agent discover a site's types, schemas, and
content before writing components against them.
Using the clients programmatically
The CLI is a thin layer over the same classes Nuxt injects for you. In any Node process:
const { DruxtClient } = require('druxt');
const druxt = new DruxtClient('http://127.0.0.1:8888');
// The JSON:API index.
const index = await druxt.getIndex();
// A collection, one page.
const collection = await druxt.getCollection('node--recipe');
// A single resource by UUID, with JSON:API query filtering.
const recipe = await druxt.getResource('node--recipe', uuid, {
'fields[node--recipe]': 'title,field_ingredients',
});
// Every page of a collection.
const collections = await druxt.getCollectionAll('node--recipe');
DruxtClient also accepts an axios instance via options.axios - the same
injection point Nuxt's plugin uses - which is how the CLI's test suite runs
against recorded JSON:API fixtures with zero network access. See
examples/node-client/test/adapter.js for the pattern, and the
DruxtClient API reference for the full method list.
Testing without a backend
examples/node-client includes a Jest suite that replays recorded JSON:API
responses through that axios injection - no Drupal required:
# from the druxt.js repo root
yarn test:node-client
# or from the example itself
cd examples/node-client && yarn test
Fixtures are re-recorded against a live backend only when the data actually
needs to change: cd examples/node-client && DRUXT_BASE_URL=... node test/record.js.